Redis Pub/Sub不自动重连,必须手动实现:断连后新建Redis和PubSub实例,全量重订阅所有channel,并采用指数退避重试(如1s→2s→4s→最大30s),同时配合心跳检测与幂等校验防消息重复。

redis-py 的 PubSub 不自动重连,必须自己写循环
redis-py 的 PubSub 对象在连接断开后不会恢复订阅,listen() 会直接抛 ConnectionError 并退出。这不是 bug,是设计如此——它只负责“监听”,不负责“存活”。
- 每次异常后必须新建
Redis实例和PubSub对象,再调用subscribe() -
time.sleep(1)是底线,但生产环境建议用指数退避(如 1s → 2s → 4s → 最大 30s)避免雪崩重连 - 别在
for msg in pubsub.listen():外层包 try/catch——要 catch 在整个 listen 循环之前,否则一断就死 - 如果订阅多个频道,
subscribe('a', 'b', 'c')要一次性重订全,不能漏掉任何一个
Jedis 的 subscribe() 断开后不恢复,重连必须显式调用
Jedis 的 JedisPubSub 同样无自动重连能力,且 subscribe() 是阻塞调用,一旦连接中断,线程卡在 native 方法里出不来。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 必须用独立线程 +
while(true)封装重试逻辑,不能依赖JedisPool的连接池自动恢复——池里的连接断了,getResource()返回的仍是失效连接 - 重连前务必
jedis.close(),否则旧连接资源泄漏,容易触发 Redis 的maxclients限制 - 重新
subscribe()前,确保JedisPubSub实例是新创建的,或已调用unsubscribe()清理状态,否则可能收不到消息 - 阿里云 Redis 实例常见闪断场景(如主备切换),建议在
reconnect()中加入ping()预检,避免刚连上就发subscribe却被拒绝
Lettuce 自动重连需手动开启,且默认不恢复订阅关系
Lettuce 确实支持 autoReconnect(true),但它只保证底层 TCP 连接重建,PUBSUB 订阅状态**不会自动同步回服务端**——这是最容易忽略的坑。
- 必须配置
ClientOptions.builder().autoReconnect(true).disconnectedBehavior(RECONNECT_AND_QUEUE_COMMANDS),否则重连后命令直接丢弃 - 即使启用了自动重连,也要监听
StatefulRedisPubSubConnection的连接事件,在onConnected回调里重新subscribe() - Spring Boot 用户注意:
spring.redis.lettuce.pool配置对 Pub/Sub 无效,Pub/Sub 不走连接池,它是独占长连接 - 若用
RedisClusterClient,订阅仅支持单节点模式(集群不支持 Pub/Sub),别误配成 cluster 地址导致静默失败
消息重复不是网络抖动导致的,而是 Pub/Sub 机制本身决定的
网络抖动引发断连重连,只是让重复概率变高;真正根源在于 Redis Pub/Sub 是无状态广播,不存 offset、不等 ACK、不判去重。
- 发布方必须生成全局唯一
msg_id(推荐 Snowflake 或 UUIDv7),并随 payload 透传,不能靠时间戳+随机数拼接 - 消费者校验必须用
SET key value NX EX 3600原子操作,而不是先GET再SET——竞态下会漏判 - 别指望
PSUBSCRIBE能减少重复:一个进程PSUBSCRIBE order.*和三个进程各SUBSCRIBE order.created,收到的消息总量完全一样 - Redis 实例故障期间,
seen:{msg_id}key 可能丢失,这时幂等失效是可接受的降级行为,重点保主流程不崩溃,而非强一致

















