发布于2026-07-19 阅读(0)
扫一扫,手机访问
记住几个关键点:使用最新版 StackExchange.Redis(2.7.x+),ConnectionMultiplexer单例复用,显式配置abortConnect=false,对象存取必须手动序列化,并发更新优先用 Lua 脚本,Docker 环境里注意 DNS 和网络配置。这些做好了,基本不会踩坑。

直接用 StackExchange.Redis 就好,别碰过时的 ServiceStack.Redis,也别用 StackExchange.Redis 的 1.x 低版本——不然连接泄漏、异步死锁、序列化兼容性问题会让你头疼到怀疑人生。
NuGet 里装最新稳定版 StackExchange.Redis(目前是 2.7.x+),注意别装 StackExchange.Redis.StrongName,那个已经废弃了。
连接字符串建议把关键参数写清楚,别指望默认值能帮你兜底:
abortConnect=false:启动时如果连不上,别直接抛异常挂掉,先忍着connectTimeout=5000:5 秒超时,太短容易失败,太长拖慢服务启动syncTimeout=3000:同步操作的上限时间,防止线程池被阻塞allowAdmin=true:只在开发或调试时开,生产环境别开,不然执行 FLUSHDB 这种命令就太危险了强烈推荐用 ConnectionMultiplexer 单例复用,不要每次 new 一个——它自己线程安全,内部管理连接池,你用 Lazy 或者 DI 容器注册成 Singleton 都行:
private static readonly LazyLazyConnection = new Lazy (() => ConnectionMultiplexer.Connect("localhost:6379,abortConnect=false,connectTimeout=5000"));
StackExchange.Redis 默认只认 byte[],你直接丢一个 string 或自定义类进去,它就会抛出 System.NotSupportedException: The collection type 'System.Collections.Generic.List`1' is not supported. 这种错误。别慌,序列化必须自己来。
推荐用 System.Text.Json(.NET Core 3.0+ 或 .NET 5+ 默认就有):
db.StringSet("user:1001", JsonSerializer.Serialize(user))var json = db.StringGet("user:1001"); var user = JsonSerializer.Deserialize(json!) 注意:如果项目强依赖 Newtonsoft.Json,也可以用 JsonConvert.SerializeObject,但必须确保所有属性 public 可读写,且没有循环引用。否则一样会炸。
千万别用“先 GET 再 SET”这种两步操作——竞态条件百分之百会发生。Redis 原生的 DECR、INCR、GETSET 都是原子的,但 C# 封装里要借助 IServer 或 Lua 脚本才能保证原子性。
最推荐的是 Lua 脚本,多条命令打包执行,原子性有保障:
var script = @"
if redis.call('GET', KEYS[1]) >= ARGV[1] then
return redis.call('DECRBY', KEYS[1], ARGV[1])
else
return -1
end";
var result = db.ScriptEvaluate(script, new RedisKey[] { "stock:item101" }, new RedisValue[] { "5" });
返回 -1 表示库存不够,其他值就是扣减后的剩余数量。注意脚本里下标从 1 开始,别写成 KEYS[0],那是非法索引。
典型症状:.NET 6+ 应用在 Docker 里连 Redis 报 SocketFailure on GET 或 Timeout performing GET,但用 redis-cli -h redis 却能通。问题往往出在 DNS 解析和连接复用冲突上。
bridge 网络,localhost 指向容器自己,不是宿主机host.docker.internal(Docker Desktop)或宿主机真实 IP(Linux Docker 需要加 --add-host 参数)ssl=true,除非 Redis 真的开了 TLS验证方法:进容器执行 ping redis(服务名)或 telnet redis 6379,不通就说明不是代码问题,是网络没通。
还有一个很容易被忽略的点:连接生命周期管理。ConnectionMultiplexer 不要轻易 Dispose 掉,除非应用整个退出。如果用了 DI 容器(比如 Microsoft.Extensions.DependencyInjection),注册成 Singleton 就行,别手动调 .Close() 或 .Dispose(),否则下次再操作就会重新创建连接,白白浪费性能。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8