转自:https://learnku.com/articles/50902
1.概念
在编程中,一个幂等操作的特点是其任意多次执行 所产生的影响均与一次执行 的影响相同。幂等函数或幂等方法是指可以使用相同参数重复执行,并能获得相同结果的函数 / 方法。这些函数 / 方法不会影响系统状态,因此不用担心重复执行会对系统造成改变。
比如,用户发起一笔付款请求,就应该只扣用户一次钱,即使遇到网络重发或系统 bug 重发请求,也应该之扣一次钱。
增删改查都应该是幂等的。
- 新增时通过主键的唯一性索引控制不能插入重复的;
- 修改时通过悲观锁、乐观锁、分布式锁。
//状态机幂等不太懂。
2.分布式下如何保证接口幂等
https://www.zhihu.com/question/27744795
防重设计
和 幂等设计
,其实是有区别的。防重设计主要为了避免产生重复数据,对接口返回没有太多要求。而幂等设计除了避免产生重复数据 之外,还要求每次请求都返回一样的结果。
- insert前先select;但不适用于并发场景,仍会产生重复数据。
- 加悲观锁。即利用innoDB针对索引加行锁,select时for update;但事务如果耗时较长,会造成大量的请求等待,影响接口性能,每次请求接口很难保证都有相同的返回值,所以不适合幂等性设计场景,但是在防重场景中是可以的使用的。
- 加乐观锁。利用时间戳或者version字段,update时先where判断。
- 加唯一索引。
- 建防重表。
- 根据状态机。很多时候业务表是有状态的,比如订单表中有:1-下单、2-已支付、3-完成、4-撤销等状态。如果这些状态的值是有规律的,按照业务节点正好是从小到大,我们就能通过它来保证接口的幂等性。
- 加分布式锁。通过redis,检查Redis 中的 Key是否存在。
重试操作可交给专门的重试队列去处理。
3.去重和幂等
https://www.zhihu.com/question/27744795/answer/2362919418
- 「去重」是对请求或者消息在「一定时间内」进行去重「N次」;
- 「幂等」则是保证请求或消息在「任意时间内」进行处理,都需要保证它的结果是一致的;
- 不论是「去重」还是「幂等」,都需要对有一个「唯一 Key 」,并且有地方对唯一Key进行「存储」。
布隆过滤器:
布隆过滤器的底层数据结构可以理解为bitmap位图,bitmap也可以简单理解为是一个数组,元素只存储0和1,所以它占用的空间相对较小;当一个元素要存入bitmap时,其实是要去看存储到bitmap的哪个位置,这时一般用的就是哈希算法,存进去的位置标记为1;标记为1的位置表示存在,标记为0的位置标示不存在。
- 布隆过滤器是可以以较小的空间占用来判断元素是否存在进而用于去重,但是它也有对应的缺点;
- 只要使用哈希算法离不开「哈希冲突」,导致有存在「误判」的情况。
至于幂等,一般的存储还是「Redis」和「数据库」,最常见的还是唯一索引。