分布式事务 2PC, 3PC, TCC
“分布式事务 2PC, 3PC, TCC” 数据库事务的概念 在讲述分布式事务的概念之前,我们先来回顾下事务相关的一些概念。 事务的基本概念: 就是一个程序执行单元,里面的操作要么全部执行成功,要么全部执行失败,不允许只成功一半另外一半执行失败的事情发生。例如一段事务代码做了两次数据库更新操作,那么这两次数据库操作要么全部执行成功,要么全部回滚。 事务的基本特性: 我们知道事务有4个非常重要的特性,即我们常说的 (ACID) 。 Atomicity (原子性) :是说事务是一个不可分割的整体,所有操作要么全做,要么全不做;只要事务中有一个操作出错,回滚到事务开始前的状态的话,那么之前已经执行的所有操作都是无效的,都应该回滚到开始前的状态。 Consistency (一致性) : 是说事务执行前后,数据从一个状态到另一个状态必须是一致的,比如A向B转账 (A、B的总金额就是一个一致性状态) ,不可能出现A扣了钱,B却没收到的情况发生。 Isolation (隔离性) : 多个并发事务之间相互隔离,不能互相干扰。关于事务的隔离性,可能不是特别好理解,这里的并发事务是指两个事务操作了同一份数据的情况;而对于并发事务操作同一份数据的隔离性问题,则是要求不能出现脏读、幻读的情况,即事务A不能读取事务B还没有提交的数据,或者在事务A读取数据进行更新操作时,不允许事务B率先更新掉这条数据。而为了解决这个问题,常用的手段就是加锁了,对于数据库来说就是通过数据库的相关锁机制来保证。 Durablity (持久性) : 事务完成后,对数据库的更改是永久保存的,不能回滚。 关于数据库事务的基本概念大家可以去网上搜一下,这里只是给大家回顾下事务的基本概念及特性,诸如事务并发问题、事务隔离级别等大家如有遗忘可以去回顾下 (tips: 面试经常会问到的问题哦) 。 3 什么是分布式事务 以上内容我们回顾了下事务的基本概念,那么分布式事务又是个什么概念呢?它与数据库事务之间又有什么区别呢? 其实分布式事务从实质上看与数据库事务的概念是一致的,既然是事务也就需要满足事务的基本特性 (ACID) ,只是分布式事务相对于本地事务而言其表现形式有很大的不同。举个例子,在一个JVM进程中如果需要同时操作数据库的多条记录,而这些操作需要在一个事务中,那么我们可以通过数据库提供的事务机制 (一般是数据库锁) 来实现。 而随着这个JVM进程 (应用) 被拆分成了微服务架构,原本一个本地逻辑执行单元被拆分到了多个独立的微服务中,这些微服务又分别操作不同的数据库和表,服务之间通过网络调用。 举个例子: 服务A收到一笔购物下单请求后,需要调用服务B去支付,支付成功则处理购物订单为待发货状态,否则就需要将购物订单处理为失败状态。 (如图所示) 640?wx_fmt=png 在上面这个例子中会不会出现服务B支付成功了,但是由于网络调用的问题没有通知到服务A,导致用户付了钱,但是购物订单无法显示支付成功的状态呢? 答案是这种情况是普遍存在的,因为服务B在处理成功后需要向服务A发送网络请求,而这个过程是极有可能失败的。那么如何确保“服务A->服务B”这个过程能够组成一个事务,要么全部成功、要么全部失败呢?而这就是典型的需要通过分布式事务解决的问题。 分布式事务是为了解决微服务架构 (形式都是分布式系统) 中不同节点之间的数据一致性问题。这个一致性问题本质上解决的也是传统事务需要解决的问题,即一个请求在多个微服务调用链中,所有服务的数据处理要么全部成功,要么全部回滚。当然分布式事务问题的形式可能与传统事务会有比较大的差异,但是问题本质是一致的,都是要求解决数据的一致性问题。 而分布式事务的实现方式有很多种,最具有代表性的是由Oracle Tuxedo系统提出的XA分布式事务协议。XA协议包括两阶段提交 (2PC) 和三阶段提交 (3PC) 两种实现,接下来我们分别来介绍下这两种实现方式的原理。 两阶段提交 (2PC) 分布式事务的解决方案 两阶段提交/XA 两阶段提交,顾名思义就是要分两步提交。存在一个负责协调各个本地资源管理器的事务管理器,本地资源管理器一般是由数据库实现,事务管理器在第一阶段的时候询问各个资源管理器是否都就绪?如果收到每个资源的回复都是 yes,则在第二阶段提交事务,如果其中任意一个资源的回复是 no, 则回滚事务。 大致的流程: 第一阶段 (prepare) : 事务管理器向所有本地资源管理器发起请求,询问是否是 ready 状态,所有参与者都将本事务能否成功的信息反馈发给协调者; 第二阶段 (commit/rollback): 事务管理器根据所有本地资源管理器的反馈,通知所有本地资源管理器,步调一致地在所有分支上提交或者回滚。 ...