NOTEDevOps

定时付费任务如何分配递增编号并避免重试重复创建

本文结论

为每次调度设置稳定分配键,并用互斥锁保护编号分配,使周期性付费任务既能在同一周期多次运行,又不会因异常重试重复创建。

一个按周运行的媒体流水线需要支持同一 ISO 周内发布多期内容。原来的周标识不再唯一,因此任务目录和历史记录改成了 2026-W32-02026-W32-12026-W32-2 这样的版本化形式。

但增加序号只解决了一半问题。调度器可能在分配任务后、记录成功前异常重启。如果每次重跑都重新申请“下一个序号”,同一次逻辑运行就会消耗多个任务 ID。对于付费流水线,后果不只是目录混乱:后续命令还可能初始化第二个任务,并向供应商重复提交请求。

重试为什么会重复创建任务

这套流程必须同时满足两个看似冲突的要求:

  1. 同一周内的不同运行必须获得递增序号;
  2. 同一次定时运行的异常重试必须拿回原序号。

只看当前最大序号可以满足第一条,却会破坏第二条;固定使用一个周 ID 虽能安全重试,却无法支持同周多更。直接用时间戳也不够,因为它会让每次重试都天然变成新任务,恰好违背了恢复要求。

真正缺少的是一项能够稳定标识“本次调度”的信息。调度器知道自己正在执行哪一次逻辑任务,但这个标识之前没有与已分配任务一起保存。

区分周期、序号和本次调度

任务身份被拆成三个字段:

  • week_id 表示所属 ISO 周;
  • sequence 表示当周从零开始的发布顺序;
  • episode_id 组合两者,作为目录、状态、历史和后续命令使用的唯一持久标识。

分配入口同时接受稳定的分配键 allocation_key。定时任务可用自身调度标识生成这个键,例如 scheduled-run:2026-08-07。具体格式并不重要,关键规则是:同一次逻辑调度的所有重试必须复用同一个键。

分配器在流水线锁内执行以下步骤:

  1. 读取现有任务状态和已完成历史;
  2. 查找是否已有任务保存了本次分配键;
  3. 如果在目标 ISO 周内唯一匹配,则直接返回原任务 ID;
  4. 如果同一键跨周复用或匹配多个任务,则立即失败;
  5. 只有没有匹配时,才计算 max(sequence) + 1、持久化新任务并返回 ID。

流水线锁用于保证同一时刻只有一个分配过程执行,不能省略。仅有幂等键时,两个首次调用仍可能同时读到相同最大序号并分配同一个新值;仅有锁时,重试虽然会串行执行,却仍会各自获得新序号。稳定分配键和互斥锁必须同时存在。

把任务分配与付费执行分开

零费用的规划命令可以分配新 ID,但任何付费命令都不得隐式创建任务。生成、审批、返工和重新装配等命令现在都要求传入一个明确且已存在的 episode_id

如果任务不存在,程序会在读取凭据或初始化供应商客户端之前停止。这样形成了清晰的安全边界:

  • 分配阶段决定“这次调度拥有哪个持久任务”;
  • 执行阶段决定“这个已知任务是否可以产生费用”。

任务状态仍然保存已受理的远端任务引用和费用账本。中断恢复时,流程会继续已保存的任务,而不是仅凭目录名重新构造供应商请求。

迁移旧状态时保留证据

两个已完成任务从单纯周标识迁移到了版本化 ID。状态和历史新增了任务 ID、所属周、序号与迁移元数据,同时保留原有远端任务引用、审批状态、费用记录、完成时间和媒体哈希。

迁移验证没有停留在“目录移动成功”。两个任务都通过了既有只读检查器,最终视频和封面哈希保持不变;整个迁移过程没有调用任何付费 API。

验证

实现完成后共有 69 项自动化测试通过,其中分配专项覆盖证明:

  • 同一 ISO 周内序号递增,进入下一周后从零重新开始;
  • 相同分配键在异常重试后返回同一任务;
  • 分配键不能静默跨越 ISO 周;
  • 并发分配由流水线锁串行化;
  • 同一周的多个已完成任务可以同时写入历史;
  • 付费执行必须显式提供任务 ID;
  • 任务不存在时,会在读取凭据或访问付费供应商之前失败。

两个迁移后的任务也通过了端到端只读检查,产物哈希、费用账本和远端任务引用数量均未变化。

经验与限制

递增后缀只是命名规则,不是幂等设计。可靠的周期性任务分配需要稳定的调度标识、覆盖“读取—决策—保存”全过程的互斥;如果发现一个分配键跨周期或对应多个任务,程序必须立即停止,不能猜测应该复用哪一项。

这个模式不只适用于媒体生成,也适用于周期性导出、账单批次、模型评测、报表快照等场景:同一周期可以合法产生多个任务,同时调度器又可能在结果不确定时自动重试。

分配键必须来自稳定的调度身份。每次新建随机值或直接使用重试启动时间,都会让恢复能力失效。锁的范围也必须覆盖发现旧任务和写入新任务的完整过程;如果只锁最终写入,读取最大序号与选择下一值之间仍然存在竞态。

最后,分配幂等并不等于供应商提交天然幂等。远端提交仍需要持久化任务引用、明确恢复规则,并在是否已受理无法确认时禁止重新提交。

分类DevOps
遇到类似系统问题?

先说明系统,再说明症状

如果需要生产排障、DevOps 交付或物流系统集成协作,请提供当前表现、预期结果、受影响环境、可用日志或数据样例,以及发布限制。我会从现有证据开始判断。

通过邮件开始