只需5分钟,深刻理解本地事务状态表方案|分布式事务系列(四)
之前我们已经讲过了最基础的CAP、BASE理论,然后介绍了强一致性方案XA、2PC和3PC,然后详细讲述了TCC在生产中的应用场景和原理。本文继续讲解最终一致性方案——本地事务状态表方案。
点击上方“后端开发技术”,选择“设为星标” ,优质资源及时送达
本地事务状态表
本地事务状态表的方案中主要有三种角色:调用方、被调用方、定时任务。
我们都知道,分布式事务之所以很难保证一致性,但是本地事务却可以,就是因为本地事务是存储引擎层面去保证的。比如 MySQL 的InnoDB 引擎中,他的底层用了 RedoLog 和 UndoLog 以及锁等机制确保了这一点。这里对此不再深入作答,具体可以看往期文章。
所以现在思路是这样:我们要利用存储引擎可以保证事务一致性,这就让我们想到了为每一次远程服务的调用生成一条数据,在数据库落盘,利用本地事务的特点来保证一致性。每一条数据都代表一次RPC调用,然后利用重试机制来保证最终一致性。
用一个案例思考
我先不给详细过程,而是带你实际推理一下,掌握学习方法更重要。
这里使用支付和订单项目来举例,本地服务是支付项目,在支付完成后需要使用RPC通知订单支付结果成功,订单更新订单状态。
正常调用流程如下:
看起来流程没有毛病,余额如果通知订单失败,本地事务回滚就是了。余额会加上去,订单也没有支付成功。
订单接口超时怎么办?
但是,一个远程连接有有来和去两个过程,如果余额扣减成功,并且订单服务已经收到支付成功的信息,但是订单本地状态更新为支付成功后,接口响应超时,没有成功返回给支付服务怎么办?
这就造成了余额本地事务回退,金额没有扣减,但是订单状态成功的情况。
本地事务状态表核心流程
为了解决数据不一致的情况,根据文章一开始我们提到的BASE理论,以及利用本地事务来保证数据一致的思路。
因为订单接口有可能超时,网络问题我们无法从编码层面解决,但是可以做到有效的补偿。根据BASE理论,一次调用不能一致,那我多次调用不断尝试不就可以了嘛,总不能每次都超时。
所以这就涉及到两个问题:
订单接口(被调用方)需要支持幂等操作。
需要有一种机制让系统知道该重试哪些操作,并且这个机制需要保证和余额(被调用方)数据的一致性。
第一个问题很好解决,可以通过订单ID利用唯一键或者Redis来保证支付行为不会被重复处理。
第二个问题提到了一致性和数据记录,那我们直接保存一条本地事务数据到表里就可以了,保存时候记录订单接口的必要参数信息,以及调用成功状态,默认是未成功。
因为要保证本地事务状态表中的数据和余额(被调用方)一致,那我们就需要把事务提交的时机提前到RPC调用前。
因为此时还没有真正发起RPC调用,所以对于表中记录的数据,可以单独启动一个定时任务不断重试。如果通知订单(被调用方)成功就更改状态为已通知,这样以后定时任务就不会再读取这条记录了。如果还不成功就保持状态不变,继续等待下一次尝试。
这里的定时任务不断重试体现了最终一致性的思想。
优缺点
当然,本地事务状态表也优缺点并存,具体使用需要根据场景。
优点:
性能还不错,业务之间没有强依赖。
实现了最终一致性,适合对数据不一致有一定容忍度的系统。
缺点:
有一定的业务入侵性。
每个系统需要有自己的本地事务状态表,难通用。
实效性并不是很好。
但是,如上这些缺点其实有一些解决的办法。
定时任务不及时怎么办
笔者自己实现了一套简单的本地事务表框架,主要解决了两个问题:业务入侵度高和实效性。
这里不说具体代码了,核心思想是:
将每个需要利用本地事务表方案的接口和参数保存在ThreadLocal中,并且保存状态表数据到MySQL。
将每个需要利用本地事务表方案的方法用一个自定义注解去做切面。
利用TransactionSynchronization接口自己实现了commit,afterCompletion等方法,在事务结束的时候读取ThreadLocal中的内容,以做到及时调用对应RPC。
但是还有问题,每次都需要根据不同的事件类型,写不同的业务逻辑,并且还需要在手动写保存到任务表的逻辑,依旧有业务入侵性,还是有点繁琐。
总结
简单总结下流程:
调用方在本地事务中保存一条待调用状态的数据到本地事务状态表中。
本地事务提交后马上调用RPC,如果成功就更新状态,如果不成功那就不管。
在后台启动一个定时任务,定期扫描本地事务状态表中未调用完成的数据,不断尝试调用。如果成功就更新状态,如果失败那就等待下次调用。在失败重试一定次数后触发告警人工介入处理。
对于本地事务表方案,你能做出自己设计的框架吗?如何解决他存在的问题?
加入讨论群是升职加薪第一步!
回复:加群
点赞是一种美德,如对您有帮助,欢迎评论和分享,感谢阅读!
面试官:会SQL调优,那你知道索引合并吗?|金三银四系列
2023-03-21
CAP、BASE理论真的很重要!|分布式事务系列(一)
2023-03-17
面试官:你是如何预防多线程死锁的?|金三银四系列
2023-03-16
只需5分钟,深刻理解本地事务状态表方案|分布式事务系列(四)相关推荐
- red hat安装宝塔_只需几分钟即可安装Red Hat Container Development Kit(视频)
red hat安装宝塔 自从我开始使用各种形式的OpenShift(例如带盒的Online,然后又作为容器化的图像)玩耍以来,没有什么比Red Hat Container Development Ki ...
- 只需几分钟即可安装Red Hat Container Development Kit(视频)
自从我开始使用各种形式的OpenShift(例如带盒的Online,然后又作为容器化的图像)玩耍以来,没有什么比Red Hat Container Development Kit(CDK)的可用性令我 ...
- TMail电子邮件,TMail放入服务器只需4分钟
TMail电子邮件,TMail放入服务器只需4分钟 什么是TMail多域临时电子邮件系统? TMail并不难使用.快速便捷地准备具有出色功能的临时电子邮件程序.将TMail放入服务器只需4分钟. TM ...
- 只需3分钟,就能轻松创建 一个SpreadJS的React项目
概述 SpreadJS 纯前端表格控件 V11.2(SP2) 已经全面支持了 React 的拓展.接下来我们看下如何利用3分钟快速创建一个 SpreadJS 的 React 项目. 1.新建React ...
- 晚上,睡前只需1分钟,一觉到天亮!
快节奏的生活谁都有压力大的时候,压力一大就影响睡眠,觉睡不好就影响到隔天的工作表现,就一直恶性循环下去,让你天天心情差,状态又不好,怎么办? 其实,只要睡前来个睡前操,只需1分钟,就能让你轻松入睡,一 ...
- java和python的比较-如何对比Python和Java,只需三分钟告诉你!
原标题:如何对比Python和Java,只需三分钟告诉你! Java和Python两门语言都是目前非常热门的语言,可谓北乔峰南慕容,二者不分上下,棋逢对手.但是对于初学者来说,非常困惑,因为时间和精力 ...
- 3d打印英语文献_锐医学院 | 只需10分钟!解读康复医学文献+英语学习
文献解读+英语学习 只需10分钟 锐医学院致力于专业康复教育培训同时,也在康复领域专家的合作下,一直在研究康复领域最前沿所取得的研究成果.存在的问题以及发展趋势进行系统和全面的叙述和评论与各领域康复专 ...
- 看后至少多活十年--只需十分钟
看后至少多活十年--只需十分钟 看后至少多活十年--只需十分钟 -北大齐教授健康讲座笔录- 看后至少多活十年!!!~~~~不要死于无知~~~~不但要保养好自己,回家也要告诉父母这么做~~~~这是好东西 ...
- 纸片人「活」了。Meta AI新作:只需几分钟,手绘小人有了灵魂
想让画中的「纸片人」有生命,Meta AI来搞定!昨日,Meta AI宣布了一种独创性方法,只需几分钟,就能动画化儿童手绘的角色,效果拔群. 快看,「纸片人」居然自己跳出来了! 小猫学会了hiphop ...
最新文章
- 最感动的一首现代诗(转)(修正了一点翻译)
- python输入完怎么运行-如何在服务器上跑python程序
- 第 4 章 超链接和路径
- Silverlight 2.5D RPG游戏技巧与特效处理:(七)动画特写
- String与Date、Timestamp互转
- android服务开启线程,android之service与intentService的不同
- ios基础篇(十二)——UINavgationController的使用(三)ToolBar
- RabbitMQ 2.8.7 发布,AMQP 消息队列
- [bzoj3223]Tyvj 1729 文艺平衡树
- PC电源供电接口知识大科普
- google搜索语法与技巧
- 给你的服务器建立动态域名服务
- 什么是电阻器与电阻?
- 电脑中PDF如何转换成WPS格式
- 善于记录,善于总结——《走出软件作坊》读后感
- win7不显示移动硬盘_如何在移动硬盘中安装win10系统?
- 2022最新在线工单管理系统源码+PHP内核
- 项目管理理论中关于软件项目外包采购管理的探讨
- vertica用户自定义扩展介绍
- SDOI 2009 学校食堂