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" />
<PackageReference Include="RLei.PgCache" />
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
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#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
#tool nuget:?package=RLei.PgCache&version=1.0.1
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
RLei.PgCache
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 | Versions 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.
-
net10.0
- DapprWire.MicrosoftExtensions (>= 1.1.0)
- Microsoft.Extensions.DependencyInjection (>= 10.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.0)
- Npgsql (>= 10.0.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.