返回 S01~S90 教材库
S37 · 总 Day 127教材已备 ≠ 学习已完成

S37:Checkpoint 与 Idempotency Key 的最小实现

Checkpoint 保存“任务已确定到哪里”,idempotency key 标识“这次业务意图是否已执行过”;两者配合才能在崩溃和重复投递后安全恢复。

2026-12-29checkpoint、idempotency、replay、deduplication、side-effect

内容类型:预习教材(不代表已完成)
日期:2026-12-29
阶段:P2 · AI Systems Engineering 90
总路线:Day 127 / 360
周次:W6 · Agent Runtime & Durable Workflow
节奏:周二最小实现
状态:教材已备;学习未完成
标签:checkpoint、idempotency、replay、deduplication、side-effect

一句话定义

Checkpoint 保存“任务已确定到哪里”,idempotency key 标识“这次业务意图是否已执行过”;两者配合才能在崩溃和重复投递后安全恢复。

学习目标

  1. 能区分 checkpoint、日志、缓存和业务结果记录。
  2. 理解幂等不是“忽略所有重复”,而是同一业务意图重复提交得到一致可解释结果。
  3. 能设计 key 的作用域、生命周期和结果保存方式。
  4. 用最小代码或伪代码解释 crash 前后恢复语义。

核心知识

  • Checkpoint 至少包含 workflow id、当前状态、版本、已完成步骤、必要输出和更新时间。若只存步骤序号,代码升级或分支变化后可能无法解释。
  • Idempotency key 应来自稳定业务意图,例如 caseId + actionType + actionVersion,而不是每次重试重新生成的随机 request id。
  • 去重记录通常有 IN_PROGRESS / SUCCEEDED / FAILED_RETRYABLE / FAILED_FINAL 状态,并保存结果引用。只保存“见过 key”会把崩溃中的请求永久误判为完成。
  • Checkpoint 与外部副作用之间无法天然原子提交。可用事务 outbox、幂等下游接口或事后 reconciliation 缩小未知窗口。
  • Key 需要作用域与保留期:太窄会重复效果,太宽会阻止合法的新操作;过早过期会让迟到重试再次执行。

机制与推导

最小处理逻辑:

handle(command, key):
  record = idempotencyStore.get(key)
  if record.SUCCEEDED: return recordedResult
  if record.IN_PROGRESS and leaseValid: return/retryLater
  claim(key, IN_PROGRESS, lease)
  result = performEffect(command, key)
  saveResultAndCheckpoint(key, SUCCEEDED, result, nextState)

关键崩溃点有三个:claim 前崩溃可安全重试;claim 后、effect 前崩溃需要 lease 回收;effect 后、保存结果前崩溃形成未知状态,必须依赖下游幂等查询或 reconciliation。Checkpoint 本身不能消除第三个窗口。

版本也进入语义。若 workflow v2 改变了 action 含义,旧 key 是否可复用必须显式决定。安全做法通常是把业务动作版本纳入 key 或记录,但不能用版本号掩盖同一效果的重复执行。

最小练习或观察步骤

  1. 定义一个无真实外部写入的 proposeCaseEscalation 合成动作。
  2. CheckpointIdempotencyRecord 的最小字段,不超过能解释状态的范围。
  3. 模拟相同 key 连续调用两次,第二次返回已记录结果而非再次执行。
  4. 在 effect 后、保存前插入一个“假想崩溃点”,写出恢复时缺少的事实。
  5. 增加 queryEffectByKey 或 reconciliation 伪步骤,说明它如何补足未知状态。
  6. 不填写实际运行结果,除非确实运行并观察;内存 Map 只能称教学模拟。

常见误区与边界

  • 用 HTTP request id 当业务幂等 key,重试时 request id 变化。
  • 认为数据库唯一索引自动解决外部 API 或人工动作的重复。
  • 把失败全部缓存成永久失败,临时错误再也无法恢复。
  • 不保存首次结果,重复调用只能返回模糊的 duplicate
  • checkpoint 包含 secret、完整敏感正文或不可序列化运行对象。
  • 本日不追求 exactly-once,不要求建立持久数据库或大量故障测试。

系统 / 金融 / Web3 场景连接

支付争议提交、AML 案件升级与通知发送都可能因网络超时被重试。业务 key 应对应“同一案件的同一版本动作”。Web3 广播交易可用签名后的交易哈希识别同一交易,但重新签名可能改变哈希;nonce、链 ID、账户与业务意图必须共同解释重复和替换交易。

自检问题

  1. checkpoint 与 idempotency record 分别回答什么?
  2. effect 后保存前崩溃为什么最棘手?
  3. key 过宽、过窄和过早过期分别会怎样?
  4. 为什么 IN_PROGRESS 需要 lease 或恢复策略?

专业课程对齐

  • 阅读 Temporal 官方文档 中 durable execution、Activity retry 和 Event History 相关说明,重点观察 workflow progress 与外部 activity 结果怎样分别记录。
  • 阅读 MIT 6.5840 Distributed Systems 中 RPC、容错和一致性相关主题,聚焦请求重复与服务器崩溃为何让“执行一次”难以保证。
  • 阅读 CloudEvents 官方站点 的事件 envelope 概览,关注稳定 idsourcetype 等字段怎样帮助识别事件,而不把事件 ID 直接等同于业务幂等语义。

深入学习提示

先列崩溃点再写实现。对每个持久写和外部调用之间插入崩溃,判断恢复后可以重放、查询还是只能人工对账。进一步比较 event id、request id、workflow id 与 business idempotency key 的作用域;能清楚解释差异比写更多代码更重要。

学后填写区

  • 使用的合成动作与 key:
  • Checkpoint / 幂等记录字段:
  • 观察到或推演的崩溃窗口:
  • 仍需对账的状态:
  • 未实际验证的部分:
重点主线 · H02 · Harness 循环、状态与恢复本周配套机制实验 · W6 · Agent 恢复:请求重试不等于副作用重做 →详细讲义、离线示例与源码;按需要选读,不新增必交任务。
本页是未来 P2 的预习教材。等 P1 完成并正式进入 P2 后,再填写真实理解、练习结果和不确定项;现在阅读不会改变P1 唯一进度账本