分布式事务-什么是2阶段提交

「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战

事务的基本特性

我们知道事务有4个非常重要的特性,即我们常说的(ACID)。

Atomicity: 原子性(要么全部执行,要么全部都不执行)

Consistency: 一致性(数据库只有一个状态,不存在未确定状态)

Isolation: 隔离性(事务之间互不干扰)

Durability: 永久性(事务一旦提交,数据库记录永久不变)

2PC&3PC (2阶段提交&3阶段提交)

2阶段提交

两阶段提交又称2PC,2PC是一个非常经典的强一致、中心化的原子提交协议

这里所说的中心化是指协议中有两类节点:一个是中心化协调者节点(coordinator)和N个参与者节点(partcipant)。

两个阶段:第一阶段:投票阶段 和第二阶段:提交/执行阶段

举例 订单服务A,需要调用 支付服务B 去支付,支付成功则处理购物订单为待发货状态,否则就需要将购物订单处理为失败状态。


2pc-step1.drawio.png

第一阶段: 投票阶段

  1. ①.订单服务发起的事物性操作那么订单服务就为事物的发起者,向协调者提出事务请求
  2. ② 协调者接收到事务请求的时候,向所有的参与者发送事务预处理请求(prepare),并且开始等待参与者的响应。
  3. 参与者接收到了协调者的预处理请求的时候,会向协调者返回是否可以提交本地事务(也就是是否执行没有错误)(YES or NO)
  4. ⑴ 各个节点在执行完成本地事务操作的时候,并不会真正的提交本地事务,先执行操作语句但是不会commit ,会保留当前的事务操作连接

如果 参与者 成功执行了事务操作,那么就反馈给协调者 Yes 响应,表示事务可以执行,如果没有 参与者 成功执行事务,那么就反馈给协调者 No 响应,表示事务不可以执行。


第一阶段执行完后,会有两种可能:

所有参与者都返回Yes

2pc-step2-success.drawio.png

①当所有参与者都给协调者返回了yes,代表了所有参与者的业务都没有问题

②当协调者接收到了没有错误的信息后,就会给所有的参与者发送commit请求

③当参与者接收到了commit请求后就会执行本地的commit ,并在完成提交之后释放整个事务执行期间占用的事务资源

执行事务结束后会给协调者上报事务提交结果

到此分布式事务结束

有一个或者多个返回No

2pc-step2-error.drawio.png

①任何一个 参与者 向 协调者 反馈了 No 响应,或者等待超时之后,协调者尚未收到所有参与者的反馈响应。

协调者 向所有参与者节点发出 RoollBack 请求。

③当参与者接收到了RoollBack 请求后,后就会执行本地的rollback,并在完成rollback之后释放整个事务执行期间占用的事务资源

到此分布式事务结束


二阶段提交所带来的缺陷问题

1)性能问题

无论是在第一阶段的过程中,还是在第二阶段,所有的参与者资源和协调者资源都是被锁住的,只有当所有节点准备完毕,事务 协调者 才会通知进行全局提交,参与者 进行本地事务提交后才会释放资源。这样的过程会比较漫长,对性能影响比较大

2)单节点故障

由于协调者的重要性,一旦 协调者 发生故障。参与者 会一直阻塞下去。尤其在第二阶段,协调者 发生故障,那么所有的 参与者 还都处于锁定事务资源的状态中,而无法继续完成事务操作。(虽然协调者挂掉,可以重新选举一个协调者,但是无法解决因为协调者宕机导致的参与者处于阻塞状态的问题)

2PC出现单点问题的三种情况

(1)协调者正常,参与者宕机

由于 协调者 无法收集到所有 参与者 的反馈,会陷入阻塞情况。

解决方案:引入超时机制,如果协调者在超过指定的时间还没有收到参与者的反馈,事务就失败,向所有节点发送终止事务请求。

(2)协调者宕机,参与者正常

无论处于哪个阶段,由于协调者宕机,无法发送提交请求,所有处于执行了操作但是未提交状态的参与者都会陷入阻塞情况.

解决方案:引入协调者备份,同时协调者需记录操作日志.当检测到协调者宕机一段时间后,协调者备份取代协调者,并读取操作日志,向所有参与者询问状态。

(3)协调者和参与者都宕机

1)发生在第一阶段: 因为第一阶段,所有参与者都没有真正执行commit,所以只需重新在剩余的参与者中重新选出一个协调者,新的协调者在重新执行第一阶段和第二阶段就可以了。

2)发生在第二阶段并且挂了的参与者在挂掉之前没有收到协调者的指令。也就是上面的第②步挂了,这是可能协调者还没有发送第4步就挂了。这种情形下,新的协调者重新执行第一阶段和第二阶段操作。

3)发生在第二阶段并且有部分参与者已经执行完commit操作。就好比这里订单服务A和支付服务B都收到协调者 发送的commit信息,开始真正执行本地事务commit,但突发情况,Acommit成功,B确挂了。这个时候目前来讲数据是不一致的。虽然这个时候可以再通过手段让他和协调者通信,再想办法把数据搞成一致的,但是,这段时间内他的数据状态已经是不一致的了! 2PC 无法解决这个问题。


猜你喜欢

转载自juejin.im/post/7054408617780314126