RLei.PgCache 1.0.1

dotnet add package RLei.PgCache --version 1.0.1
                    
NuGet\Install-Package RLei.PgCache -Version 1.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="RLei.PgCache" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RLei.PgCache" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="RLei.PgCache" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add RLei.PgCache --version 1.0.1
                    
#r "nuget: RLei.PgCache, 1.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package RLei.PgCache@1.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=RLei.PgCache&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=RLei.PgCache&version=1.0.1
                    
Install as a Cake Tool

RLei.PgCache

NuGet License

RLei.PgCache 是一个基于 PostgreSQL 的轻量级 .NET 分布式缓存库,使用 JSONB 存储、PL/pgSQL 函数驱动。


为什么用 PG 做缓存?VS Redis

适用场景(推荐使用 RLei.PgCache)

  • 小团队 / 小项目:不想维护 Redis 集群,项目已经用 PG,加个表就能缓存
  • 缓存与业务数据需要事务一致性:同一个数据库,写入缓存和业务操作可以在同一个事务里完成
  • 降低运维成本:零额外服务依赖,无需监控 Redis 内存、持久化、淘汰策略
  • 部署环境受限:某些内网环境不允许装 Redis,但 PG 是标配

不适用场景(建议用 Redis)

场景 原因
高性能缓存 PG 磁盘 IO 延迟远高于 Redis 内存操作
高并发读写 Redis 单机 QPS 10万+,PG 难以企及
自动淘汰策略 Redis 有 LRU/LFU/TTL 自动驱逐,PgCache 只有 TTL + 定时清理
丰富数据结构 Redis 有 List/Set/SortedSet/HyperLogLog,PgCache 仅 JSONB
大规模缓存 PG 表数据量过大会影响查询性能,Redis 专为缓存设计

RLei.PgCache 定位是轻量级缓存方案,不是 Redis 替代品。适合项目已用 PG、缓存需求简单、不想引入额外中间件的场景。


功能特性

  • 泛型 API,零序列化样板代码:直接存对象、取对象,无需手动序列化
  • 内置 GetOrSetAsync:缓存穿透保护,工厂模式一行搞定
  • TTL 过期支持:精确到秒,null 表示永不过期
  • UNLOGGED:跳过 WAL 日志,写入性能接近 Redis
  • 双模式过期清理:优先 pg_cron,不可用时自动回退到进程内 PeriodicTimer
  • 完整参数校验:所有 public 方法对 key/value 做空值检查,拒绝脏数据入库
  • 自定义 JsonSerializerOptions:支持 camelCase 命名策略等
  • 开箱即用:一键注册,自动建表、建函数、启动清理

安装

dotnet add package RLei.PgCache

IDistributedCache 方案的核心差异

.NET 生态中已有多个 PG 缓存库(含微软官方 Microsoft.Extensions.Caching.Postgres),但它们都走 IDistributedCache 接口 —— 只能存 byte[],调用方自行处理序列化

// IDistributedCache:先序列化再存,取出来再反序列化
var bytes = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(obj));
await cache.SetAsync("key", bytes);
var result = JsonSerializer.Deserialize<MyClass>(await cache.GetAsync("key"));

RLei.PgCache 的 IPgCache 是泛型接口,直接操作对象:

// RLei.PgCache:像操作本地变量一样用缓存
await cache.SetAsync("key", obj);
var result = await cache.GetAsync<MyClass>("key");

功能对比

能力 IDistributedCache IPgCache
存储类型 byte[],需自行序列化 泛型 <T>,内置 System.Text.Json
GetOrSetAsync(缓存穿透保护) ❌ 需自己实现 ✅ 内置
KeyExistsAsync ❌ 需自己实现 ✅ 内置
DeleteAsync 返回是否删除成功 ❌ 只删除,不返回 ✅ 返回 bool
参数校验 ❌ 需调用方确保 ✅ 自动检查,拒绝空 key/空值
使用代码量 多(序列化模板代码)

快速开始

1. 注册服务

// Program.cs
builder.Services.AddPgCache(
    "Host=localhost;Port=5432;Database=mydb;Username=postgres;Password=123456");

默认自动初始化数据库(创建 schema、表、函数)并启动过期清理服务。

如果不想自动初始化(例如由 DBA 手动执行 SQL):

builder.Services.AddPgCache(connectionString, initializeDatabase: false);

2. 使用缓存

public class MyService(IPgCache cache)
{
    public async Task DoSomethingAsync()
    {
        // 存 —— 直接传对象
        await cache.SetAsync("user:1", new { Name = "Alice", Age = 30 }, expireSeconds: 60);

        // 取 —— 直接指定类型
        var user = await cache.GetAsync<User>("user:1");

        // 检查是否存在
        if (await cache.KeyExistsAsync("user:1")) { /* 命中 */ }

        // 缓存穿透保护 —— 缓存命中直接返回,未命中执行 factory 并自动回填
        var data = await cache.GetOrSetAsync("key", async () =>
        {
            return await FetchExpensiveDataAsync();
        }, expireSeconds: 300);

        // 删除 —— 同时知道有没有删掉
        var deleted = await cache.DeleteAsync("user:1");
    }
}

API 参考

IPgCache 接口

方法 说明 参数校验
GetAsync<T>(key) 获取缓存值,不存在返回 default key 为空/空白抛出 ArgumentException
SetAsync(key, value, expireSeconds?) 设置缓存,expireSeconds 为 null 表示永不过期 key/value 为空抛出异常
DeleteAsync(key) 删除缓存,返回 true 表示 key 存在且已删除 key 为空/空白抛出 ArgumentException
KeyExistsAsync(key) 检查 key 是否存在且未过期 key 为空/空白抛出 ArgumentException
GetOrSetAsync<T>(key, factory, expireSeconds?) 获取或创建,factory 仅在缓存不存在时执行 key/factory 为空抛出异常

PgCacheOptions

属性 类型 说明
PgCronAvailable bool pg_cron 是否可用,由 DatabaseInitializer 自动检测

配置

自定义 JSON 序列化

// 注册全局 JsonSerializerOptions(可选)
builder.Services.Configure<JsonSerializerOptions>(options =>
{
    options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});

// AddPgCache 会自动注入
builder.Services.AddPgCache(connectionString);

跳过数据库自动初始化

builder.Services.AddPgCache(connectionString, initializeDatabase: false);

适用场景:

  • 数据库初始化由 DBA 手动执行 Scripts/cache_init.sql
  • 只想在部署时初始化一次,而非每次启动都执行
  • 只读副本不需要执行初始化

过期清理机制

方式 触发 要求
pg_cron 扩展 PostgreSQL 内置调度,每 5 分钟 需要 PostgreSQL 超级用户权限
CacheCleanupService 进程内 PeriodicTimer,每 5 分钟 无额外依赖(默认 fallback)

DatabaseInitializer 启动时优先尝试安装 pg_cron,失败则自动回退到进程内清理。


数据库架构

库会在 basic schema 下自动创建以下对象:

  • cache_store — UNLOGGED 表,JSONB 存储
  • 函数 cache_get — 获取缓存(带过期检查)
  • 函数 cache_set — 设置缓存(支持 UPSERT + TTL)
  • 函数 cache_del — 删除缓存
  • 函数 cache_exists — 检查 key 是否存在
  • 函数 cache_cleanup — 批量清理过期数据
  • 索引 idx_cache_expires — 过期时间条件索引

依赖

版本
DapprWire.MicrosoftExtensions 1.1.0+
Npgsql 10.0+
Microsoft.Extensions.DependencyInjection 10.0+
Microsoft.Extensions.Hosting.Abstractions 10.0+

目标框架

  • .NET 10.0+

License

MIT

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 124 7/9/2026
1.0.0 115 7/9/2026