极高 进阶
幂等性设计#
一句话答案#
同一操作执行多次结果一致,方案:唯一请求 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