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

前言

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

大家觉得还不错的可以关注我的主页【点击进入】,每天都会更新一下技术干货、电子书、架构资料等免费领取!

罪魁祸首

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

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 whereuserid=1 and version=1

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

乐观锁机制缺点

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

唯一主键机制

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

去重表机制

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

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

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

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

总结

大家觉得还不错的可以关注我的主页【点击进入】,每天都会更新一下技术干货、电子书、架构资料等免费领取!

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

原文地址:https://www.cnblogs.com/moon0201/p/11133497.html

时间: 2024-10-08 02:31:34

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

微服务架构及幂等性

微服务架构 微服务架构是一种架构概念,旨在通过将功能分解到各个离散的服务中以实现对解决方案的解耦.它的主要作用是将功能分解到离散的各个服务当中,从而降低系统的耦合性,并提供更加灵活的服务支持. 和 微服务 相对应的,这种方式一般被称为 单体式开发(Monolithic).既所有的功能打包在一个 WAR 包里,基本没有外部依赖(除了容器),部署在一个 JavaEE 容器(Tomcat,JBoss,WebLogic)里,包含了 DO/DAO,Service,UI 等所有逻辑. 单体应用的优缺点: 优

微服务架构设计基础之领域驱动设计

DDD早于微服务「出道」十年,这两个「忘年交」的软件设计哲学是如何相爱相杀的? 背景 微服务现在可以说是软件研发领域无人不提的话题,然而业界流行的对比多数都是所谓的Monolithic(单体应用),而大量的系统在十几年前都已经是以SOA(面向服务架构)为基础的分布式系统了,那么微服务作为新的架构标准与SOA有什么差异点呢?其本质区别在于设计原理,微服务是去中心化设计,SOA是「集成」形成中心设计: 另外,笔者认为以下几点并不是微服务和SOA的区别点: CI/CD:持续集成.持续部署本身与敏捷.D

微服务设计关键的难点:微服务架构的数据库是如何设计的?

单独的数据库: 微服务设计的一个关键是数据库设计,基本原则是每个服务都有自己单独的数据库,而且只有微服务本身可以访问这个数据库.它是基于下面三个原因. 优化服务接口:微服务之间的接口越小越好,最好只有服务调用接口(RPC或消息),没有其他接口.如果微服务不能独享自己的数据库,那么数据库也变成了接口的一部分,这大大拓展了接口范围. 错误诊断:生产环境中的错误大部分都是和数据库有关的,要么是数据出了问题,要么是数据库的使用方式出了问题.当你不能完全控制数据库的访问时,会有各种各样的错误发生.它可能是

微服务架构设计

微服务 软件架构是一个包含各种组织的系统组织,这些组件包括 Web服务器, 应用服务器, 数据库,存储, 通讯层), 它们彼此或和环境存在关系.系统架构的目标是解决利益相关者的关注点. Conway’s law: Organizations which design systems[...] are constrained to produce designs which are copies of the communication structures of these organizati

分布式系统(微服务架构)的一致性和幂等性问题相关概念解析

目录 前言 1. 分布式系统的数据一致性 1.1 分布式存储系统中的一致性问题 1.2 微服务应用的分布式一致性问题 1.3 对于一致性的正确理解 2.分布式一致性模型 3. 追求强一致性的约束--CAP定理 3.1 如何理解CAP三要素不可兼得 3.2 如何正确理解CAP定理 4. 一致性的妥协--最终一致性和Base原则 4.1 CAP,BASE以及ACID的关系 5. 分布式系统的幂等性 6.微服务架构的分布式一致性和幂等性问题 6.1 微服务架构下的分布式一致性问题 6.2 微服务架构下

微服务架构的设计和实践-培训感悟

这两天(4月8号,9号)我有幸参加了极客邦的培训课程-微服务架构的设计和实践,能够面对面倾听58架构师-孙玄的亲身授课,个人也是感到非常的荣幸.两天的时间,来回于广州和深圳,虽然不能说自己的技术有了一个质的提升,但至少也是一次很好的交流体现,这一趟不白走! 身为一个技术小白(虽然个人也有四年的开发经验,但大多的技术只是知其然而不知其所以然,而且接触面太狭隘),此次学习最明显的感受是,如果你只会写软件代码,了解与某种语言相关的语法,框架以及架构包括技术,那你肯定会"死的很惨".作为软件行

Atitit.架构设计趋势 设计模式 ---微服务架构  soa

Atitit.架构设计趋势 设计模式 ---微服务架构  soa 什么是微服务架构?1 .微服务与SOA的关系 :微服务架架构师面向服务架构(SOA)的一种特定实现1 微服务与康威定律2 微服务的一些设计 断路器 幂等2 <微服务设计>([英] 纽曼(Sam Newman))3 微服务架构与实践4 什么是微服务架构? Martin Fowler认为,微服务架构是一种独立部署的软件应用设计方式.这种架构方式没有准确的定义,但是在业务能力.自动部署.端对端的整合.对语言及数据的分散控制上有着共性.

孢子框架-互联网金融平台微服务架构设计

按照孢子框架要义对互联网金融理财平台进行微服务架构设计.假设我们设计的目标是5年后的陆金所(https://www.lu.com/).陆金所简介,平安集团旗下理财平台,是中国最大的网络投融资平台之一,2011年9月在上海注册成立,注册资本金8.37亿元,lufax结合全球金融发展与互联网技术创新,在健全的风险管控体系基础上,为中小企业及个人客户提供专业.可信赖的投融资服务,帮助他们实现财富增值.截至2014年1月末,注册用户已逾570万. l 需求分析 参照陆金所,获得如下核心需求矩阵. 分类

软件架构设计学习总结(22):软件架构——分层架构、事件驱动架构、微内核架构、微服务架构、基于空间的架构

分层架构 (Layered Architecture) 分层架构是最常见的架构,也被称为n层架构.多年以来,许多企业和公司都在他们的项目中使用这种架构,它已经几乎成为事实标准,因此被大多数架构师.开发者和软件设计者所熟知.比如MVC. 分层架构的一个特性就是 关注分离(separation of concerns) .在层中的组件只负责本层的逻辑.组件的划分很容易让它们实现自己的角色和职责,也比较容易地开发,测试管理和维护. 我们需要这样的冗余,即使业务层没有处理业务规则,也要通过业务层来调用数