因为调用方为了保障音讯的发送是高可用的,所以会有重试机制。如果有这个场景:
服务 A 调用服务 B,此时第一个申请,因为网络起因,服务 B 提早收到了这个申请,或者服务 B 回复服务 A 的时候,服务 A 没收到,导致服务 A 又发送了雷同的申请。此时,服务 B 就又解决了一次申请,如果这个申请是对数据库进行操作的,比方对金额的扣减,那这麻烦可大了。
首先,咱们先看看接口是否须要幂等性。以下两个不须要保障幂等性:
- 如果只是查问操作,那无论调用多少次,返回的后果是一样的,所以查问操作不须要保障幂等性。
- 如果业务上容许,比方点赞个数是 10000 还是 10001 不太重要,那能够不须要保障幂等性。
基本上对数据库的新增、批改、删除都须要幂等性。
新增
新增的时候,惟一标识就是主键(分布式下的主键是怎么生成的?),所以只管屡次插入,胜利的只能一条数据,此时新增是幂等性的。如果此时主键是数据库生成的,那须要惟一索引防止插入反复数据,这个时候也是幂等性的。如果既须要数据库生成主键,也没有惟一索引,那这个幂等就没方法保障了。所以要保障新增的幂等,必须本人生成主键(举荐),或者创立惟一索引。
批改
批改分为两种状况(这边只思考申请重试,不思考并发的状况,并发在分布式锁中探讨),一个是间接赋值,一个是绝对赋值。
# 间接赋值
update table set num=5 where id=1;
# 绝对赋值
update table set num=num-1 id=1;
如果是间接赋值的,不论给 num 赋值多少次 5,后果还是 5,那如果是绝对赋值的,此时就会始终减 1。此时应该先从数据库查问出 num,失去后果为 5,服务 A 计算 num-1,再把后果 4 传给服务 B,服务 B 不论执行多少次 set num= 4 都一样,这样就是幂等的。
删除
删除也分两种状况,一个是指定值删除,一个是范畴值删除。
# 间接赋值
delete from table where id=1;
# 绝对赋值
delete from table order by id desc limit 3;
如果是指定值删除,第一次删除返回 1,第二次删除返回 0,不论执行几次,数据库都没有 id= 1 的信息,所以是幂等的。
如果是范畴值删除,第一次执行删除 3 个,第二次执行又删除 3 个,这样就不是幂等的。办法跟下面相似,先把须要删除的 id 查问进去,失去 10,9,8,而后把须要删除的 id(10,9,8)传给服务 B,服务 B 不论删除几次 id(10,9,8),数据库都没有 id(10,9,8)的信息,也没有额定多删除其余的信息,所以是幂等的。