🏠 首页 攻略 幂等性是什么?保证重复操作不翻车的关键设计原则

幂等性是什么?保证重复操作不翻车的关键设计原则

为什么支付接口不怕重复提交?因为用了幂等性设计。一文讲清这个让系统更稳定的核心概念。

什么是幂等性?

幂等性(Idempotency)是一个数学概念,翻译成大白话就是:不管你做多少次同样的操作,结果都跟做一次一样。

听起来有点抽象?举个生活中的例子。

你按电梯的楼层按钮。按一下,电梯会记住你要去这层。就算你按了十下、一百下,电梯也不会多来一趟——它只会来一次。这就是幂等的。

再举个例子。你往自动售货机里投了五块钱买饮料。投一次,机器出饮料。投两次,还是只出一瓶。机器不会因为你多投了钱就多给你一瓶。这也是幂等。

但如果反过来呢?你每次按按钮,银行就往你账户里扣一百块。那你连按十下,就扣了一千块。这就不是幂等的。

幂等性有什么用?

在软件开发中,幂等性特别重要,尤其是在网络世界里。

网络不可靠。你可能点了"支付"按钮,但网络卡了一下,按钮没反应。你会忍不住再点一次。如果支付接口不是幂等的,你的卡可能被扣两次钱。

幂等性就是为了解决这类问题而生的。它让系统在面对重复请求时依然安全。

常见的应用场景:

  • 支付系统:用户重复点击支付按钮,只能扣一次钱
  • 消息队列:消息被重复投递时,消费者能正确处理
  • 分布式系统:服务间调用可能重试,需要保证结果一致
  • 表单提交:防止用户刷新页面导致重复提交

哪些操作天然幂等?

不是所有操作都是幂等的。区分一下:

幂等操作(做多少次都一样):

  • GET 查询数据:查十次和查一次结果相同
  • PUT 更新资源:把名字改成"小明",改十次还是"小明"
  • DELETE 删除资源:删十次,第一次删掉,后面九次返回"已不存在"
  • 设置变量:x = 1,执行一百次,x 还是 1

非幂等操作(做多次结果不同):

  • POST 创建资源:创建订单,发十次就生成十个订单
  • 转账:转一百块给别人,转十次就转出去一千块
  • 累加操作:计数器加一,加十次就加了十

怎么实现幂等性?

有几种常见做法。

第一种:唯一请求 ID

每个请求带一个唯一的 ID。服务端收到请求后,先检查这个 ID 是否处理过。处理过了就直接返回之前的结果,不再重复执行。

就像你去餐厅点餐,服务员给你一个取餐号。即使你拿着同一个取餐号去催单三次,厨房也不会再做一份。

第二种:条件判断

在执行操作前,先判断条件是否满足。比如转账前先查余额够不够,或者检查这笔交易是否已经存在。

第三种:数据库唯一约束

在数据库层面设置唯一索引。比如订单号必须唯一,重复插入就会报错。这样从根源上防止了重复。

第四种:状态机

把资源设计成状态机。比如订单只有"待支付"→“已支付"两种状态。已支付的订单不能再变回待支付,自然就不会重复扣款。

HTTP 里的幂等性

HTTP 协议本身对幂等有明确定义:

  • GET、PUT、DELETE 是幂等的
  • POST 通常不是幂等的

这也是为什么查询数据用 GET,更新数据用 PUT,创建数据用 POST。每种方法都有它的语义。

不过要注意,HTTP 方法只是约定,具体实现还是要看你的代码怎么写。

总结

幂等性不是什么高深的技术,而是一种思维方式:在不可靠的网络环境中,假设一切都会出错,然后设计出能容忍错误的系统。

它不是银弹。实现幂等性需要额外的设计和存储开销。但在关键业务场景里——尤其是涉及钱的——幂等性几乎是必选项。

下次你看到某个接口说自己是"幂等的”,你就知道:这个接口不怕你重复调用,放心点。