分布式场景下接口幂等性保证方案 幂等性指同一个请求执行一次和执行多次的结果完全一致不会因为重复调用产生脏数据、重复扣款、重复下单等问题。分布式系统中网络超时、重试机制、前端重复提交、消息重复消费都会导致接口被重复调用必须强制保证幂等性。我会从核心原理、适用场景、实现方案、最佳实践四个维度给你最完整、可落地的总结。一、先明确哪些接口必须做幂等非幂等接口执行多次会改变数据状态新增接口insert扣款/扣库存/支付接口提交订单接口发送消息/推送接口天然幂等接口执行多次无影响查询接口select修改指定状态的接口set status1删除指定ID接口delete where id1二、分布式幂等性 6 种主流实现方案按推荐优先级排序1. 唯一索引 / 唯一约束最简单、最推荐核心思想利用数据库唯一索引天然防重复重复插入会直接报错业务捕获异常即可。适用场景用户注册手机号唯一订单创建订单号唯一日志/流水表插入实现步骤给业务唯一字段订单号、手机号、业务编号建唯一索引插入时捕获DuplicateKeyException捕获后直接返回成功视为幂等处理优点实现最简单、无侵入、可靠性高缺点只适用于插入场景不适合更新/扣款场景2. 分布式锁Redis / Zookeeper核心思想重复请求进来时只有一个能拿到锁执行其他请求直接拦截。适用场景高并发秒杀、库存扣减支付、退款所有需要强防重的写操作实现步骤Redis 最常用请求携带唯一标识订单号、用户ID业务号先尝试SETNX加锁设置过期时间加锁成功 → 执行业务加锁失败 → 直接返回“重复请求”/幂等成功关键必须用Redis 原子操作防止锁超时、死锁。优点适用范围极广、性能好缺点需要引入 Redis有锁超时风险3. 前端 Token 机制最通用、企业标准方案核心思想先获取 Token再用 Token 请求Token 一次性有效。适用场景表单提交订单、支付前端防重复点击 后端防重复提交完整流程进入页面时前端请求后端生成全局唯一 Token存在 Redis页面渲染时把 Token 隐藏带入表单提交接口时必须携带 Token后端使用Redis DEL原子操作删除 Token删除成功 → 放行执行业务删除失败 → 说明重复请求直接返回为什么用 DEL原子操作绝对保证只执行一次比 GET DELETE 更安全不会出现并发问题优点覆盖全场景、无业务侵入、最安全缺点多一次请求获取 Token4. 状态机幂等业务状态流转控制核心思想只有当前状态允许才能流转到下一个状态重复请求会被状态拦截。适用场景订单流程待支付 → 已支付 → 已发货审批流程所有有明确状态流转的业务示例 SQLUPDATEorderSETstatus2WHEREid?ANDstatus1;状态1待支付才能改成 2已支付重复执行时条件不满足更新行数0直接返回优点业务天然幂等、无额外组件依赖缺点只适用于有状态流转的业务5. 悲观锁 / 乐观锁1悲观锁数据库锁SELECT*FROMtableWHEREid?FORUPDATE;同一数据同一时间只能一个请求操作适用于低并发、强一致性场景不推荐分布式高并发2乐观锁版本号机制UPDATEtableSETamountamount-1,versionversion1WHEREid?ANDversion?;版本号匹配才执行高并发性能好适用于扣款、库存更新6. 全局唯一请求号上游传入核心思想上游调用方传入全局唯一 requestId后端存储并校验。适用场景微服务之间调用第三方回调支付回调MQ 消息消费实现用 requestId 作为唯一键存入 Redis/DB存在则直接返回不存在则执行三、方案选型速查表直接照抄用方案适用场景优点缺点推荐指数唯一索引插入、防重复数据简单、可靠仅插入⭐⭐⭐⭐⭐Token 机制表单提交、订单、支付通用、安全多一次请求⭐⭐⭐⭐⭐分布式锁高并发、扣款、秒杀性能好需 Redis⭐⭐⭐⭐状态机订单/流程状态流转无侵入业务限定⭐⭐⭐⭐乐观锁更新、扣库存高并发需版本字段⭐⭐⭐悲观锁低并发强一致简单性能差⭐四、企业级最佳实践必看查询接口天然幂等不用处理插入优先用唯一索引订单/支付/表单提交 必用 Token 机制高并发扣减 用分布式锁 乐观锁状态流转业务 用状态机控制所有幂等控制必须是原子操作Redis SET/DEL、数据库唯一索引/行锁重复请求不抛异常直接返回成功幂等语义五、伪代码示例Token 方案最常用// 1. 获取 Token 接口StringgetToken(){StringtokenUUID.randomUUID().toString();redis.set(token,token,5,TimeUnit.MINUTES);// 5分钟过期returntoken;}// 2. 业务提交接口幂等核心Resultsubmit(Stringtoken,Orderorder){// 原子删除成功第一次请求失败重复请求Booleansuccessredis.delete(token);if(!success){returnResult.success(重复请求已幂等处理);}// 正常执行业务orderService.save(order);returnResult.success(提交成功);}总结幂等性 一次请求和多次请求结果一致分布式下最通用方案Token 机制最简单方案数据库唯一索引高并发方案Redis 分布式锁所有实现必须基于原子操作才能保证绝对安全