接口幂等设计的几种落地方式

Cold 发布于 2020-08-11 11 次阅读 396 字 预计阅读时间: 2 分钟 后端开发


用户连点两下提交,或者网络超时重试,同一个请求发了两次,订单就重复创建了。幂等就是解决这个问题的。

方案一:唯一索引

最简单可靠。给业务字段加唯一索引,重复插入直接报错,捕获后返回已存在。

ALTER TABLE orders ADD UNIQUE KEY uk_order_no (order_no);

适合「创建」类操作,但要求有天然唯一键,比如订单号、支付流水号。

方案二:Token 机制

  1. 前端打开页面时先请求一个 token
  2. 提交时带上 token
  3. 后端用 Redis SETNX 占位,成功才处理,失败说明重复提交
  4. 处理完删除 token 或设过期
$ok = $redis->set($token, 1, ['nx', 'ex' => 300]);
if (!$ok) {
    throw new Exception('请勿重复提交');
}
// 处理业务...
$redis->del($token);

方案三:状态机

比如订单状态从「待支付」到「已支付」,更新时加条件:

UPDATE orders SET status = 'paid' WHERE id = ? AND status = 'pending';

影响行数为 0 说明已经被处理过,直接返回成功。适合状态流转类业务。

方案四:分布式锁

用 Redis 或 ZooKeeper 加锁,锁住业务 key,处理完释放。适合并发高、需要互斥的场景,但要注意锁超时和误删问题。

怎么选

  • 有唯一业务键:唯一索引,最省事
  • 表单提交防重:Token
  • 状态流转:条件更新
  • 复杂并发:分布式锁

实际项目里往往是组合用,比如 Token 防前端重复提交 + 唯一索引兜底。

和喜欢的一切在一起~
最后更新于 2020-08-11