Skip to content

重点:幂等、可回放、可恢复。把“失败”视为一等公民。

🎯 文章目标

  • 设计长任务的状态机与检查点
  • 定义重试与补偿策略,确保一致性
  • 提供最小实现与观测指标

📚 背景/前置

  • 长任务:分钟/小时级,跨多服务/工具,易失败
  • 失败类型:网络/配额/权限/数据质量/超时/中断

🔧 核心内容

1) 状态与检查点

  • 状态机:pending → running → succeeded/failed/cancelled
  • 检查点:在关键步骤持久化(输入/输出/偏移量)
  • 幂等键:避免重复执行副作用

2) 重试与补偿

  • 指数退避 + 最大尝试次数;按错误类型决定是否可重试
  • 补偿动作:对外部系统的副作用需“反向操作”或“标记撤销”
  • 超时/中断恢复:从最近检查点恢复

3) 观测与告警

  • 指标:平均耗时、失败率、重试次数、卡点分布
  • 告警:重试过多/长期 pending/同类错误爆发

💡 实战示例:异步队列 + 状态机(Node.js)

javascript
import Queue from 'bull'
const q = new Queue('long-job')

q.process(async (job)=>{
  const { steps } = job.data
  for (const s of steps){
    // 幂等:不要重复执行副作用
    if (await done(job.id, s.name)) continue
    await doStep(s)
    await checkpoint(job.id, s.name)
  }
})

📊 对比/取舍(速查)

  • 同步:简单但易超时;
  • 异步:复杂但可恢复,建议用于长任务

🧪 踩坑与经验

  • 无幂等键导致重复执行;
  • 无检查点导致中断无法恢复;
  • 无观测导致故障不可见

📎 参考与延伸

  • Saga/补偿事务、Outbox/Inbox 模式
  • 任务队列与工作流引擎(Bull/Temporal/Airflow)

💭 总结

  • 以“状态机 + 检查点 + 幂等 + 重试/补偿 + 观测告警”,构建可恢复的长任务