Redis Pub/Sub 订阅者断线后为什么收不到历史消息
Redis 的 Pub/Sub 订阅者断线后收不到之前错过的历史消息,不是客户端漏写了拉取逻辑,而是这套机制从设计之初就没有历史回放的语义。Redis 官方把 Pub/Sub 定义为 at-most-once(最多一次)投递模式:消息发布的瞬间,只有当下已经连通服务端、并且提前订阅了对应频道的客户端才能收到这条消息。如果客户端中途断线、消息处理失败,哪怕之后立刻重连重新发起订阅,之前错过的消息也不会自动补发。业务如果需要支持消息补偿读取、实现至少一次消费的可靠性,应该把事件写入 Redis Streams 或者独立的业务持久化存储,Pub/Sub 只用来做轻量的实时通知就好。
官方地址:https://redis.io/
- Pub/Sub 是广播通道,不保存消息,也没有订阅者游标;断线期间发布的消息会永久错过。
- 允许短暂丢失的缓存失效、在线状态和界面刷新可以继续用 Pub/Sub,但重连后要主动读取持久状态。
- 订单、审计、任务和必须补偿的领域事件,应选择 Redis Streams 或业务数据库,再按消息 ID 恢复。
Redis Pub/Sub 为什么不会补发断线消息
PUBLISH 的工作是把一条消息推给当前匹配频道的订阅者;SUBSCRIBE 建立的是实时监听关系,不是一个可以翻页的消息列表。消息经过广播后不会自动写入某个频道历史,也不存在“订阅者上次读到哪里”的位置。
因此,发布者在 10:00 发送消息,订阅者在 10:01 才重连,即使频道名称、客户端身份和业务内容都一样,10:00 的消息也不会因为重新执行 SUBSCRIBE 而出现。Redis 文档把这种行为称为 at-most-once;断开网络、消费者进程崩溃或回调处理失败时,消息都没有第二次投递机会。

先区分实时广播和可恢复数据
排查“重连后少消息”时,先不要急着调大客户端缓冲区。要问的是:这条消息本身是不是业务事实?如果只是“让页面刷新一下”的提示,丢一条通常可以接受;如果它代表支付状态、库存变更或审计记录,就不能把唯一事实放在 Pub/Sub 上。
| 场景 | Pub/Sub 是否合适 | 重连后的处理 |
|---|---|---|
| 缓存失效通知 | 适合,允许偶发漏通知 | 重连时按版本或 TTL 主动刷新缓存 |
| 在线状态、输入中提示 | 适合,状态很快过期 | 重新上报当前状态,不追历史事件 |
| 订单、扣款、审计 | 不应作为唯一通道 | 从数据库或 Streams 按记录/消息 ID 补偿 |
另外,Pub/Sub 与 Redis 数据库编号没有关系:在一个逻辑数据库上发布,不会让另一个数据库产生独立的频道历史。需要环境隔离时,应把 prod:、staging: 这类环境前缀放进频道名。
允许丢失的通知,重连时怎样补当前状态
实时通知可以继续使用 Pub/Sub,但把“可恢复的当前状态”放在普通 Redis key 或业务数据库里。发布者先写入状态,再广播一个轻量通知;订阅者收到通知后读取状态。重连时不追问“我错过了几条消息”,而是直接读取最新状态,避免把广播通道误当成事件日志。
#!/usr/bin/env bash
# 先保存可恢复的当前版本,再发送只负责提醒的实时通知。
redis-cli HSET order:42 status paid version 18
# PUBLISH 返回当前收到消息的订阅者数量,不是历史消息数量。
redis-cli PUBLISH order:changed '{"order_id":42,"version":18}'
# 订阅者重连后主动读取当前状态,而不是等待 Pub/Sub 补发旧消息。
redis-cli HGETALL order:42
这个模式的关键是幂等:通知可以重复、丢失或乱序到达,但持久状态有版本号,消费者读取后能判断是否需要更新。若业务要求知道每个事件,而不是只关心最终状态,就升级为 Streams。
必须恢复的事件改用 Redis Streams
Redis Streams 会保留消息和消息 ID,可以让消费者在重连后从上次位置继续读取,并结合消费组处理确认与待处理消息。它和 Pub/Sub 解决的是两种不同问题:前者偏向可追踪事件流,后者偏向低延迟广播。

#!/usr/bin/env bash
# 把订单事件写入 Stream;* 让 Redis 生成可恢复的消息 ID。
redis-cli XADD order-events '*' order_id 42 status paid
# 消费组从未投递位置读取,重连后仍有消息身份可以继续处理。
redis-cli XREADGROUP GROUP billing-worker consumer-a COUNT 10 STREAMS order-events '>'
# 处理成功后确认这条消息,避免把“读到”误当成“业务完成”。
redis-cli XACK order-events billing-worker 1710000000000-0
生产环境还要明确确认时机、重复消费和待处理消息回收策略。不要因为 Pub/Sub 和 Streams 都在 Redis 里,就把两者混用成“先发布、之后一定能补回”的假可靠链路。
常见问题
订阅者重连后重新 SUBSCRIBE,为什么还是没有旧消息?
SUBSCRIBE 只建立新的实时订阅关系,不读取频道历史。旧消息没有被 Pub/Sub 保存,重连只能收到之后发布的消息。
PUBLISH 的返回值是不是消息积压数量?
不是。它表示本次发布时匹配到并收到推送的订阅者数量,不能说明有多少客户端离线,也不能说明消息是否已被业务处理。
缓存失效通知漏掉后一定会造成脏数据吗?
不一定。若缓存有 TTL、版本校验或重连后的主动刷新,漏掉一次通知可以被修复;没有这些补偿机制时,缓存失效事件就不该只依赖 Pub/Sub。
什么时候应该直接换 Redis Streams?
当消息必须保留、需要重放、需要消费确认、需要按消费者进度恢复,或业务能接受至少一次处理并自行幂等时,应优先考虑 Streams。
Go map lookup 读取不存在键为什么返回元素零值
- 上一篇
- Go map lookup 读取不存在键为什么返回元素零值
- 下一篇
- Go encoding/csv FieldsPerRecord 设置为负数后如何自行校验列数
-
- 数据库 · Redis | 1小时前 | Redis · 消息队列 · Stream · 消费组 · XREADGROUP XACK XPENDING XAUTOCLAIM Redis Streams Pending List
- Redis Streams XREADGROUP 后 Pending List 怎么处理
- 342浏览 收藏
-
- 数据库 · Redis | 2小时前 | Redis · 排行榜 · Sorted Set · 分页设计 · 游标分页 · redis 分页 limit rev ZRANGE Sorted Set
- Redis Sorted Set 分数相同时怎么保证分页稳定
- 349浏览 收藏
-
- 数据库 · Redis | 4小时前 |
- Redis Hash 只给单个 field 设置过期时间为什么不行
- 456浏览 收藏
-
- 数据库 · Redis | 13小时前 | Redis · lua · eval · eval Redis Lua 多 key 原子校验
- Redis Lua 脚本读取多个 key 时怎么保持原子校验
- 423浏览 收藏
-
- 数据库 · Redis | 21小时前 |
- Redis ZRANGEBYSCORE 分数边界怎么写成开区间
- 440浏览 收藏
-
- 数据库 · Redis | 1天前 |
- Redis EXPIRE 续期时为什么会把旧过期时间覆盖
- 273浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 63次使用
-
- SuperCLUE
- SuperCLUE是权威的中文大语言模型综合评测基准,涵盖语言理解、知识应用、AI Agent智能体及安全性等12项核心能力。通过多轮对话与客观测试,定期发布榜单与技术报告,为模型研发、优化及行业选型提供科学依据。
- 224次使用
-
- C-Eval
- 深入了解C-Eval中文评估套件,涵盖52个学科与4级难度。本文详解其功能特点、Zero-shot/Few-shot使用方法及代码示例,助您全面评测LLM中文理解与泛化能力。
- 148次使用
-
- AI Prompt Library
- 探索AI Prompt Library免费资源库,涵盖营销、写作及多场景AI提示词。兼容ChatGPT、Claude等工具,一键复制优化输出,提升工作效率。
- 81次使用
-
- Generrated
- Generrated汇集9300+张DALL·E生成图像及对应提示词,支持查看完整图集、对比DALL·E 2与3版本差异,是AI绘图新手学习Prompt设计与获取创作灵感的实用工具。
- 58次使用
-
- Redis RDB 和 AOF 怎么按可接受数据丢失量选择
- 2026-09-08 501浏览
-
- Redis XAUTOCLAIM 之后为什么仍有 pending:JUSTID、PEL 与消息删除边界
- 2026-08-29 501浏览
-
- Redis SET 的 GET 与 KEEPTTL 怎么一起验收:旧值返回、续期与回滚边界
- 2026-08-20 501浏览
-
- Redis 慢命令快照小工具:用 SLOWLOG 定位接口延迟
- 2026-06-29 501浏览
-
- Redis集群节点规划与部署全解析
- 2025-08-02 501浏览

