2020-12-24

博客园Logo
首页
新闻
博问
专区
闪存
班级

代码改变世界
搜索
注册
登录
博客园 首页 新随笔 联系 订阅 管理
随笔 - 203 文章 - 0 评论 - 125
12张图带你彻底理解分布式事务!!
写在前面
写这篇文章的背景是有个跟我关系不错的小伙伴去某大型互联网公司面试,面试官问了他关于分布式事务的问题,不巧的是他确实对分布式事务掌握的不是很深入,面试的结果挺遗憾的。不过,这位小伙伴还是挺乐观的,让我写写关于【分布式事务】的系列文章,他想提升自己关于分布式事务的短板,那我就写一个【分布式事务】专题吧,专题的内容计划是从原理、框架源码到企业级实现,这篇文章也算是整个专题的开篇吧。希望能够为小伙伴们带来实质性的帮助。

本地事务
本地事务流程

在介绍分布式事务之前,我们先来看看本地事务。首先,我们先来一张图。

由上图,我们可以看出,本地事务由资源管理器(比如DBMS,数据库管理系统)在本地进行管理。

本地事务的优缺点

本地事务具备相应的优点,也有其不足。

优点:

支持严格的ACID属性。
可靠,事务实现的效率高(只是在本地操作)。
可以只在RM(资源管理器)中操作事务。
编程模型简单。
缺点:

缺乏分布式事务的处理能力。
数据隔离的最小单元由RM(资源管理器决定),开发人员无法决定数据隔离的最小单元。比如:数据库中的一条记录等。
ACID属性

说起事务,我们不得不提的就是事务的ACID属性。

A(Atomic):原子性,构成事务的所有操作,要么都执行完成,要么全部不执行,不可能出现部分成功部分失
败的情况。
C(Consistency):一致性,在事务执行前后,数据库的一致性约束没有被破坏。比如:张三向李四转100元,
转账前和转账后的数据的正确状态叫作一致性,如果出现张三转出100元,李四账户没有增加100元这就出现了数
据错误,就没有达到一致性。
I(Isolation):隔离性,数据库中的事务一般都是并发的,隔离性是指并发的两个事务的执行互不干扰,一个事
务不能看到其他事务运行过程的中间状态。通过配置事务隔离级别可以避脏读、重复读等问题。
D(Durability):持久性,事务完成之后,该事务对数据的更改会被持久化到数据库,且不会被回滚。
分布式事务
随着业务的快速发展,网站系统往往由单体架构逐渐演变为分布式、微服务架构,而对于数据库则由单机数据库架构向分布式数据库架构转变。此时,我们会将一个大的应用系统拆分为多个可以独立部署的应用服务,需要各个服务之间进行远程协作才能完成事务操作。

我们可以使用下图来表示刚开始我们系统的单体架构。

上图中,我们将同一个项目中的不同模块组织成不同的包来进行管理,所有的程序代码仍然是放在同一个项目中。

后续由于业务的发展,我们将其扩展为分布式、微服务架构。此时,我们将一个大的项目拆分为一个个小的可以独立部署的微服务,每个微服务都有自己的数据库,如下所示。

又比如,在我们的程序中,经常会在同一个事务中执行类似如下的代码来完成我们的需求。

@Transactional(rollbackFor = Exception.class)
public void submitOrder() {
orderDao.update(); // 更新订单信息
accountService.update(); // 修改资金账户的金额
pointService.update(); // 修改积分
accountingService.insert(); // 插入交易流水
merchantNotifyService.notify(); // 通知支付结果
}
上述代码中的业务,仅仅在submitOrder()方法上添加了一个@Transactional注解,这能够在分布式场景下避免分布式事务的问题吗?很显然是不行的。

如果上述代码所对应的:订单信息、资金账户信息、积分信息、交易流水等信息分别存储在不同的数据里,而支付完成后,通知的目标系统的数据同样是存储在不同的数据库中。此时就会产生分布式事务问题。

分布式事务产生的场景
跨JVM进程

当我们将单体项目拆分为分布式、微服务项目之后,各个服务之间通过远程REST或者RPC调用来协同完成业务操作。典型的场景就是:商城系统中的订单微服务和库存微服务,用户在下单时会访问订单微服务,订单微服务在生成订单记录时,会调用库存微服务来扣减库存。各个微服务是部署在不同的JVM进程中的,此时,就会产生因跨JVM进程而导致的分布式事务问题。

跨数据库实例

单体系统访问多个数据库实例,也就是跨数据源访问时会产生分布式事务。例如,我们的系统中的订单数据库和交易数据库是放在不同的数据库实例中,当用户发起退款时,会同时操作用户的订单数据库和交易数据库,在交易数据库中执行退款操作,在订单数据库中将订单的状态变更为已退款。由于数据分布在不同的数据库实例,需要通过不同的数据库连接会话来操作数据库中的数据,此时,就产生了分布式事务。

多服务单数据库

多个微服务访问同一个数据库。例如,订单微服务和库存微服务访问同一个数据库也会产生分布式事务,原因是:多个微服务访问同一个数据库,本质上也是通过不同的数据库会话来操作数据库,此时就会产生分布式事务。

注意:跨数据库实例场景和多服务单数据库场景,本质上都是因为会产生不同的数据库会话来操作数据库中的数据,进而产生分布式事务。这两种场景是大家比较容易忽略的。

分布式事务解决方案
知道了分布式事务产生的场景后,接下来,我们就聊聊分布式事务具体有哪些解决方案。

2PC方案

2PC即两阶段提交协议,是将整个事务流程分为两个阶段,准备阶段(Prepare phase)、提交阶段(commit
phase),2是指两个阶段,P是指准备阶段,C是指提交阶段。

这里,我们用MySQL数据库举例,MySQL数据库支持两阶段提交协议,可以分为成功和失败两种情况。

成功情况

失败情况

具体流程如下:

准备阶段(Prepare phase): 事务管理器给每个参与者发送Prepare消息,每个数据库参与者在本地执行事
务,并写本地的Undo/Redo日志,此时事务没有提交。
(Undo日志是记录修改前的数据,用于数据库回滚,Redo日志是记录修改后的数据,用于提交事务后写入数
据文件)

提交阶段(commit phase): 如果事务管理器收到了参与者的执行失败或者超时消息时,直接给每个参与者
发送回滚(Rollback)消息;否则,发送提交(Commit)消息;参与者根据事务管理器的指令执行提交或者回滚操
作,并释放事务处理过程中使用的锁资源。

使用2PC方案时,需要注意的是:必须在最后阶段释放锁资源。

可靠消息最终一致性方案

可靠消息最终一致性方案是指当事务发起方执行完成本地事务后并发出一条消息,事务参与方(消息消费者)一定能
够接收消息并处理事务成功,此方案强调的是只要消息发给事务参与方最终事务要达到一致。

事务发起方(消息生产方)将消息发给消息中间件,事务参与方从消息中间件接收消息,事务发起方和消息中间件
之间,事务参与方(消息消费方)和消息中间件之间都是通过网络通信,由于网络通信的不确定性会导致分布式事
务问题。 所以,我们在具体方案中会引入消息确认服务和消息恢复服务。

使用可靠消息最终一致性方案时需要注意几个问题:

本地事务与消息发送的原子性问题。
事务参与方接收消息的可靠性问题。
消息重复消费的问题(需要实现幂等)。
TCC方案

TCC分为三个阶段:

Try 阶段 是做业务检查(一致性)及资源预留(隔离),此阶段仅是一个初步操作,它和后续的Confirm 一起才能
真正构成一个完整的业务逻辑。
Confirm 阶段 是做确认提交,Try阶段所有分支事务执行成功后开始执行 Confirm。通常情况下,采用TCC则
认为 Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功。若Confirm阶段真的出错了,需引
入重试机制或人工处理。
Cancel 阶段 是在业务执行错误需要回滚的状态下执行分支事务的业务取消,预留资源释放。通常情况下,采
用TCC则认为Cancel阶段也是一定成功的。若Cancel阶段真的出错了,需引入重试机制或人工处理。

使用TCC分布式解决方案时需要注意空回滚、幂等、悬挂等问题。

最大努力通知型方案

此种方案主要用于多个不同系统之前保证数据的最终一致性,大体如下图所示。

使用最大努力通知型方案需要注意幂等和数据的回查操作。

好了,今天就到这儿吧,后续我们会针对每种分布式事务解决方案进行具体介绍,下期见!!

开源项目
最后,我开源了基于消息最终一致性的分布式事务框架mykit-transaction-message。框架中有很完善的demo示例。

github:https://github.com/sunshinelyz/mykit-transaction-message
gitee:https://gitee.com/binghe001/mykit-transaction-message

分类: 分布式事务
好文要顶 关注我 收藏该文
冰河团队
关注 - 0
粉丝 - 122
+加关注
1
« 上一篇: 我们该如何正确的中断一个线程的执行??
posted @ 2020-12-23 23:03 冰河团队 阅读(70) 评论(0) 编辑 收藏
刷新评论刷新页面返回顶部
登录后才能发表评论,立即 登录 或 注册, 访问 网站首页
写给园友们的一封求助信
【推荐】News: 大型组态、工控、仿真、CADGIS 50万行VC++源码免费下载
【推荐】有你助力,更好为你——博客园用户消费观调查,附带小惊喜!
【推荐】博客园x丝芙兰-圣诞特别活动:圣诞选礼,美力送递
【推荐】了不起的开发者,挡不住的华为,园子里的品牌专区
【福利】AWS携手博客园为开发者送免费套餐+50元京东E卡
【推荐】未知数的距离,毫秒间的传递,声网与你实时互动
【推荐】新一代 NoSQL 数据库,Aerospike专区新鲜入驻

相关博文:
· 12-12:Servlet
· TT-12
· leetcode-12
· 12-20
· 12-1
» 更多推荐…

最新 IT 新闻:
· 红帽为CentOS的决定辩护 声称Stream版本可以覆盖当前95%的用户场景
· 美国宇航局可能已经捕捉到了太阳纳米耀斑的全生命周期
· 京东“京蜓”无人机在自贡成功首飞
· 《光环:士官长合集》开发商宣布加入腾讯:会变得更好
· 游族爆高层内斗CEO被投毒住院 警方通报来了:光速反转
» 更多新闻…
公告

昵称: 冰河团队
园龄: 1年5个月
粉丝: 122
关注: 0
+加关注
< 2020年12月 >
日 一 二 三 四 五 六
29 30 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 1 2
3 4 5 6 7 8 9
搜索

找找看

谷歌搜索
常用链接

我的随笔
我的评论
我的参与
最新评论
我的标签
我的标签

Java(3)
高并发(3)
高并发,Java(3)
线程(3)
设计模式(1)
随笔分类

Canal(2)
Docker(12)
FastDFS(5)
Java(5)
Java8(16)
Jenkins(1)
JVM(4)
K8S(14)
MySQL(9)
Nginx(21)
Oracle(5)
Redis(2)
ShardingSphere(1)
Spring(36)
程序人生(2)
更多
随笔档案

2020年12月(9)
2020年11月(19)
2020年10月(20)
2020年9月(24)
2020年8月(22)
2020年7月(28)
2020年6月(31)
2020年5月(29)
2020年4月(15)
2020年2月(6)
最新评论

  1. Re:我们该如何正确的中断一个线程的执行??

    –shian

  2. Re:冰河,能不能讲讲如何实现MySQL数据存储的无限扩容?
    谢谢分享
    –沈赟

  3. Re:并发编程中一种经典的分而治之的思想!!
    @可少 厉害…
    –冰河团队

  4. Re:并发编程中一种经典的分而治之的思想!!
    分而治之的思想
    存在于宇宙万物之中
    –可少

  5. Re:MySQL如何实现万亿级数据存储?
    @缤纷世界 有…
    –冰河团队
    阅读排行榜

  6. 【高并发】高并发秒杀系统架构解密,不是所有的秒杀都是秒杀!(7150)

  7. 【高并发】高并发分布式锁架构解密,不是所有的锁都是分布式锁!!(4784)

  8. 【高并发】为何高并发系统中都要使用消息队列?这次彻底懂了!(4231)

  9. 【Oracle】CentOS7/CentOS8命令行安装Oracle 11G R2(3947)

  10. 【K8S】K8S部署Metrics-Server服务(3850)
    评论排行榜

  11. 【高并发】高并发秒杀系统架构解密,不是所有的秒杀都是秒杀!(21)

  12. 【高并发】高并发分布式锁架构解密,不是所有的锁都是分布式锁!!(11)

  13. 【Java】面试官灵魂拷问:if语句执行完else语句真的不会再执行吗?(7)

  14. 【高并发】终于弄懂为什么局部变量是线程安全的了!!(7)

  15. MySQL如何实现万亿级数据存储?(6)
    推荐排行榜

  16. 【高并发】高并发秒杀系统架构解密,不是所有的秒杀都是秒杀!(55)

  17. 【高并发】高并发分布式锁架构解密,不是所有的锁都是分布式锁!!(17)

  18. 三万字无坑搭建基于Docker+K8S+GitLab/SVN+Jenkins+Harbor持续集成交付环境(7)

  19. 小伙伴问我:如何搭建Maven私服?我连夜肝了这篇实战文章!!(6)

  20. 【Nginx】如何使用Nginx搭建流媒体服务器实现直播?看完这篇我会了!!(6)
    Copyright © 2020 冰河团队
    Powered by .NET 5.0.1-servicing.20575.16 on Kubernetes

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值