离线补传队列:领取、退避与幂等确认

任务长期处于 uploading,不能只看累计次数判断卡住。应检查领取、超时、租约与失败后的下一次时间。

edyang · 2021-04-06

任务长期处于 uploading,不能只看累计次数判断卡住。应检查领取、超时、租约与失败后的下一次时间。

持久队列把发送意图与网络执行分开。领取需并发约束,租约支持崩溃回收;回执丢失后的重试仍需业务幂等身份。

离线补传队列:领取、退避与幂等确认:处理路径与验证条件

一、问题的范围与前提

消息传输、业务处理与设备执行具有不同完成条件。消息系统可以提供队列和协议确认,但不会自动把数据库写入与物理动作合成一个事务。事件身份、对象版本与会话范围需要由应用定义,尤其在重复、乱序和断网补传时。

二、技术分析与方案取舍

租约让 worker 崩溃后的任务有机会回收,但上传实际上仍可能被远端受理。回收以后先查稳定业务键的结果,比立即发第二次更安全。长耗时文件可以和关键注册任务分开调度,并观察最老等待时间。成功回执保存以后再处理文件清理,索引、业务状态与附件保留周期不能混成一步。

先区分状态、事件和命令,再选择传输语义与保留方式。发送端持久保存重要意图,接收端用稳定业务键管理去重与结果。队列领取与回收需要并发约束,超时与退避有整体预算,避免持续失败把下游压力无限放大。

三、实现与排查的顺序

  1. 原子领取到期任务。
  2. 设置上传超时租约。
  3. 失败退避回队。
  4. 确认回执后清理。

按这个顺序保留中间结果,可以区分输入条件、处理过程和最终输出。前一阶段的条件不成立时,先解释对应错误,再继续后面的试验;单次返回成功不足以覆盖整条链路。

最小示例

1
2
3
pending → claimed → sending → confirmed
失败:sending → pending,保存下次重试条件
中断:租约到期 → 查询结果 → 安全回收

状态是通用结构,不对应现场数据库字段。任务领取需要原子边界,回执未知时优先查询,成功后的业务记录与文件清理分别管理。

四、验证和结果解释

记录消息来源、序号、采集时间、接收时间和处理状态,有助于判断旧消息、重复消息与新事件。次数本身不能解释进展,应看一段时间内领取、失败、下一次执行和确认是否连贯。关键任务等待时间也比 worker 存活更能说明调度质量。

需要验证的结果 保留的对照 不能由此推出的结论
重启回收中断任务 固定输入与配置、对应输出 一次成功代表所有条件成功
重复不重复入库 中断前后状态与错误阶段 没有报错代表结果正确
慢任务不会饿死关键任务 恢复后的同条件复测 临时恢复代表根因已经消失

故障测试包括发送后断线、受理后丢回执、处理中崩溃和重连乱序。系统应能明确查询、回收或拒绝,不能把网络未知结果一律当作失败重发。保留消息不替代历史库,高 QoS 也不自动提供跨系统业务只执行一次。

五、适用边界与结论

next_retry_at 过去不一定异常,任务可能已执行。队列存活、任务进展与业务完成分别观察。

这条路径把“原子领取到期任务”与“确认回执后清理”连在一起,中间保留可复查的条件。实施时优先确认“重启回收中断任务”,再检查“慢任务不会饿死关键任务”;两者都满足,才能在当前样本与配置范围内评价方案。设备、数据或软件版本改变以后,相关假设需要重新验证。

参考资料