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

c#如何使用Redis_c#Redis项目实例附完整源码

直接用 StackExchange.Redis 就好,别碰过时的 ServiceStack.Redis,也别用 StackExchange.Redis 的 1.x 低版本——不然连接泄漏、异步死锁、序列化兼容性问题会让你头疼到怀疑人生。

安装和基础连接怎么配

NuGet 里装最新稳定版 StackExchange.Redis(目前是 2.7.x+),注意别装 StackExchange.Redis.StrongName,那个已经废弃了。

连接字符串建议把关键参数写清楚,别指望默认值能帮你兜底:

强烈推荐用 ConnectionMultiplexer 单例复用,不要每次 new 一个——它自己线程安全,内部管理连接池,你用 Lazy 或者 DI 容器注册成 Singleton 都行:

private static readonly Lazy LazyConnection = 
    new Lazy(() => ConnectionMultiplexer.Connect("localhost:6379,abortConnect=false,connectTimeout=5000"));

存取对象为什么报错“Unable to serialize”

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+ 默认就有):

注意:如果项目强依赖 Newtonsoft.Json,也可以用 JsonConvert.SerializeObject,但必须确保所有属性 public 可读写,且没有循环引用。否则一样会炸。

如何安全地做并发更新(比如库存扣减)

千万别用“先 GET 再 SET”这种两步操作——竞态条件百分之百会发生。Redis 原生的 DECRINCRGETSET 都是原子的,但 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],那是非法索引。

为什么本地跑得好,上 Linux 容器就超时

典型症状:.NET 6+ 应用在 Docker 里连 Redis 报 SocketFailure on GETTimeout performing GET,但用 redis-cli -h redis 却能通。问题往往出在 DNS 解析和连接复用冲突上。

验证方法:进容器执行 ping redis(服务名)或 telnet redis 6379,不通就说明不是代码问题,是网络没通。

还有一个很容易被忽略的点:连接生命周期管理。ConnectionMultiplexer 不要轻易 Dispose 掉,除非应用整个退出。如果用了 DI 容器(比如 Microsoft.Extensions.DependencyInjection),注册成 Singleton 就行,别手动调 .Close().Dispose(),否则下次再操作就会重新创建连接,白白浪费性能。

本文转载于:https://www.php.cn/faq/2312188.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。