当前位置: 首页 - 科技 - 微服务架构之幂等性问题及设计思想 你不得不知的一些幂等方案

微服务架构之幂等性问题及设计思想 你不得不知的一些幂等方案

2025-01-08 科技 0

微服务架构之幂等性问题及设计思想 你不得不知的一些幂等方案

前言

小伙伴们有没有遇到过生产环境经常出现过重复的资料?在排查问题的时候,资料又是正常的。这个是何解呢?怎么会出现这种情况,而且还很难排查问题。今天我给大家分享一下这里的原因,以及解决方案。

罪魁祸首

产生重复资料或资料不一致(假定程式业务程式码没问题),绝大部分就是发生了重复的请求重复请求是指同一个请求因为某些原因被多次提交。导致这个情况会有几种场景

1)微服务场景,在我们传统应用架构中呼叫界面,要么成功,要么失败。但是在微服务架构下,会有第三个情况【未知】,也就是超时。如果超时了,微服务框架会进行重试。2)使用者互动的时候多次点选。如:快速点选按钮多次。3)MQ讯息中介软件,讯息重复消费4)第三方平台的界面(如:支付成功回拨界面),因为异常也会导致多次异步回拨 5)其他中介软件/应用服务根据自身的特性,也有可能进行重试。

我们知道了发生的原因,本质就是多次请求了,那如何解决呢?

幂等性

有些小伙伴们会想到幂等这个词,是的,就是我们在设计某些界面时,要考虑如何保证界面幂等,那什么是界面幂等呢?

网上是这样介绍的【界面的幂等性实际上就是界面可重复呼叫,在呼叫方多次呼叫的情况下,界面最终得到的结果是一致的

网上的说法定义,有点不是太正确,我们看下怎么不正确

一个执行绪请求使用者列表界面:select * from user,返回使用者表中的资料,而另一个执行绪往使用者表插入资料。那请求使用者列表的执行绪返回的资料每次都不一样,那按照上面的说法,查询使用者列表的界面就不是幂等的,这显然是不正确的。

老顾的理解应该是多次呼叫对系统的产生的影响是一样的,即对资源的作用是一样的,但是返回值允许不同。

幂等场景

我们来看一下SQL相关业务是否幂等?

一、查询,select * from user where xxx,不会对资料产生任何变化,具备幂等性

二、新增,insert into user(userid,name) values(1,a),

userid为唯一主键,即重复操作上面的业务,只会插入一条使用者资料,具备幂等性。如userid不是主键,可以重复,那上面业务多次操作,资料都会新增多条,不具备幂等性

三、修改,区分直接赋值和计算赋值。

1、直接赋值,update user set point = 20 where userid=1,不管执行多少次,point都一样,具备幂等性。2、计算赋值,update user set point = point + 20 where userid=1,每次操作point资料都不一样,不具备幂等性

四、删除,delete from user where userid=1,多次操作,结果一样,具备幂等性。

上面场景中,我们发现新增没有唯一主键约束的资料,和修改计算赋值型操作都不具备幂等性

那怎么去解决呢?

网上介绍很多,但介绍的太简单了,且关键点都没有介绍到。老顾这里只介绍常用的方案

token机制

token方式的流程,上一张图,比较清晰

上图就是token+redis的幂等方案,适用绝大部分场景。主要思想:

1、服务端提供了传送token的界面。我们在分析业务的时候,哪些业务是存在幂等问题的,就必须在执行业务前,先去获取token,服务器会把token储存到redis中。(微服务肯定是分散式了,如果单机就适用jvm快取)。2、然后呼叫业务界面请求时,把token携带过去,一般放在请求头部。3、服务器判断token是否存在redis中,存在表示第一次请求,可以继续执行业务,执行业务完成后,最后需要把redis中的token删除。4、如果判断token不存在redis中,就表示是重复操作,直接返回重复标记给client,这样就保证了业务程式码,不被重复执行。

这种方案是比较常用的方案,也是网上经常介绍的,但是有一点不同的地方:

网上方案:检验token存在(表示第一次请求)后,就立刻删除token,再进行业务处理上面方案:检验token存在(表示第一次请求)后,先进行业务处理,再删除token

关键点就是 先删除token,还是后删除token。

一、网上方案缺点

我们看下网上方案,先删除token,这是出现系统问题导致业务处理出现异常,业务处理没有成功,界面呼叫方也没有获取到明确的结果,然后进行重试,但token已经删除掉了,服务端判断token不存在,认为是重复请求,就直接返回了,无法进行业务处理了。

二、上面方案缺点

后删除token也是会存在问题的,如果进行业务处理成功后,删除redis中的token失败了,这样就导致了有可能会发生重复请求,因为token没有被删除

小伙伴们有没有发现,其实上面的问题就是数据库和快取redis资料不一致的问题。之前老顾分享了一篇文章,里面详细介绍了如何解决数据库和快取redis资料不一致的问题。小伙伴们可自行查阅。

其实根据这个场景的业务,可以有个简单的处理方式。老顾推荐是网上方案先删除token,先保证不会因为重复请求,业务资料出现问题。顶多再让使用者处理一次。

出现业务异常,可以让呼叫方配合处理一下,重新获取新的token,再次由业务呼叫方发起重试请求就ok了

token机制缺点

小伙伴们有没有发现,业务请求每次请求,都会有额外的请求(一次获取token请求、判断token是否存在的业务)。其实真实的生产环境中,1万请求也许只会存在10个左右的请求会发生重试,为了这10个请求,我们让9990个请求都发生了额外的请求。(当然redis效能很好,耗时不会太明显)

乐观锁机制

关于乐观锁老顾之前也讲过,大家可以去查阅。乐观锁这里解决了计算赋值型的修改场景。我们对之前的sql语句进行修改。

update user

set point = point + 20, version = version + 1

where

userid=1

and

version=1

加上了版本号后,就让此计算赋值型业务,具备了幂等性

乐观锁机制缺点

就是在操作业务前,需要先查询出当前的version版本

唯一主键机制

这个机制是利用了数据库的主键唯一约束的特性,解决了在insert场景时幂等问题。但主键的要求不是自增的主键,这样就需要业务生成全域性唯一的主键,之前老顾的文章也介绍过分散式唯一主键ID的生成,可自行查阅。如果是分库分表场景下路由规则要保证相同请求下落地在同一个数据库和同一表中,要不然数据库主键约束就不起效果了,因为是不同的数据库和表主键不相关。因为对主键有一定的要求,这个方案就跟业务有点耦合了,无法用自增主键了

去重表机制

这个方案业务中要有唯一主键,这个去重表中只要一个字段就行,设定唯一主键约束,当然根据业务自行新增其他字段。主要流程上图

上面的主要流程就是 把唯一主键插入去重表,再进行业务操作,且他们在同一个事务中。这个保证了重复请求时,因为去重表有唯一约束,导致请求失败,避免了幂等问题

这里要注意的是,去重表和业务表应该在同一库中,这样就保证了在同一个事务,即使业务操作失败了,也会把去重表的资料回滚。这个很好的保证了资料一致性

这个方案也是比较常用的,去重表是跟业务无关的,很多业务可以共用同一个去重表,只要规划好唯一主键就行了。

总结

上面介绍了一些幂等方案,小伙伴们根据自身的业务进行选择,尽量不要让系统变的复杂,所以推荐唯一主键和乐观锁方式,因为实现比较简单。好了,今天就介绍到这里,谢谢大家!!!

大家记得点个关注+转发哦!,咱们下回聊!

标签: 美术老师画的科幻画中国芯科学技术在社会发展中的作用科技类文章人工合成淀粉

上一篇:选购数码相机如同挑选一颗璀璨的明珠需要细心考量每一个角落屏幕大小虽重要但也需兼顾像素密度与光线处理让

下一篇:为何选择焦距更长 探讨为什么在某些情况下使用较长焦段能让你的照片更加引人入胜并传达更深层次的情感或信

相关推荐
推荐资讯
热门文章