登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  Redis

Redis Pub/Sub 可靠性边界 怎样处理

来源:17golang原创

时间:2026-10-22 06:18:25 288浏览 收藏

热门推荐
漫画APP
动画内容聚合,热门资源快捷查看
立即下载

Redis Pub/Sub 可靠性边界 怎样处理

Redis Pub/Sub 适合向在线订阅者发送即时通知,不负责保存离线消息、确认业务完成或失败后重投。处理可靠性边界,应先问“漏掉一条能否通过重新读取当前状态恢复”:可以时,把 Pub/Sub 当刷新提示并增加回源补偿;不可以、且每条事件都必须追踪时,应选择带持久记录和消费进度的方案,而不是只靠自动重连。

以下用商品目录刷新通知比较三种设计。命令是原创示例,未启动 Redis 或执行本地测试,所有观察条件均供读者在自己的独立环境对照。官方入口:https://redis.io/docs/latest/develop/pubsub/。

先确认通知是在提醒刷新,还是在下发任务

商品目录已经保存在权威存储中,在线页面收到提示后重新获取当前版本;断线期间没看到提示,下次回源仍能恢复。这属于状态通知。相反,“收到一条就执行一次发货”把消息当作任务,漏失和重复执行都影响业务,不能只用 Pub/Sub 承担完成保证。

最小订阅与发布写法如下。两段命令在两个会话分别运行,不需要创建频道键,也不向频道设置 TTL。

# 在独立示例环境的订阅会话运行;先等待订阅确认。
redis-cli SUBSCRIBE demo:catalog:refresh
# 此命令保持接收消息,结束示例时在这个会话按 Ctrl-C。
# 在另一个会话运行;这里只发送刷新提示,不执行业务操作。
redis-cli PUBLISH demo:catalog:refresh '{"event_id":"demo-e17","entity":"catalog","version":17}'
# 返回整数不是库存已更新、订单已处理或客户端已展示的证明。

读者应先看到订阅确认,再发布消息,观察订阅连接中的消息负载。若订阅尚未建立便发布,或客户端断线时发布,后续重新订阅不会自动补回那段历史。本文没有记录真实执行输出,因此不预设发布命令一定返回某个固定数字。

三个候选方案各自保留什么

方案保留内容适合的目标必须另做什么
纯 Pub/Sub在线订阅关系,不保留可回放事件日志可漏失的临时提示连接管理、负载处理
Pub/Sub 加状态回源权威当前状态及版本目录、看板等最终状态刷新重连回源、周期校正、并发版本处理
持久事件或任务系统事件记录与处理进度需要逐条追踪和补处理保留期、重试、确认、幂等及运维

Redis 官方指出,若需要更强投递语义,可以考虑 Redis Streams。这里只把它作为具有持久记录能力的候选方向,不将“换成 Stream”直接等同于业务只执行一次;持久化、故障恢复和消费处理仍需完整设计。状态回源也不是回放所有中间事件,只恢复当前可查询状态。

连接、投递与业务结果不是同一层

发布端向频道发送负载,Redis 按在线订阅关系投递到订阅连接,应用处理器再处理消息并产生业务结果。发布返回整数只反映命令定义下的接收者计数,不是应用处理器的确认,也不是目标数据库提交回执。在集群等部署中计数还有作用范围,不能把它解释为全系统成功消费者数量。

发布投递连接与业务处理结果的责任分组
说明图:发布投递分组包含发布端、频道、订阅连接;业务处理分组包含应用处理器、业务结果、发布回执。连线区分通知投递与应用处理,发布回执不连接为业务成功证明;图片不是执行时间轴或现场截图。

Pub/Sub 的至多一次投递并不承诺应用永远只看到一次相似业务事件。发布端主动重发、上游产生重复,或者频道订阅与模式订阅同时匹配,都可能让业务处理同一含义的通知多次。需要副作用的处理器仍应设计 event_id、幂等约束和结果记录。

网络超时时,发布端可能不知道命令是否已经由服务端执行。盲目重试可能产生额外通知,不重试又可能错过提示;这个不确定性不能通过解释一次返回值消除。若提示只是“刷新到当前状态”,合并重复提示通常更容易;若消息就是扣减指令,则必须采用更严格的业务协议。

可恢复当前状态时,选择通知加版本回源

推荐的状态刷新设计保留权威状态、状态版本和本地视图:发布端先完成权威状态变更,再尽力发送包含实体和版本的提示;订阅端收到提示后从回源接口读取状态,只有不旧于本地版本的结果才替换本地视图。回源接口必须返回状态与版本的一致配对,不能从两个彼此可能变化的来源随意拼接。

订阅连接重新建立后主动回源,并用周期校正补偿“状态已提交但提示未发出”等窗口。如果两次回源并发完成,较旧响应后到,不能覆盖较新视图。这里的 event_id 用于识别事件,状态版本用于比较实体状态,两者不是可以随意互换的字段。

通知提示与权威状态回源的依赖结构
说明图:权威数据分组包含权威状态、状态版本、回源接口,客户端分组包含通知提示、本地版本、本地视图。连线表示回源与版本比较依赖,漏掉通知仍需依靠主动校正恢复,不表示 Pub/Sub 保存了历史。

这个方案的承诺应写成“在权威源可用、校正持续执行且版本规则正确时恢复当前状态”,不能写成“每个事件绝不丢”。若断线期间经历版本 17、18、19,回源只得到版本 19,无法据此重建每个中间变更;审计与逐笔任务需要事件记录。

这些可靠性要求不能靠重连补齐

自动重连只恢复未来接收能力,不能让服务端回放此前没有保留的频道消息。开启 AOF 或副本也不会把普通频道变成带消费游标的事件日志。给频道同名键设置过期时间,改变的是键空间,不是频道消息保留机制。

订阅回调里堆积耗时业务还会使应用缓冲不断增长;客户端和服务端资源都有边界。接收与处理可以解耦,但放入进程内队列不等于持久保存,进程退出仍可能丢失待处理内容。若要求崩溃后继续处理,应持久记录任务并设计恢复策略。

RESP2 的订阅连接有命令使用限制,示例因此使用独立会话;RESP3 在订阅状态下允许更多命令,但客户端库如何管理连接仍需按它的文档确认。环境隔离也要用明确的频道命名与权限策略,不要以为切换 Redis 数据库编号就隔离了 Pub/Sub 频道。

按漏失后果做决策,再记录处理证据

关键问题选择方向
漏一条只影响短暂动画或提示纯 Pub/Sub 可作为候选
漏一条后能重新读取最新状态通知加版本回源,并明确校正间隔
每个中间事件都要留存和补处理持久事件方案,设计进度与保留
重复执行会改变资产或业务数量业务幂等与事务约束不能省略

落地时至少区分发布错误、订阅断开、负载解析失败、处理失败和回源失败,记录事件标识或状态版本,不将全部故障合并成“Redis 不稳定”。可在独立测试环境安排订阅建立前发布、断线期间发布、重复提示和旧响应晚到等情况,对照所选契约;本文不声称已运行这些检查。

PUBLISH 返回大于零就能删除业务待办吗?不能,计数不是业务完成确认。如果待办必须完成,应由持久任务协议记录处理结果。

重连后为什么没有上次消息?普通 Pub/Sub 不提供按历史位置补发的能力;恢复当前状态要主动回源,恢复事件则需要提前保留记录。

只给通知加 ACK 频道就可靠吗?不自动可靠,ACK 自己也可能漏失。还需要关联、持久状态、超时、重试和幂等设计,复杂度不能被频道名称替代。

参考:Redis Pub/Sub 官方说明、PUBLISH 命令。核心边界是:即时投递负责通知,业务可靠性由可恢复的数据与明确的处理协议承担。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>