专栏首页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(下一篇会演示)

本文分享自微信公众号 - Liusy01(Liusy_01),作者:Liusy01

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-04-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • k8s之DNS服务器搭建

    在使用k8s部署springboot+redis简单应用这篇文章中,spring boot连接redis是直接使用的IP连接,那么可不可以直接使用服务名称进行连...

    Liusy
  • 【设计模式-单例模式】

    今天来说一下同样属于创建型模式的单例模式,相信这个模式普遍都清楚,因为平时在编码的时候都会进行相应的使用,我这边就当做日志记录一下。免得以后忘了还得去搜,我发现...

    Liusy
  • k8s全系列文章汇总

    k8s的文章一共写了十八篇,是一个比较全面的学习日志。从八月二十九开始发的第一篇文章,到现在十二月份了,从看《Kubernetes权威指南 第4...

    Liusy
  • Java事务解析(事务的基本操作+隔离的等级+事务的四大特性+事务的概念)

    如果一个包含多个步骤的业务操作,这些操作被事务管理,那么这些操作要么同时成功要么同时失败

    一只胡说八道的猴子
  • MySQL深入学习第三篇 -事务隔离:为什么你改了我还看不见?

    提到事务,你肯定不陌生,和数据库打交道的时候,我们总是会用到事务。最经典的例子就是转账,你要给朋友小王转 100 块钱,而此时你的银行卡只有 100 块钱。

    越陌度阡
  • mysql学习笔记(二)事务隔离

    银行转账例子,你要给朋友转账100,并且卡里只有100元。在期间转账中还可以做一些列操作,比如余额查询、余额转出、余额转入等操作,如果业务中显示转账成功...

    虞大大
  • Mysql进阶垫脚石 -- 到底什么是数据库事务?

    事务(Transaction)是并发控制的基本单位。所谓的事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。事务处理可以确保...

    陈哈哈
  • Spring事务的传播属性和隔离级别

    前言:mysql事务在程序运行中事关重大,解决同时运行sql语句的一致性的问题。有效的避免由于异常造成的生产事故。

    王念博客
  • 关系型数据库的ACID(原子性、一致性、隔离性与持久性)

    Coxhuang
  • Mysql - 数据库的隔离级别、传播行为

    夹胡碰

扫码关注云+社区

领取腾讯云代金券