接口层幂等如何设计?有哪些实现要点?

结论先行:接口幂等指"同一个请求无论执行一次还是多次,结果都一致"。GET 等查询天然幂等,需要设计的是 POST/PUT 这类会改状态的接口。核心思路是让请求携带稳定幂等键,服务端用原子手段保证"第一次真正执行,后续直接返回首次结果",常见落地是幂等令牌 + Redis 占位,或唯一索引 + 状态机校验。

一、常见实现方案

方案原理适用
幂等令牌前端请求先取 token,处理时原子占用,用后即焚表单提交、下单防重复
唯一约束业务幂等键建唯一索引,插入冲突视为重复流水、消息落库
状态机只允许合法状态流转,非法流转直接返回成功订单状态变更
乐观锁UPDATE 带版本/状态条件,0 行影响即重复并发更新

二、核心流程与注意点

  • 幂等键必须来自业务:订单号、支付流水号、用户请求号,而不是随机生成的无关字符串;
  • 占用要原子:先查再写有竞态,必须用 Redis SETNX 或数据库唯一索引一次写入判断;
  • 键要过期兜底:Redis 占位设置合理 TTL,防止客户端一直不提交导致键永久占用;
  • 重复请求返回首次结果:处理成功后缓存响应,重试时直接返回,避免下游重复扣款;
  • 超时重试用同一幂等键:网关或 SDK 层重试必须复用原请求标识;
  • 网关层聚合:SDK 或网关可自动为写请求生成并透传幂等键,业务侧无需每个接口重复实现;
  • 边界说明:幂等只约束同一个键的重复请求,不同键的请求并发修改同一资源时仍需配合乐观锁。

三、代码示例

-- 状态机校验:只有 CREATED 才能流转到 PAID,0 行影响说明已处理
UPDATE t_order SET status = 'PAID' WHERE id = ? AND status = 'CREATED';
# 幂等令牌:抢到令牌的请求才允许执行业务
redis-cli SETNX idem:order:1001 token-abc123
redis-cli EXPIRE idem:order:1001 60

常见追问 / 记忆点

  • 追问:幂等与并发控制是一回事吗?答:不是,幂等解决"同一请求重复执行"的副作用,并发控制解决"多个不同请求同时改同一数据"。
  • 追问:先查订单状态再决定是否处理够吗?答:不够,查与改之间仍有竞态,必须靠唯一约束或乐观锁兜底。
  • 追问:幂等键有效期怎么设?答:覆盖客户端最长重试周期即可,过短会漏判重复,过长会占用存储。
  • 记忆点:业务幂等键 + 原子占用 + 状态校验 + 响应缓存,四步构成完整幂等设计。
笔记加载中…