连载中 9/18

最大努力通知:通知到为止的艺术

2026-06-18 · 4745 阅读 · 0 评论 · 0 赞

宕机三小时的接收方

老王把平台能力开放给外部商户,支付成功后要把结果通知商户系统。第一版直接复用了内部 MQ 的可靠投递:无限重试直到成功。结果撞上商户系统升级宕机三小时——重试队列堆了八万条,告警炸锅,而对面的人还在等升级结束。这次折腾让老王想明白一件事:对外通知和内部消息是两种生物。内部服务自己可控,消息必达天经地义;外部系统你管不着,无限重试是自我感动。

模式定义:尽力喊,留后门

最大努力通知(Best Effort Delivery)的两个组成部分:

一:有上限的重试——按阶梯间隔通知有限次,比如 1 分钟、5 分钟、30 分钟、2 小时、6 小时各一次,共五次,全失败就停止。间隔递增是给接收方恢复留时间,上限是给自己止损。

二:主动查询的口子——这是精髓。通知不到不算完,发起方提供查询接口(或定期生成对账文件),接收方发现自己没收到,可以主动来查。通知是推,查询是拉,推拉结合,信息最终不丢。

微信支付、支付宝的异步回调就是教科书实现:商户接口没响应,按 15 秒、15 秒、30 秒、3 分钟、10 分钟……递减频率重试若干次,同时商户可以随时调查询接口对账。你在商场见过的这套回调,就是最大努力通知的工业级版本。

实现的三块积木

notify_task 表:业务ID, 目标URL, 已试次数, 下次时间, 状态
调度器:扫描到期任务 → 发通知 → 成功标记完成
        失败次数+1,按阶梯算下次时间
        超过上限 → 标记「通知失败」,转入人工/对账
查询接口:接收方按业务单号主动查最终状态

和本地消息表长得像,差别在语义:本地消息表的目标是「必达」,任务永不放弃;最大努力通知的目标是「尽力」,任务可以判死。判死不是躺平——通知失败的任务要进告警和对账流程,由对账系统兜底(第 16 篇),模式之间是接力关系。

内部与外部的分界线

对象方案原因
内部服务可靠消息(消息表/事务消息)自己可控,必达值得
外部商户/第三方最大努力通知 + 查询接口不可控,止损优先
短信/推送最大努力通知通道本身尽力而为

分界线划错了会发生什么:拿可靠消息对外部系统无限重试,是把自己的资源押给别人的故障;拿最大努力通知给内部服务,该到的积分没到,用户投诉。老王把这条线写进了服务边界规范:跨出自己团队的调用,默认按最大努力通知设计

小结

最大努力通知一句话:阶梯重试尽力喊、喊不到判死、查询接口留后门;对内可靠消息,对外尽力而为,边界决定方案。消息型方案(消息表、事务消息、通知)到此讲完,它们全都默认一件事——接收方能正确处理重复消息。这个默认不成立时一切归零:下一篇把系列的通用地基补齐——幂等设计。

503

10 年全栈工程师 · 503咖啡馆主理人

#分布式事务#最大努力通知#回调#通知重试#对账

评论 (0)

相关推荐

连载中 12/20

排查四件套:jstack、jmap、jstat、jcmd 的实战分工

jstack 看线程在干什么,jmap 看堆里装了什么,jstat 看运行时在变什么,jcmd 是统一入口。四把刀各管一段,配合着用没有查不动的现场。

#jstack#jmap#jstat#jcmd#排查工具
2026-09-16 · 5 阅读 · 0 评论 · 0 赞
连载中 11/20

GC 日志:把回收过程翻译成人话

一行 GC 日志里塞着七种信息:谁触发的、收了哪、停了多久、活了哪些。加上 -Xlog 配置,再加上日志分析工具,GC 不再是只能盯监控曲线的黑盒。

#GC日志#Xlog#日志分析#GC监控#Full GC排查
2026-09-16 · 13 阅读 · 0 评论 · 0 赞
连载中 10/20

ZGC:亚毫秒停顿是怎么炼成的

百 G 大堆停顿不到一毫秒,靠的是把搬家全部挪到并发阶段——着色指针让引用自带状态,读屏障让搬运中的对象依然可访问。代价是吞吐与内存,收益是停顿与堆大小解耦。

#ZGC#着色指针#读屏障#亚毫秒停顿#分代ZGC
2026-09-15 · 8 阅读 · 0 评论 · 0 赞