ConnectionMultiplexer 初始化必须异步+延迟加载+显式超时,禁用同步Connect();连接字符串需设connectTimeout=2000,syncTimeout=1000且AbortOnConnectFail=false;IDatabase操作需注意RedisValue判空、批量用MGET/Pipeline、对象存取优先Hash。

别用 ConnectionMultiplexer.Connect() 同步阻塞初始化,也别每次操作都 new 一个连接对象——这会直接拖垮 ASP.NET Core 启动速度,甚至在 Redis 临时不可达时让整个服务 hang 住。
ConnectionMultiplexer 初始化必须异步 + 延迟加载 + 显式超时
默认 Connect() 在 DNS 解析失败、端口不通时会卡死 5 秒(实际是 connectTimeout=5000),而 ConnectAsync() 才是真正可控的入口。同步调用在 Web 应用启动阶段极易引发线程池饥饿。
- 必须用
Lazy<ConnectionMultiplexer>或IServiceProvider注册单例,禁止在业务方法里new ConnectionMultiplexer(...) - 连接字符串里硬编码
connectTimeout=2000,syncTimeout=1000,避免依赖默认值 -
AbortOnConnectFail=false是保命参数:首次连不上不抛异常,后续自动重试;设为true(默认)会导致应用启动失败 - Docker 或云环境务必把
localhost换成真实 IP 或服务名,且确认宿主机能 ping 通、防火墙放行 6379 端口
IDatabase.StringGet 返回值不是 string,是 RedisValue 结构体
StringGet("key") 返回 RedisValue,它隐式转 string 时,对不存在的 key 会返回空字符串,而不是 null —— 这会让你误判“缓存命中”,实际是 key 不存在。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 判断 key 是否存在,只认
if (!value.IsNull),别用value == null、string.IsNullOrEmpty(value)或value.ToString() == "" - 想存 null 字符串?
StringSet("k", null)静默失败(返回false),得传RedisValue.Null才能触发 DEL 行为 - 反序列化前先检查
value.HasValue,否则JsonConvert.DeserializeObject<T>(value)会炸在空值上
批量读写必须用 MGET / Pipeline,别手写 for 循环
连续调用 10 次 StringGet("k1")、StringGet("k2")… 是 10 次网络往返(RTT),哪怕它们在同一台机器上。真正省时间的方式只有两种:
- 同类型批量:用
StringGet(new RedisKey[] { "k1", "k2", "k3" })→ 底层走 Redis 的MGET命令,1 次 RTT 拿回全部 - 跨类型或带逻辑:用
db.ScriptEvaluate(luaScript, keys, values),把“查 A → 若存在则删 B → 再设 C”这种原子操作压进 Lua,否则 CAS 场景下必现竞态 - 别在循环里反复调用
GetDatabase():它开销极小,但不如提前存个局部变量var db = Connection.GetDatabase()
序列化对象别自己拼 JSON 字符串塞 StringSet
直接 StringSet("user:1001", JsonConvert.SerializeObject(user)) 看似简单,但埋了三个坑:UTF-8 字节长度 vs 字符串长度歧义、JSON 序列化器配置不一致、无法部分更新字段。
- 优先用 Hash:用
HashSet("user:1001", new HashEntry[] { new("name", "Alice"), new("age", "30") }),字段可单独读写 - 若必须存整个对象,封装一层
JsonSerializer,统一控制NullValueHandling和日期格式,别裸用JsonConvert - 注意:HashGetAll 返回的是
HashEntry[],不是字典,遍历时要自己.ToDictionary(x => x.Name, x => x.Value)
最易被忽略的一点:GetDatabase() 永远成功,即使 Redis 完全宕机;真正的失败点在第一次执行 StringGet() 或 KeyExists() 时才暴露——所以健康检查不能只看连接对象是否创建成功,得真发一条 PING 命令。

















