接口对接中被重复调用、或者调用失败之后没有后续处理,结果就是数据对不上。解决这类问题,通常要从两头入手:入口处保证同一请求重复到达也只生效一次,也就是幂等;出口处对执行失败或状态不明的操作安排重试或人工介入,也就是补偿。下面按场景给出几种常见方案,并说明各自的代价与取舍。
场景一:外部渠道重复推送订单或支付结果
渠道侧的重试策略往往不受我们控制,同一个业务单号可能在几分钟内到达多次。这类场景对实时性要求高,但每次请求携带的业务标识是稳定的。
候选方案:基于唯一业务键的去重表
- 做法:在数据库中为对接单号建立唯一约束,第一次写入成功后,后续相同请求直接返回已有结果,不再执行业务逻辑。
- 优点:实现直接,数据库本身就能保证唯一性,不依赖中间件;对接口代码改动小。
- 代价:每次请求都会多一次数据库写操作,高峰期对数据库有一定压力;历史去重记录需要定期清理或归档。
- 适用边界:请求量中等、渠道标识稳定的场景,比如支付回调、订单创建通知。
如果单号不是渠道直接给的,而是由我们生成的,建议把生成规则固定下来,避免同一笔业务因为路径不同产生两个单号。
场景二:内部系统之间调用,需要控制状态流转
内部调用通常可以约定接口语义,比如查询、创建、状态变更分开设计。麻烦往往出在状态变更这一步:同一个请求到达两次,系统状态就被改了两遍。
候选方案:状态机加版本号
- 做法:业务对象带一个状态字段和版本号,每次变更都要求客户端带上当前版本;版本不匹配就拒绝,由调用方重新查询后再提交。
- 优点:不依赖额外存储,天然能挡住重复变更;状态流转清晰,出问题时容易定位。
- 代价:调用方需要处理冲突重试;对接口契约要求高,双方都要遵守。
- 适用边界:流程审批、订单状态推进这类状态有限且变更需要明确的场景。
状态机的设计建议在需求调研阶段就定下来,避免开发后期再补充。我们做过的同类项目见同类项目案例,其中不少涉及内部系统状态同步。
场景三:跨系统写入,本地事务无法覆盖远程调用
本地数据库写成功了,远程接口调用失败,这时本地和远端就不一致。这类问题不能靠单次重试解决,需要有持续补偿的机制。
候选方案:本地消息表加定时补偿
- 做法:本地事务里同时写业务数据和一条待投递消息;由独立的任务按固定节奏把消息投递到目标系统,成功后标记完成,失败则按间隔重试,超过次数转入人工处理队列。
- 优点:本地事务和消息投递在一个事务里,不会出现业务写入成功但消息丢失;重试逻辑集中,容易监控。
- 代价:需要额外的消息表和调度任务;消息表与业务表在同一个库,长期运行要考虑容量;补偿任务的设计要避免重复投递。
- 适用边界:跨系统写入且不允许长期不一致的场景,比如财务、库存、物流节点回传。
补偿任务本身也需要幂等,否则补偿会变成新的重复来源。需要具体实施方案时,可以参考我们的软件定制开发与系统集成服务。
什么情况下不要选这些方案
不是所有接口都需要做幂等与补偿,过度设计会拖慢交付节奏。
- 纯查询接口、对数据没有写操作的,不需要幂等链路,做好缓存和超时即可。
- 只调一次、失败后人工处理的内部小工具,没必要引入消息表和调度任务,会增加维护面。
- 业务本身允许重复记录的,比如日志上报、行为埋点,去重逻辑反而会带来额外开销。
- 对一致性要求不高、可以按天对账抹平的场景,优先考虑对账而不是逐笔补偿。
判断依据可以简化为两点:这次写入是否会影响资金、库存或对外的状态告知;以及重复写入之后能不能靠后续对账快速发现。两个答案都是否,就可以不做。
另外,国产 OA 与 ERP、HR、财务系统对接时,流程数据和单据状态往往要双向同步,幂等和补偿通常需要和组织权限体系一起梳理,不只是在接口层面加个去重表。具体改造范围可以看政府与国企国产化改造案例中的思路。
决策建议与文字版对比清单
选型没有统一答案,建议按写入影响面和调用频率两条线快速判断,再决定投入多少工程量。
- 先确认唯一业务键从哪来,渠道给的优先用渠道的,自己生成的要有稳定规则。
- 再确认重复写入的后果,影响资金或对外状态的,优先强调幂等;只影响内部统计的,可以用对账兜底。
- 最后确认补偿由谁负责,能自动重试的自动重试,超过阈值的落人工队列,避免无限重试打爆下游。
文字版对比清单如下。
- 去重表 → 适合外部渠道回调、单号稳定 → 主要代价是数据库写入压力和记录清理。
- 状态机加版本号 → 适合内部状态流转、审批流程 → 主要代价是接口契约和调用方冲突处理。
- 本地消息表加补偿 → 适合跨系统写入、不允许长期不一致 → 主要代价是调度任务和维护成本。
- 只做对账不加补偿 → 适合可容忍短时不一致、按周期核对的场景 → 主要代价是问题发现滞后。
常见问题
问:幂等和补偿必须一起做吗?
不一定。写入影响小、可以靠对账发现的问题,可以先做幂等,把重复提交挡住,补偿后续再补。
问:接口已经做了超时重试,还需要幂等吗?
需要。重试次数越多,重复到达的概率越大,没有幂等兜底,重试本身就是重复写入的来源。
问:补偿任务重试到什么时候停?
建议设置最大重试次数,超过后标记为待处理并通知负责人。无限重试会掩盖问题,也会持续占用下游资源。
问:怎么验收幂等是否生效?
可以用同一个业务单号连续发起多次相同请求,观察业务数据是否只产生一条、返回结果是否一致,并在日志里能查到对应的去重记录。部署和运维阶段的排查方法,可以参考更多技术实现细节。