必须用 iconnectionmultiplexer.getsubscriber() 获取 isubscriber 实例才能订阅,idatabase 不支持;订阅需连接就绪后执行,发布与订阅须同一连接实例,取消订阅需显式调用 unsubscribeasync() 防泄漏。

怎么用 StackExchange.Redis 订阅频道
直接用 IDatabase 无法订阅,必须用 IConnectionMultiplexer.GetSubscriber() 获取独立的 ISubscriber 实例。这是新手最常卡住的地方:误以为在普通数据库连接上 Subscribe() 就行,结果调用无响应或抛出 NotSupportedException。
-
ISubscriber是长连接、事件驱动的,不能复用或跨线程共享 - 每个订阅逻辑建议独占一个
ISubscriber,避免Subscribe和Unsubscribe混乱 - 订阅必须在连接就绪后执行(监听
ConnectionMultiplexer.Connected事件或检查IsConnected)
示例:
var subscriber = connection.GetSubscriber();
await subscriber.SubscribeAsync("user:notify", (channel, message) =>
{
Console.WriteLine($"收到: {message}");
});
发布消息时为什么收不到?常见断连原因
发布成功但订阅端没反应,90% 是因为发布和订阅用了不同连接实例,且未启用同一 Redis 服务器的 Pub/Sub 通道——本质是网络/配置层面断开,不是代码写错。
- 确认 Redis 服务未启用
protected-mode yes且绑定地址允许外部访问(如bind 0.0.0.0) - Docker 环境下,
localhost在容器内指向自己,必须用宿主机 IP 或host.docker.internal - 防火墙或云服务器安全组拦截了 Redis 默认端口
6379,Pub/Sub 不走命令端口的“请求-响应”流,而是依赖底层 TCP 连接保持
验证方式:用 redis-cli 手动 SUBSCRIBE user:notify 和 PUBLISH user:notify "test" 能通,说明服务端没问题。
如何安全取消订阅并释放资源
Unsubscribe() 不等于“断开连接”,它只是从 Redis 的内部订阅列表中移除客户端标识;若不显式调用,连接会一直维持,造成连接泄漏和内存缓慢增长。
- 必须配对使用
SubscribeAsync()/UnsubscribeAsync(),尤其在 ASP.NET Core 中,别在Controller方法里临时订阅 - 推荐在
IDisposable或IAsyncDisposable实现中调用UnsubscribeAsync(),例如封装成RedisPubSubService类 - 不要依赖 GC 自动清理 ——
ISubscriber没有终结器,不手动退订就永远挂着
错误示范:subscriber.SubscribeAsync(...) 后没存引用,也无处调用 UnsubscribeAsync()。
Pattern 订阅(PSUBSCRIBE)在 C# 里怎么写
StackExchange.Redis 支持通配符,但语法不是字符串拼接,而是通过 RedisChannel 构造函数传入带 RedisChannel.Pattern 标记的参数。
- 错误写法:
subscriber.SubscribeAsync("user:*", ...)→ 不匹配任何模式 - 正确写法:
new RedisChannel("user:*", RedisChannel.Pattern) - 注意:模式订阅无法用
Unsubscribe()精确退订,要用UnsubscribeAsync(RedisChannel)显式传入相同 pattern 实例 - 性能提示:大量 pattern 订阅会增加 Redis 遍历开销,单机建议不超过几百个活跃 pattern
示例:
var pattern = new RedisChannel("order:*", RedisChannel.Pattern);
await subscriber.PSubscribeAsync(pattern, (channel, message) => { ... });
真正麻烦的是跨进程状态同步——比如你发了个 PUBLISH order:1001 "shipped",但另一个服务的订阅者刚启动、还没来得及 PSubscribe,这条消息就永远消失了。Pub/Sub 本身不保证送达,这点必须由业务层兜底,比如配合 Stream 做双写或用消息 ID 做幂等查漏。










