Fast.Cache
版本 3.5.33;目标 net8.0、net9.0、net10.0;依赖 Fast.Runtime、CSRedisCore。这是 Redis 客户端封装,注册成功不代表连接可用。
dotnet add package Fast.Cache注册与配置
services.AddCache(string section = "RedisSettings") 注册 ICache 及被发现的 ICache<TLocator> 单例。另一个重载接受 Action<RedisSettingsOptions>,默认连接直接配置在选项上,命名连接写入 Services。
当前列表回调已经绑定到缓存实现读取的 IOptionsMonitor<RedisSettingsOptions>;第一项为默认配置,后续具名项进入 Services。配置节点和回调最终使用相同选项类型。
| 选项 | 后配置默认值 |
|---|---|
ServiceIp | 127.0.0.1 |
Port | 6379 |
DbName | 0 |
Poolsize | 100 |
SSL | false |
DbPwd、Prefix | 无默认值 |
Services | 空列表;条目类型 RedisServiceSettingsOptions,额外包含 ServiceName |
ICacheContextLocator 用于配置定位;DefaultCacheContextLocator 为默认定位器。自定义泛型定位器须满足 new() 约束,ServiceName 用于匹配 Services 条目,未找到对应服务会抛 InvalidOperationException。生产配置由宿主注入,不将密码写入示例或仓库。
ICache 与 ICache<TLocator>
| API 家族 | 参数与返回 |
|---|---|
Prefix、Client、ContextLocator | 分别提供前缀、底层 CSRedisClient 与定位器 |
Get/Get<T>、GetAsync/GetAsync<T> | 按键读取字符串或指定类型;异步返回 Task<string> / Task<T> |
Exists/ExistsAsync | 按键判断存在,返回 bool / Task<bool> |
Set/SetAsync | (key, object value)、追加 int expireSeconds 或 TimeSpan expireTimeSpan 三组重载;返回写入成功标志 |
GetAndSet/GetAndSet<T> | 缺失时调用同步值工厂并缓存;可指定秒数或 TimeSpan |
GetAndSetAsync/GetAndSetAsync<T> | 工厂为 Func<Task<string>> / Func<Task<T>>;需等待返回任务 |
Del/DelAsync(params string[] key) | 返回实际删除数 long / Task<long> |
DelByPattern/DelByPatternAsync | 按模式扫描并删除,返回实际删除数;不是廉价的单键操作 |
GetAllKeys/GetAllKeysAsync | 返回 List<string> / 对应任务;扫描数据库,避免高频调用 |
下面是消费代码结构,不在文档检查时连接 Redis:
using Fast.Cache;
public sealed class LabelReader(ICache cache)
{
public Task<string> ReadAsync(string key) => cache.GetAsync(key);
}缺失值与对象序列化由底层客户端行为共同决定,调用方应处理空结果。GetAndSet 不是分布式锁或去重保证,不能依赖它只执行一次业务副作用。网络和序列化异常需由消费端处理。
Program.cs 与缓存消费者
使用 Microsoft.NET.Sdk.Web,目标为本页列出的 .NET 8/9/10。宿主从外部配置提供 RedisSettings;不要把连接凭据写入代码。以下是完整的注册与调用关系,启动后调用端点才会进行缓存 I/O。
using Fast.Cache;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCache();
builder.Services.AddScoped<CatalogCache>();
var app = builder.Build();
app.MapGet("/catalog/{id:int}", (int id, CatalogCache cache) => cache.ReadAsync(id));
app.Run();
public sealed record CatalogItem(int Id, string Name);
public sealed class CatalogCache(ICache cache)
{
public Task<CatalogItem> ReadAsync(int id) => cache.GetAndSetAsync(
$"catalog:{id}", TimeSpan.FromMinutes(5),
() => Task.FromResult(new CatalogItem(id, "示例商品")));
public Task<bool> ReplaceAsync(CatalogItem item) =>
cache.SetAsync($"catalog:{item.Id}", item, TimeSpan.FromMinutes(5));
public Task<long> InvalidateAsync(int id) => cache.DelAsync($"catalog:{id}");
}GetAndSetAsync 的返回值是缓存中的对象或工厂结果;示例工厂为本地固定数据,实际应用可替换为读取服务。不要依赖它实现跨进程互斥或防止并发重复计算。SetAsync 返回成功标志,DelAsync 返回实际删除数量;删除不存在的键不等于异常。Redis、序列化与工厂异常可传播给调用方,此接口没有统一的取消令牌参数。
来源与验证
依据 ICache 完整重载、选项。本轮未编译、未连接或写入 Redis。
委托配置、客户端切换与原子消费
列表回调的第一项配置默认 Redis,后续项必须为具有唯一 ServiceName 的 RedisServiceSettingsOptions;它们共同绑定到实际消费的 IOptionsMonitor<RedisSettingsOptions>。空列表、重复名称和无名称附加项会明确失败。该调整没有连接或写入 Redis 的测试副作用。
配置变化时先创建新客户端,再原子发布不可变快照。新建失败保留旧客户端,并记录不含连接信息的诊断;一次缓存操作始终使用同一个客户端和 Prefix。公开 Client 是借用引用,不由调用方 Dispose。由于无法追踪外部借用者,旧代客户端保留至缓存服务释放;频繁热更新可能保留多个连接池,不承诺无限热更新而无资源成本。
注册 Fast.Cache 同时提供 Redis 原子刷新消费存储器;这是专门的防重放能力,不意味着普通 GetAndSet 也具有分布式互斥。
