当前位置:网站首页>接口幂等设计

接口幂等设计

2020-11-10 16:01:23 大军

由于调用方为了保证消息的发送是高可用的,所以会有重试机制。假如有这个场景:
服务A调用服务B,此时第一个请求,由于网络原因,服务B延迟收到了这个请求,或者服务B回复服务A的时候,服务A没收到,导致服务A又发送了相同的请求。此时,服务B就又处理了一次请求,如果这个请求是对数据库进行操作的,比如对金额的扣减,那这麻烦可大了。
image.png
首先,我们先看看接口是否需要幂等性。以下两个不需要保证幂等性:

  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都一样,这样就是幂等的。
image.png

删除

删除也分两种情况,一个是指定值删除,一个是范围值删除。

# 直接赋值
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)的信息,也没有额外多删除其他的信息,所以是幂等的。
image.png

版权声明
本文为[大军]所创,转载请带上原文链接,感谢
https://segmentfault.com/a/1190000037786746