什么是幂等性?
幂等性(Idempotency)是一个数学概念,翻译成大白话就是:不管你做多少次同样的操作,结果都跟做一次一样。
听起来有点抽象?举个生活中的例子。
你按电梯的楼层按钮。按一下,电梯会记住你要去这层。就算你按了十下、一百下,电梯也不会多来一趟——它只会来一次。这就是幂等的。
再举个例子。你往自动售货机里投了五块钱买饮料。投一次,机器出饮料。投两次,还是只出一瓶。机器不会因为你多投了钱就多给你一瓶。这也是幂等。
但如果反过来呢?你每次按按钮,银行就往你账户里扣一百块。那你连按十下,就扣了一千块。这就不是幂等的。
幂等性有什么用?
在软件开发中,幂等性特别重要,尤其是在网络世界里。
网络不可靠。你可能点了"支付"按钮,但网络卡了一下,按钮没反应。你会忍不住再点一次。如果支付接口不是幂等的,你的卡可能被扣两次钱。
幂等性就是为了解决这类问题而生的。它让系统在面对重复请求时依然安全。
常见的应用场景:
- 支付系统:用户重复点击支付按钮,只能扣一次钱
- 消息队列:消息被重复投递时,消费者能正确处理
- 分布式系统:服务间调用可能重试,需要保证结果一致
- 表单提交:防止用户刷新页面导致重复提交
哪些操作天然幂等?
不是所有操作都是幂等的。区分一下:
幂等操作(做多少次都一样):
- GET 查询数据:查十次和查一次结果相同
- PUT 更新资源:把名字改成"小明",改十次还是"小明"
- DELETE 删除资源:删十次,第一次删掉,后面九次返回"已不存在"
- 设置变量:
x = 1,执行一百次,x 还是 1
非幂等操作(做多次结果不同):
- POST 创建资源:创建订单,发十次就生成十个订单
- 转账:转一百块给别人,转十次就转出去一千块
- 累加操作:计数器加一,加十次就加了十
怎么实现幂等性?
有几种常见做法。
第一种:唯一请求 ID
每个请求带一个唯一的 ID。服务端收到请求后,先检查这个 ID 是否处理过。处理过了就直接返回之前的结果,不再重复执行。
就像你去餐厅点餐,服务员给你一个取餐号。即使你拿着同一个取餐号去催单三次,厨房也不会再做一份。
第二种:条件判断
在执行操作前,先判断条件是否满足。比如转账前先查余额够不够,或者检查这笔交易是否已经存在。
第三种:数据库唯一约束
在数据库层面设置唯一索引。比如订单号必须唯一,重复插入就会报错。这样从根源上防止了重复。
第四种:状态机
把资源设计成状态机。比如订单只有"待支付"→“已支付"两种状态。已支付的订单不能再变回待支付,自然就不会重复扣款。
HTTP 里的幂等性
HTTP 协议本身对幂等有明确定义:
- GET、PUT、DELETE 是幂等的
- POST 通常不是幂等的
这也是为什么查询数据用 GET,更新数据用 PUT,创建数据用 POST。每种方法都有它的语义。
不过要注意,HTTP 方法只是约定,具体实现还是要看你的代码怎么写。
总结
幂等性不是什么高深的技术,而是一种思维方式:在不可靠的网络环境中,假设一切都会出错,然后设计出能容忍错误的系统。
它不是银弹。实现幂等性需要额外的设计和存储开销。但在关键业务场景里——尤其是涉及钱的——幂等性几乎是必选项。
下次你看到某个接口说自己是"幂等的”,你就知道:这个接口不怕你重复调用,放心点。