一、为什么需要幂等
网络不可靠:客户端重试、消息队列重投、网关超时重发,都会让同一个请求被处理多次。如果”扣款””下单”被重复执行,就是资损。幂等保证:同一请求执行一次和执行多次,业务结果一致。
二、常见实现方案
| 方案 | 做法 | 适用 |
|---|---|---|
| 唯一 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 要选稳定且唯一的业务标识,别用时间戳;
- 去重记录要设过期,避免表无限增长;
- 幂等和事务配合:插入流水与业务操作在同一事务里;
- 读接口天然幂等,重点防的是写接口。
幂等不是可选项,是分布式系统的”安全带”——上线前先问一句:这个接口重复调两次会怎样?