因为调用方为了保障音讯的发送是高可用的,所以会有重试机制。如果有这个场景:
服务A调用服务B,此时第一个申请,因为网络起因,服务B提早收到了这个申请,或者服务B回复服务A的时候,服务A没收到,导致服务A又发送了雷同的申请。此时,服务B就又解决了一次申请,如果这个申请是对数据库进行操作的,比方对金额的扣减,那这麻烦可大了。

首先,咱们先看看接口是否须要幂等性。以下两个不须要保障幂等性:

  1. 如果只是查问操作,那无论调用多少次,返回的后果是一样的,所以查问操作不须要保障幂等性。
  2. 如果业务上容许,比方点赞个数是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)的信息,也没有额定多删除其余的信息,所以是幂等的。