前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >你还不懂分布式事务吗?

你还不懂分布式事务吗?

作者头像
Liusy
发布2020-08-31 13:49:01
4170
发布2020-08-31 13:49:01
举报
文章被收录于专栏:Liusy01

当系统是分布式系统,并且数据库有分库分表的情况下,此时会产生分布式事务相关的问题。

数据库事务需要满足条件:ACID

Atomic(原子性):事务操作必须是原子性的,要么成功,要么失败

Consistent(一致性):事务完成后,必须使所有数据都保持一致状态

Isolation(隔离性):并发事务所做的修改必须和其他事务所做的修改是隔离的,也就是只能访问事务前和事务后的状态,不能访问事务操作时的状态。

Duration(持久性):事务完成之后,对系统的影响是永久的。

分布式事务产生背景:

(1)数据库进行了分库分表

(2)服务SOA化(跟微服务的概念差不多)

(3)事务执行情况协调:在分布式系统中,每一个机器节点虽然都能明确的知道自己执行的事务是成功还是失败,但是却无法知道其他分布式节点的事务执行情况。因此,当一个事务要跨越多个分布式节点的时候,为了保证该事务可以满足ACID,就要引入一个协调者(Cooradinator)。其他的节点被称为参与者(Participant)。协调者负责调度参与者的行为,并最终决定这些参与者是否要把事务进行提交。

类似于下图,当需要在商场下订单的时候,需要同时调用库存服务、支付服务以及订单服务。当一个挂掉无法提交,其他已经完成提交,就会出现分布式事务的问题。数据最终不一致。

MySQL事务处理流程:

(1)先记录 undo/redo log,确保日志刷到磁盘上持久存储。(redo log 记录事务修改后的数据, undo log 记录事务前的原始数据。)

(2)更新数据记录,缓存操作并异步刷盘。

(3)提交事务,在 redo log 中写入 commit 记录。

X/OpenDTP事务模型:

X/Open Distributed Transaction Processing Reference Model X/Open是一个组织机构,定义出的一套分布式事务标准, 定义了规范的API接口。

2PC(two -phase-commit), 用来保证分布式事务的完整性

J2EE 遵循了X/open DTP规范,设计并实现了java里面的分布式事务编程接口规范-JTAXA是X/Open DTP定义的中间件与数据库之间的接口规范。XA接口函数由数据库厂商提供。

X/OpenDTP 角色 AP application

RM resouces manager 资源管理器,数据库

TM transaction manager 事务管理器,事务协调者

2PC(two -phase-commit),两阶段提交

(1)阶段一:提交事务请求(投票)

1、TM向所有的AP发送事务内容,询问是否可以执行事务的提交操作,并等待各个AP的响应

2、执行事务

各个AP节点执行事务操作,将undo和redo信息记录到事务日志中,尽量把提交过程中所消耗时间的操作和准备都提前完成后确保后续事务提交的成功率

3.各个AP向TM反馈事务询问的响应

各个AP成功执行了事务操作,那么反馈给TM yes的response;如果AP没有成功执行事务,就反馈TM no的response

(2)阶段二:执行事务提交

1、执行提交事务

假设一个事务的提交过程总共需要30s, 其中prepare操作需要28(事务日志落地磁盘及各种io操作),而真正commit只需要2s,那么,commit阶段发生错误的概率和prepare相比, 2/28 (<10%) .只要第一个阶段成功,那么commit阶段出现失败的概率就非常小,大大增加了分布式事务的成功概率。

2、中断事务提交

(3)2pc存在的问题

1、数据不一致。在二阶段提交的阶段二中,当协调者向参与者发送commit请求之后,发生了局部网络异常或者在发送commit请求过程中协调者发生了故障,这回导致只有一部分参与者接受到了commit请求。而在这部分参与者接到commit请求之后就会执行commit操作。但是其他部分未接到commit请求的机器则无法执行事务提交。于是整个分布式系统便出现了数据部一致性的现象。

2、同步阻塞问题。执行过程中,所有参与节点都是事务阻塞型的。当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态

3、二阶段无法解决的问题:协调者在发出commit消息之后宕机,而唯一接收到这条消息的参与者同时也宕机了。那么即使协调者通过选举协议产生了新的协调者,这条事务的状态也是不确定的,没人知道事务是否被已经提交

4、单点故障。由于协调者的重要性,一旦协调者发生故障。参与者会一直阻塞下去

3PC(three phase commit),三阶段提交

1、阶段一:canCommit

先询问是否可以执行commit,如果有一台机器返回no,就停止事务

2、阶段二:preCommit

各个AP节点执行事务操作,将undo和redo信息记录到事务日志中,尽量把提交过程中所消耗时间的操作和准备都提前完成后确保后续事务提交的成功率

3、阶段三:doCommit

各个AP成功执行了事务操作,那么反馈给TM yes的response;如果AP没有成功执行事务,就反馈TM no的response

改进点

1、增加了超时机制

2、第二阶段,如果协调者超时没有接受到参与者的反馈,则自动认为失败,发送abort命令

3、第三阶段,如果参与者超时没有接受到协调者的反馈,则自动认为成功开始提交事务(基于概率)

问题:

相对于2PC,3PC主要解决的单点故障问题,并减少阻塞,因为一旦参与者无法及时收到来自协调者的信息之后,他会默认执行commit。而不会一直持有事务资源并处于阻塞状态。但是这种机制也会导致数据一致性问题,因为,由于网络原因,协调者发送的abort响应没有及时被参与者接收到,那么参与者在等待超时之后执行了commit操作。这样就和其他接到abort命令并执行回滚的参与者之间存在数据不一致的情况。

TCC分布式事务:

TCC分为三个阶段TRYING-CONFIRMING-CANCELING。每个阶段做不同的处理

TRYING、CONFIRMING、CANCELIING大致可以理解为SQL事务中的LOCK、COMMIT、ROLLBACK

TRYING 阶段主要是对业务系统做检测及资源预留

CONFIRMING 阶段主要是对业务系统做确认提交,TRYING阶段执行成功并开始执行CONFIRMING阶段时,默认 CONFIRMING阶段是不会出错的。即:只要TRYING成功,CONFIRMING一定成功。

CANCELING 阶段主要是在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放。

如何更通俗的理解TCC事务模型

支付系统接收到会员的支付请求后,需要扣减会员账户余额、增加会员积分(暂时假设需要同步实现)增加商户账户余额会员系统、商户系统、积分系统是独立的三个子系统,无法通过传统的事务方式进行处理。

TRYING阶段:我们需要做的就是会员资金账户的资金预留,即:冻结会员账户的金额(订单金额)

CONFIRMING阶段:我们需要做的就是会员积分账户增加积分余额,商户账户增加账户余额

CANCELING阶段:该阶段需要执行的就是解冻释放我们扣减的会员余额

最终一致性方案:

采用消息队列来辅助实现事务控制流程,方案的核心是将需要分布式处理的任务通过消息队列的方式来异步执行,如果事务失败,则可以发起人工重试的纠正流程。人工重试被更多的应用于支付场景,通过对账系统对事后问题进行处理。

分布式事务实现:

1、JOTM(java open transaction manager)

2、Atomikos(下一篇会演示)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Liusy01 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • X/OpenDTP事务模型:
    • (1)阶段一:提交事务请求(投票)
      • (2)阶段二:执行事务提交
        • (3)2pc存在的问题
        • 3PC(three phase commit),三阶段提交
          • 最终一致性方案:
          相关产品与服务
          数据库
          云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档