您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

何为幂等?如何设计?

时间:2021-03-31 11:10:59  来源:今日头条  作者:老顾聊技术

欢迎关注头条号:老顾聊技术

精品原创技术分享,知识的组装工


目录

  1. 前言
  2. 罪魁祸首
  3. 幂等性
  4. 幂等场景
  5. token机制
  6. token机制缺点
  7. 乐观锁机制
  8. 乐观锁机制缺点
  9. 唯一主键机制
  10. 去重表机制
  11. 总结

前言

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

罪魁祸首

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

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的生成,可自行查阅。

如果是分库分表场景下路由规则要保证相同请求下落地在同一个数据库和同一表中,要不然数据库主键约束就不起效果了,因为是不同的数据库和表主键不相关。

因为对主键有一定的要求,这个方案就跟业务有点耦合了,无法用自增主键了

去重表机制

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

何为幂等?如何设计?

 

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

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

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

总结

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


-End-

如有收获,请帮忙转发,您的鼓励是作者最大的动力,谢谢!

10几年的经验实战分享

相关微服务,分布式,高并发,高可用,企业实战,干货等原创文章正在路上

欢迎关注头条号:老顾聊技术



Tags:幂等   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
一、幂等性概念在数学里,幂等有两种主要的定义。1、在某二元运算下,幂等元素是指被自己重复运算(或对于函数是为复合)的结果等于它自己的元素。例如,乘法下唯一两个幂等实数为0和...【详细内容】
2021-10-09  Tags: 幂等  点击:(43)  评论:(0)  加入收藏
消息中间件是分布式系统常用的组件,无论是异步化、解耦、削峰等都有广泛的应用价值。我们通常会认为,消息中间件是一个可靠的组件——这里所谓的可靠是指,只要我把消...【详细内容】
2021-08-19  Tags: 幂等  点击:(74)  评论:(0)  加入收藏
幂等,这个词来源自数学领域。幂等性衍生到软件工程中,它的语义是指:函数/接口可以使用相同的参数重复执行, 不应该影响系统状态,也不会对系统造成改变。举一个简单的例子:正常设...【详细内容】
2021-06-18  Tags: 幂等  点击:(107)  评论:(0)  加入收藏
小伙伴们有没有遇到过生产环境经常出现过重复的数据?在排查问题的时候,数据又是正常的。这个是何解呢?怎么会出现这种情况,而且还很难排查问题。今天老顾给大家分享一下这里的原因,以及解决方案。...【详细内容】
2021-03-31  Tags: 幂等  点击:(277)  评论:(0)  加入收藏
之前负责的项目报了一个问题,用户操作回退失效。我们的设计里,操作回退是回到操作前的状态。经过查看日志发现,用户之前的操作做了两次,也就是说提交操作的接口被调用了两次,导致...【详细内容】
2021-01-18  Tags: 幂等  点击:(207)  评论:(0)  加入收藏
什么是接口的幂等性,如何实现接口幂等性?(一)幂等性概念幂等性原本是数学上的概念,用在接口上就可以理解为:同一个接口,多次发出同一个请求,必须保证操作只执行一次。 调用接口发生...【详细内容】
2020-11-16  Tags: 幂等  点击:(130)  评论:(0)  加入收藏
什么是幂等性?对于同一笔业务操作,不管调用多少次,得到的结果都是一样的。幂等性设计我们以对接支付宝充值为例,来分析支付回调接口如何设计?如果我们系统中对接过支付宝充值功...【详细内容】
2019-09-24  Tags: 幂等  点击:(361)  评论:(0)  加入收藏
作者:冰峰编者说:比较实用的Redis加锁的方式,代码段可以收藏。在最近的一次业务升级中,遇到这样一个问题,我们设计了新的账户体系,需要在用户将应用升级之后将原来账户的数据手动...【详细内容】
2019-07-23  Tags: 幂等  点击:(269)  评论:(0)  加入收藏
▌简易百科推荐
摘 要 (OF作品展示)OF之前介绍了用python实现数据可视化、数据分析及一些小项目,但基本都是后端的知识。想要做一个好看的可视化大屏,我们还要学一些前端的知识(vue),网上有很多比...【详细内容】
2021-12-27  项目与数据管理    Tags:Vue   点击:(1)  评论:(0)  加入收藏
程序是如何被执行的  程序是如何被执行的?许多开发者可能也没法回答这个问题,大多数人更注重的是如何编写程序,却不会太注意编写好的程序是如何被运行,这并不是一个好...【详细内容】
2021-12-23  IT学习日记    Tags:程序   点击:(9)  评论:(0)  加入收藏
阅读收获✔️1. 了解单点登录实现原理✔️2. 掌握快速使用xxl-sso接入单点登录功能一、早期的多系统登录解决方案 单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器...【详细内容】
2021-12-23  程序yuan    Tags:单点登录(   点击:(8)  评论:(0)  加入收藏
下载Eclipse RCP IDE如果你电脑上还没有安装Eclipse,那么请到这里下载对应版本的软件进行安装。具体的安装步骤就不在这赘述了。创建第一个标准Eclipse RCP应用(总共分为六步)1...【详细内容】
2021-12-22  阿福ChrisYuan    Tags:RCP应用   点击:(7)  评论:(0)  加入收藏
今天想简单聊一聊 Token 的 Value Capture,就是币的价值问题。首先说明啊,这个话题包含的内容非常之光,Token 的经济学设计也可以包含诸多问题,所以几乎不可能把这个问题说的清...【详细内容】
2021-12-21  唐少华TSH    Tags:Token   点击:(9)  评论:(0)  加入收藏
实现效果:假如有10条数据,分组展示,默认在当前页面展示4个,点击换一批,从第5个开始继续展示,到最后一组,再重新返回到第一组 data() { return { qList: [], //处理后...【详细内容】
2021-12-17  Mason程    Tags:VUE   点击:(14)  评论:(0)  加入收藏
什么是性能调优?(what) 为什么需要性能调优?(why) 什么时候需要性能调优?(when) 什么地方需要性能调优?(where) 什么时候来进行性能调优?(who) 怎么样进行性能调优?(How) 硬件配...【详细内容】
2021-12-16  软件测试小p    Tags:性能调优   点击:(19)  评论:(0)  加入收藏
Tasker 是一款适用于 Android 设备的高级自动化应用,它可以通过脚本让重复性的操作自动运行,提高效率。 不知道从哪里听说的抖音 app 会导致 OLED 屏幕烧屏。于是就现学现卖,自...【详细内容】
2021-12-15  ITBang    Tags:抖音防烧屏   点击:(23)  评论:(0)  加入收藏
11 月 23 日,Rust Moderation Team(审核团队)在 GitHub 上发布了辞职公告,即刻生效。根据公告,审核团队集体辞职是为了抗议 Rust 核心团队(Core team)在执行社区行为准则和标准上...【详细内容】
2021-12-15  InfoQ    Tags:Rust   点击:(24)  评论:(0)  加入收藏
一个项目的大部分API,测试用例在参数和参数值等信息会有很多相似的地方。我们可以复制API,复制用例来快速生成,然后做细微调整既可以满足我们的测试需求1.复制API:在菜单发布单...【详细内容】
2021-12-14  AutoMeter    Tags:AutoMeter   点击:(20)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条