1、幂等性基础:什么是幂等性、为什么重试需要幂等、幂等性的数学定义与工程定义

1.1 先聊聊我理解的幂等性

幂等性,说白了就是——同一个操作,执行一次和执行多次,结果是一样的。

举个例子。你去自动售货机买水,扫码支付了 5 块钱。机器出一次水,这叫正常。但如果网络卡了一下,你扫了两次码,扣了两次钱,机器却只出一瓶水——你肯定不干。反过来,如果扣了一次钱,机器出了两瓶水,商家也不干。

嗯,这里的关键就是:支付接口必须是幂等的。不管用户点了几次「确认支付」,最终只扣一次钱,只出一瓶水。

我在项目中遇到过最典型的场景,就是订单系统。用户下单时前端防重复提交做得再好,也防不住后端重试、MQ 消息重复消费、网关超时重发。你想想看,一个订单如果因为网络抖动被创建了两次,仓库就得发两件货,财务就得退一次款——全是线上事故。

幂等性的核心价值:让系统在面对重复请求时,表现得像只处理了一次。

1.2 为什么重试必须考虑幂等

重试是分布式系统里最常用的容错手段。服务调用超时了,重试;数据库写冲突了,重试;消息消费失败了,重试。但重试有个天然的问题——你没法区分「请求没到」和「请求到了但响应丢了」。

我举个例子你就明白了:

  1. 客户端调用支付接口,超时了。
  2. 客户端重试,再次调用支付接口。
  3. 实际上第一次调用已经成功了,只是响应在网络中丢了。
  4. 第二次调用如果没做幂等处理,就会重复扣款。

这就是重试带来的「重复执行」风险。所以,凡是可能被重试的接口,都必须设计成幂等的。这不是可选项,是必选项。

我曾经踩过的坑:早期做支付回调时,没考虑幂等,结果银行回调重试了三次,我们系统就发了三笔账。对账时发现多了两笔,差点背 P0 事故。从那以后,我所有写接口的第一条设计原则就是——先幂等,再业务。

1.3 数学定义 vs 工程定义

聊完直觉,咱们上点硬货。幂等性其实有严格的数学定义,也有更实用的工程定义。两者都得懂。

数学定义

在数学里,幂等性是这样定义的:

对于函数 f,如果 f(f(x)) = f(x) 对所有 x 成立,则 f 是幂等的。

什么意思?就是你把一个值丢进函数,得到结果;再把结果丢进去,结果不变。典型的例子是值函数:abs(abs(-5)) = abs(-5) = 5。

在计算机科学里,这个定义被扩展到了操作上:

对于操作 op,如果 op(op(state)) = op(state),则 op 是幂等的。

说白了,就是操作多次后的系统状态,和操作一次后的系统状态完全一致。

工程定义

工程上的定义更接地气:

一个接口,使用相同的请求参数调用多次,产生的副作用与调用一次相同。

注意这里的关键词是「副作用」。查询接口天然幂等,因为没副作用。但写接口就不一定了——创建订单、扣减库存、转账汇款,这些都有副作用。

我习惯把工程幂等分成两类:

类型 定义 例子
天然幂等 操作本身多次执行结果一致 DELETE /users/123(删除一次和删除多次,结果都是用户不存在)
强制幂等 通过业务逻辑保证多次执行结果一致 创建订单时用唯一流水号去重,重复请求直接返回已有结果

我个人习惯:所有写接口都按「强制幂等」来设计。天然幂等的情况太少,而且业务一变就可能不幂等了。与其事后补,不如一开始就上幂等方案。

1.4 一张图看懂幂等性核心逻辑

下面这张图,是我自己总结的幂等性判断流程。每次设计新接口时,我都会过一遍这个逻辑:

幂等性判断与设计流程 收到请求 操作是否天然幂等? 是 直接执行,无需额外处理 否 需要幂等方案 选择幂等方案 常见幂等方案 • 唯一流水号 + 去重表 • 乐观锁 / 版本号 • 状态机 + 前置状态校验 返回结果

这个流程的核心就两点:先判断是不是天然幂等,如果不是,就上强制幂等方案。别偷懒,也别想当然。

1.5 幂等性设计的三个层次

我习惯把幂等性设计分成三个层次,从浅到深:

  • 接口层:通过请求唯一标识(如幂等键、流水号)来去重。这是最常用的方式。
  • 业务层:通过业务状态机来保证。比如订单状态从「待支付」到「已支付」只能流转一次。
  • 存储层:通过数据库约束来保证。比如唯一索引、乐观锁、分布式锁。

这三个层次不是互斥的,而是互补的。我一般建议三层都做——接口层挡掉大部分重复请求,业务层兜住状态异常,存储层做最后一道防线。

一个小建议:设计幂等方案时,先想清楚「什么算重复」。是同一个用户、同一个流水号、还是同一个请求体?定义清楚了,方案才能落地。

1.6 本章小结

幂等性不是什么高深的概念,但它是分布式系统的基石之一。重试是刚需,幂等是重试的前提。没有幂等性的重试,就是在给线上埋雷。

记住三句话:

  • 幂等 = 多次执行 = 一次结果
  • 所有可能被重试的接口,都必须幂等
  • 先判断天然幂等,不行就上强制方案