接口幂等设计:去重表、乐观锁、状态机、Token

一、为什么需要幂等

网络不可靠:客户端重试、消息队列重投、网关超时重发,都会让同一个请求被处理多次。如果”扣款””下单”被重复执行,就是资损。幂等保证:同一请求执行一次和执行多次,业务结果一致。

二、常见实现方案

方案 做法 适用
唯一 ID + 去重表 请求带唯一业务号,入库前查重,已处理直接返回 下单、支付
乐观锁 update … where version = ? 或 where status = ‘待处理’ 状态变更
状态机 只允许合法状态流转,重复事件被拒 订单生命周期
Token 机制 先取令牌,提交时校验并销毁,防重复提交 表单 / 前端

三、去重表示例

-- 建一张唯一约束的流水表
CREATE TABLE idempotent_log (
  biz_key   VARCHAR(64) PRIMARY KEY,
  created_at DATETIME
);

-- 处理前先插入,靠主键冲突拦住重复
INSERT INTO idempotent_log (biz_key, created_at)
VALUES (?, NOW());
-- 若报主键冲突,说明已处理,直接返回上次结果

四、乐观锁示例

UPDATE account
SET balance = balance - 100, version = version + 1
WHERE id = ? AND version = ?;
-- 影响行数为 0 说明并发已被别人改过,重试或失败

五、注意点

  • 幂等 key 要选稳定且唯一的业务标识,别用时间戳;
  • 去重记录要设过期,避免表无限增长;
  • 幂等和事务配合:插入流水与业务操作在同一事务里;
  • 读接口天然幂等,重点防的是写接口。

幂等不是可选项,是分布式系统的”安全带”——上线前先问一句:这个接口重复调两次会怎样?