← 返回题目列表

接口幂等性是什么?分布式系统中如何保证幂等?

高频 中等 第 9 / 26 题 更新于 2026/07/28
幂等去重分布式系统接口设计

简化版

接口幂等性是指同一个请求执行一次和执行多次,对业务结果的影响相同。分布式系统里网络超时、消息重复、客户端重试、MQ 至少一次投递都可能导致重复请求,所以写接口必须设计幂等。常见做法有唯一请求号、幂等表、数据库唯一索引、状态机约束、乐观锁、分布式锁、Token 防重复提交等。核心是识别“同一个业务请求”,并保证它只生效一次。

详细版

查询接口通常天然幂等,重复查询不会改变状态;写接口不一定幂等,比如重复创建订单、重复扣款、重复发券都会出问题。

保证幂等的关键是幂等键。客户端或上游为每次业务操作生成 requestId、orderNo、tradeNo 等唯一标识,服务端处理前先检查是否处理过。可以用数据库唯一索引避免重复插入,用幂等表记录请求状态,用状态机限制只能从待支付到已支付,用乐观锁保证版本推进。

工程上要注意并发重复请求、处理成功但响应丢失、处理中状态、幂等记录过期时间、失败是否允许重试等边界。幂等不是简单查一次再插入,必须依赖原子约束。

完整版教学

一、幂等性解决什么问题

分布式系统里,调用方经常无法确定请求到底有没有成功。比如客户端调用支付接口超时,可能是支付服务没收到请求,也可能是支付成功但响应在网络中丢了。如果客户端直接再发一次,而服务端没有幂等保护,就可能重复扣款。

幂等性的目标是让重复请求变得安全。同一个业务操作被执行多次,最终只产生一次业务效果。注意不是每次响应都必须完全一样,而是业务状态不能被重复改变。

二、哪些场景需要幂等

读接口通常天然幂等,比如查询订单详情。删除接口在很多设计里也可以做成幂等:删除已删除资源仍返回成功或资源不存在。最需要关注的是写接口,如创建订单、支付回调、发优惠券、扣库存、消息消费、任务调度。

MQ 场景尤其典型。很多消息队列提供至少一次投递,消费者可能收到重复消息。如果消费逻辑不是幂等,重复消息就会造成重复发货、重复积分、重复通知。面试中把“重试”和“消息重复”联系起来讲,会很加分。

三、幂等键和唯一约束

最常见方案是幂等键。一次业务操作生成一个全局唯一标识,比如 requestId、orderNo、paymentNo。服务端用这个标识判断是否已经处理过。如果已处理,直接返回之前结果或当前状态;如果未处理,才执行真正业务。

但判断和写入必须原子。不能先查数据库发现没有,再插入业务数据,因为两个并发请求可能同时查不到,然后都执行。正确做法是依赖数据库唯一索引、幂等表唯一键、Redis SETNX 或事务约束,让并发重复请求只有一个能抢到处理权。

四、幂等表怎么设计

幂等表通常记录幂等键、业务类型、处理状态、业务结果、创建时间和更新时间。状态可以有处理中、成功、失败。第一个请求插入处理中并执行业务;后续相同请求如果看到处理中,可以等待、返回处理中或稍后重试;看到成功则返回成功结果。

失败状态要谨慎。如果是参数错误这类确定失败,可以记录失败并重复返回;如果是系统异常或下游超时,可能允许重试继续推进。幂等记录还要设置合理过期或归档策略,避免无限增长。

五、状态机和乐观锁

很多业务天然适合用状态机保证幂等。比如订单只能从待支付变为已支付,已支付订单再次收到支付成功回调时,不再重复处理,只返回当前已支付状态。数据库更新可以写成 where status=‘WAIT_PAY’,只有第一次能更新成功。

乐观锁也常用,比如库存扣减时带 version 更新,或者使用唯一流水防止同一业务单重复扣减。状态机的好处是贴近业务语义,比单纯技术去重更可靠。

六、面试追问与工程边界

常见追问是分布式锁能不能保证幂等。分布式锁可以降低并发重复执行概率,但不是完整幂等方案。锁可能超时释放,请求可能处理成功后响应丢失,后续仍需要通过业务唯一键或状态判断结果。因此锁通常是辅助,不应替代持久化幂等记录。

另一个追问是 Token 防重复提交。Token 适合表单防连点:页面获取 token,提交时校验并删除。但它更偏前端交互防重,不能覆盖 MQ 重复、支付回调、服务间重试等后端场景。后端核心写接口仍要自己保证幂等。

七、落地设计清单

设计幂等接口时,可以按四步走。第一,定义业务唯一键,比如订单号、支付流水号、消息 ID、请求 ID。第二,确定幂等作用范围,同一个用户同一个请求 ID 是否唯一,还是全局唯一。第三,选择原子约束方式,比如数据库唯一索引、幂等表唯一键、Redis SETNX 加持久化校验、状态机条件更新。第四,确定重复请求返回策略,是返回首次结果、当前状态,还是处理中提示。

幂等表要保存足够信息。只保存 requestId 不够,最好有业务类型、业务主键、状态、结果摘要、错误原因、过期时间。处理中状态尤其重要,因为并发重复请求可能在第一个请求还没完成时到来。此时可以让后续请求短暂等待,也可以返回处理中,让客户端稍后查询。没有处理中状态,系统容易在并发下重复执行。

八、常见误区和数据一致性

第一个误区是把幂等做成“先查后写”。在并发场景下,两个请求可能同时查不到记录,然后都执行成功。可靠幂等必须依赖唯一索引、事务、条件更新或原子命令。第二个误区是只在客户端防重复点击。客户端 Token 能减少连点,但挡不住网络重试、MQ 重复投递、支付平台重复回调。

还要处理“成功但响应丢失”。服务端已经扣款成功,响应在网络中丢了,客户端重试时服务端必须能识别同一个请求并返回已成功,而不是再次扣款。幂等设计最终保护的是业务状态一致性,而不是单纯防止用户多点按钮。

九、常见误区与追问

这道题不能只背概念,要把「接口幂等设计」放回真实分布式系统里解释:谁发起、谁协调、状态如何变化、失败后怎么兜底,以及它和性能、可用性、一致性的取舍。

回答层次要讲清的内容容易漏掉的边界
核心结论幂等接口保证重复请求不产生重复副作用,是重试、回调和消息消费的基础治理能力不要停在名词解释
流程机制客户端携带幂等键 -> 服务端查去重表或业务唯一索引 -> 首次请求执行业务 -> 保存结果状态 -> 重复请求返回历史结果说明触发方、参与方、状态变化和兜底
工程取舍同一个 requestId 创建订单,第一次成功写订单,第二次应返回同一订单而不是新建一单治理组件是为了控制故障半径,不是让下游无限扛流量
接口幂等设计 面试拆解:
1. 客户端携带幂等键
2. 服务端查去重表或业务唯一索引
3. 首次请求执行业务
4. 保存结果状态
5. 重复请求返回历史结果

记忆钩子:先定位治理目标,再拆限流、熔断、降级、重试、追踪、灰度和幂等边界;回答时要紧扣「接口幂等设计」这道题,不要把相邻概念混成一段泛泛的分布式套话。

  • 误区:幂等就是加分布式锁。 锁控制并发窗口,幂等控制重复请求最终结果。
  • 误区:只在前端禁按钮就够。 后端重试、MQ 重投、第三方回调都会绕过前端。
  • 误区:幂等失败可以简单返回成功。 应返回与首次处理一致的业务结果,不能掩盖失败状态。
  • 追问:幂等键如何设计? 用业务请求号、订单号、支付流水号或消息 ID,避免随机每次变。
  • 追问:去重记录何时删除? 按业务周期设置 TTL 或归档,不能早于可能重试窗口。
  • 追问:并发首次请求怎么处理? 唯一索引、事务和状态机保证只有一个请求完成创建。

十、加强记忆

幂等就是“同一业务请求,多次执行只生效一次”。关键是幂等键和原子约束。常用方案有唯一请求号、幂等表、唯一索引、状态机、乐观锁、Token 和去重表。不要只说先查再插,真正可靠的是唯一约束、事务和业务状态机。