面试知识库
极高 进阶

幂等性设计#

一句话答案#

同一操作执行多次结果一致,方案:唯一请求 ID + 去重表、Token 机制、乐观锁 version、业务状态机。

核心要点

常见方案:

方案适用
唯一请求ID + 去重表通用
Token 机制表单提交防重
乐观锁(version)更新操作
状态机有状态流转的业务

数据库层: INSERT ... ON DUPLICATE KEY / 唯一索引

面试回答(2分钟版)

幂等性是指同一个操作执行一次和执行多次产生的效果完全一致。在分布式系统中由于网络重试、MQ重复投递、用户重复点击等场景,幂等性设计非常关键。我总结有四种主要方案。第一是唯一请求ID加去重表,这是最通用的方案,客户端生成全局唯一requestId,服务端在处理前先查去重表判断是否已处理过,可以用Redis的SETNX或数据库唯一索引实现。第二是Token机制,适合表单防重复提交,先从服务端获取一次性Token,提交时携带Token,服务端校验后立即删除。第三是乐观锁,在UPDATE操作中带上version条件,比如UPDATE SET amount=amount-100, version=version+1 WHERE version=当前版本,版本不匹配则更新失败实现幂等。第四是业务状态机,利用状态只能单向流转的特性,比如订单状态从待支付到已支付到已发货,已支付状态下重复的支付请求直接拒绝。需要注意INSERT和a=a+1这类操作天然不幂等,需要通过唯一索引或其他机制显式保证。

追问与易错

追问方向:

  • “幂等和去重一样吗?”→ 去重是幂等的一种实现手段(如唯一键去重),但幂等含义更广,状态机(只允许合法状态转换)和乐观锁(version 条件更新)也是幂等
  • “乐观锁实现幂等的限制?”→ 只适合更新操作(UPDATE SET version=version+1 WHERE version=X),不适合插入操作;高并发下失败率高需要配合重试机制
  • “你项目的幂等怎么做的?”→ 结合项目讲,如订单创建用唯一订单号做去重表、支付回调用状态机(待支付→已支付只能单向转换)、库存扣减用乐观锁 version

易错点:

  • ❌ 数据库自动保证幂等——INSERT 和 a=a+1 不是幂等的
  • ❌ 加了唯一索引就幂等——只解决 INSERT