跳到主要内容
约 4 分钟2 张卡

幂等键

幂等键标识同一次业务意图,避免重复请求产生额外副作用。本文负责键作用域、事务边界和结果恢复。

1. 面试核心​

先记住这几条,再读正文
  • 业务意图。 同一业务意图复用同一 key,不同意图使用新 key。
  • 唯一作用域。 主体、接口与 key 组成唯一作用域,请求摘要用于检测参数冲突。
  • 本地原子提交。 同库操作用事务共同提交业务变化与幂等结果。卡 · 综合题
  • 外部副作用。 外部副作用需稳定下游请求号和结果核对。卡 · 外部调用的崩溃窗口
  • 保留窗口。 幂等记录的保留期决定重复请求的识别窗口。

2. 幂等键的含义​

客户端为一次创建、支付或退款生成唯一 key。结果未知时复用它。用户主动发起另一笔交易时使用新 key。

服务端按调用主体、接口和 key 隔离记录。同 key 的请求摘要必须一致。金额或资源不同的请求返回参数冲突。

幂等约束的是副作用。重复响应可重放首次结果,也可返回当前资源,需由接口契约定义。

3. 原子占用​

记录可包含以下字段:

principal, operation, key, request_hash,
status, resource_id, response, expires_at

唯一约束决定哪个事务取得执行权。先查询再无约束插入会产生并发竞态。

冲突请求读取既有结果,或按状态返回处理中。唯一键解决执行权竞争,处理状态还需配合事务设计。

4. 与业务结果一致​

业务与幂等记录在同库时,可使用一个本地事务。占用 key、修改业务和保存结果共同提交。

以 MySQL 8.0 的 RC/RR 为例,普通读取看不到未提交记录。重复插入会按数据库机制等待或冲突。提交后再读取已保存结果。

崩溃导致事务回滚时,幂等占用也回滚。另一请求可重新竞争执行权。

5. 处理中的重复请求​

长任务或外部调用可先提交 PROCESSING 状态。后续请求能读到该状态,并返回状态查询入口。

这类方案需持久化工作流。执行者崩溃后,由恢复任务核对实际结果。租约过期只是接管条件,外部支付结果仍需查询。

接口可约定返回 202 与查询地址。短暂等待也应受请求总时限约束。

6. 返回结果​

保存首次响应可稳定重放,但要处理敏感字段与旧 header。保存资源 ID 后重新读取,则返回资源当前状态。

参数校验失败和已发生副作用的失败应分开处理。Stripe 会保存进入执行后的结果,包括 500。参数校验失败或并发执行冲突不保存结果。其他接口需自行声明对应规则。

7. 保留时间​

保留期覆盖自动重试、消息重投与人工补单窗口。记录清理后,相同 key 将被视为新请求。

长期业务唯一号可提供更长的去重边界。短 TTL 缓存适合加速,权威业务约束仍需持久化。

8. 条件状态转换​

业务状态更新需检查合法前置状态。

UPDATE payment
SET status = 'CAPTURED'
WHERE payment_id = ? AND status = 'AUTHORIZED';

应用根据影响行数确认本次是否完成转换。影响 0 行时,再查询当前状态判断结果。

该更新只保护数据库内的状态推进。外部扣款仍需稳定请求号与结果核对。

9. 客户端重试​

结果未知时,客户端复用原 key 并按预算重试。具体退避规则见重试。

总时限耗尽后停止自动发送,转为查询状态。修改请求参数时,应发起新的业务意图。

10. 外部调用的崩溃窗口​

外部支付成功、本地结果尚未写入时,进程可能崩溃。恢复任务读到 PROCESSING,仍无法据此判断支付失败。

调用前需持久化稳定下游请求号。恢复时用该号码查结果,或按下游幂等协议重发。确认成功后,再更新本地完成状态。

下游缺少查询和幂等能力时,自动补发有重复扣款风险。此类未知结果需进入对账或人工处理。Outbox 可靠投递仍需消费者去重。

11. 常见问题​

11.1 唯一索引与幂等记录​

唯一索引原子阻止重复占用。幂等记录还保存摘要、状态与返回结果。业务唯一约束可与接口幂等记录共同使用。

11.2 Redis 与权威状态​

12 · 面试题卡片​

12.1 如何设计一个支持安全重试的支付接口​

出现公司:美团

题型:综合题

考察重点

  • 理解幂等键作用域、请求摘要和原子占用。
  • 理解业务事务、处理中状态和外部副作用。
  • 理解TTL、状态查询与条件状态转换。

相关内容:幂等键的含义至客户端重试。

参考回答

支付接口用稳定 key 识别同一支付意图。

服务端按主体、接口与 key 建唯一记录,并校验请求摘要。同库业务与幂等结果在同一事务提交。

外部支付采用持久化状态机与稳定下游请求号。崩溃恢复先核对下游结果,再补本地状态。处理中请求返回查询入口。保留期覆盖重试与补单窗口,业务唯一号提供额外约束。

12.2 外部扣款成功后进程崩溃,PROCESSING 过期就能重新扣款吗?​

出现公司:暂无已核验的公开来源(本站自测)

考察重点:外部结果未知、稳定请求号与恢复。

相关内容:外部调用的崩溃窗口。

参考回答

PROCESSING 过期后,应先核对原扣款结果,不能直接按新请求再次扣款。

过期只说明本地处理未完成,外部支付可能已经成功。

使用持久化的下游请求号查询;下游支持幂等时,也可用同一号码重发。缺少这些能力时,未知结果进入对账或人工处理。

13. 参考资料​