什么是幂等

在我们编程中常见幂等
select查询天然幂等
delete删除也是幂等,删除同一个多次效果一样
update直接更新某个值的,幂等
update更新累加操作的,非幂等
insert非幂等操作,每次新增一条
产生原因
由于重复点击或者网络重发 :
点击提交按钮两次;
点击刷新按钮;
使用浏览器后退按钮重复之前的操作,导致重复提交表单;
使用浏览器历史记录重复提交表单;
浏览器重复的HTTP请;
nginx重发等情况;
分布式RPC的try重发等;
什么情况需要处理幂等
对于数据只能处理有且仅有一次的业务场景,例如:支付订单,扣费的操作。对于同一个订单号,只能扣费一次。不论是经过接口调用,还是通过mq消费消息,已经扣费了,如果有相同的请求过来,必须保证最终扣费结果一致。
一般导致重复提交的场景:
前端用户重复提交:客户端卡顿,用户习惯多次点击页面按钮导致同一时间多次提交。
调用接口超时重试:调用接口是如果遇到网络抖动,导致请求发出了,返回接受超时,这时调用者并不知道执行结果,进行了重试。
MQ消费重复:消费端消费消息超时,消息重新入队,MQ将消息发送到其他消费端。
如何实现接口幂等
token
对于用户的重复提交,可以使用token机制避免。在后端生成全局唯一的token,存放在redis,前端请求带上token,后端接口接受到携带的token,判断redis是否存在,存在则删除并进行业务处理,不存在则表示token已处理过,是重复请求,不做处理。
唯一标识
对于存在唯一标识的业务场景,在建表时需要建立唯一索引避免重复提交带来的脏数据。例如:用户名唯一,对用用户名做唯一索引约束。订单支付表,对订单id做唯一索引约束。
乐观锁
通过判断更新时的数据是否跟当前预期更新的数据一致,即CAS原理,不一致则根据业务提示失败,一致才更新。例如:使用更新时间判断数据是否被修改,判断是否跟查询时拿到的更新时间一致。update table1 set name='123' where id=1 and update_time='2021-05-20 00:00:00';
状态机
在设计单据相关的业务,或者是任务相关的业务,肯定会涉及到状态机(状态变更图),就是业务单据上面有个状态,状态在不同的情况下会发生变更,一般情况下存在有限状态机
如果状态机已经处于下一个状态,这时候来了一个上一个状态的变更,理论上是不能够变更的,这样的话,保证了有限状态机的幂等。
注意:订单等单据类业务,存在很长的状态流转,一定要深刻理解状态机,对业务系统设计能力提高有很大帮助。
分布式锁
通过第三方的系统(redis或zookeeper),在业务系统插入数据或者更新数据,获取分布式锁,然后做操作,之后释放锁。




