长任务异步化:队列、幂等与断点续跑的工程做法
发布于 2026-10-01
长任务异步化:队列、幂等与断点续跑的工程做法
短请求(问答、改写)用同步接口就够了。但当任务变成"读 50 个文件生成一份分析报告"、"批量处理一千条数据"时,同步方案会同时撞上三面墙:网关超时、用户干等、失败重试成本高。
异步化不是把代码改复杂,而是把任务的生命周期显式管起来。
一、把流程拆成四段
提交:接口只做校验与落库,立刻返回任务 ID;
任务表:状态(排队中/执行中/成功/失败)、进度、输入参数、产物位置都在表里;
工作进程:独立进程消费队列,与 Web 请求线程解耦;
取结果:前端轮询或服务端回调,二者至少留一个。
二、幂等键:同一请求只执行一次
用户在页面上多点了一次"生成",或客户端超时重试,都会产生重复提交。用幂等键兜住:
提交时先查键:已存在就返回已有任务 ID,不新建。执行侧再查一次,防止队列重复投递导致重复执行。
三、断点续跑:把长任务切成短步骤
一个三十分钟的任务,中途失败就全部重来的代价太高。做法是分步执行、逐步落盘:
每一步的中间产物(已处理的文件、已生成的段落)写入存储;
失败重试时从最后成功的步骤继续;
步骤粒度以"单步 13 分钟"为宜,重试成本可控。
四、失败要分类
可重试(网络抖动、上游限流):退避重试,设置最大次数;
不可重试(参数非法、内容违规):直接置失败并给出可读原因;
未知:重试到上限后进入死信队列,人工处理。
把错误分类写进任务的失败记录里,排查时才能一眼看出"该重试还是该改参数"。
五、进度与体验
异步不代表用户什么都看不到:
任务表里记录已完成比例,前端展示进度条或分步清单;
给出预估剩余时间(哪怕粗糙);
完成后通过站内信/邮件/回调通知,而不是让用户守着页面。
六、上线前检查清单
队列积压时,任务是否会无限堆积?(要有上限与拒绝策略)
同一任务并发执行会不会互相踩数据?(幂等 + 状态机锁)
产物存储有多大?(定期清理过期结果)
失败任务有人看吗?(告警或每日巡检)
异步化的收益很直接:接口秒回、重试便宜、失败可见。长任务越多,这套骨架越值。