商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > c#如何使用Redis_c#Redis项目实例附完整源码

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

  发布于2026-07-19 阅读(0)

扫一扫,手机访问

记住几个关键点:使用最新版 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,那个已经废弃了。

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

  • abortConnect=false:启动时如果连不上,别直接抛异常挂掉,先忍着
  • connectTimeout=5000:5 秒超时,太短容易失败,太长拖慢服务启动
  • syncTimeout=3000:同步操作的上限时间,防止线程池被阻塞
  • allowAdmin=true:只在开发或调试时开,生产环境别开,不然执行 FLUSHDB 这种命令就太危险了

强烈推荐用 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+ 默认就有):

  • 存对象: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 原生的 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 解析和连接复用冲突上。

  • Docker 默认用 bridge 网络,localhost 指向容器自己,不是宿主机
  • 如果 Redis 跑在宿主机上,要改用 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(),否则下次再操作就会重新创建连接,白白浪费性能。

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

热门关注