一万四千字分布式事务原理解析,全部掌握你还怕面试被问? (2)

只有当送信士兵成功往返后,总指挥才能确认这场战争的胜利(上方图)。现在问题来了,派遣出去送信的士兵没有回来,则左侧蓝军中的总指挥能不能决定按命令中约定的时间发起进攻?

答案是不确定,派遣出去送信的士兵没有回来,他可能遇到两种状况:

1)命令还没送达就被俘虏了(中间图),这时候右侧蓝军根本不知道要何时进攻;

2)命令送达,但返回途中被俘虏了(下方图),这时候右侧蓝军知道要何时进攻,但左侧蓝军不知道右侧蓝军是否知晓进攻时间。

类似的问题在计算机网络中普遍存在,例如发送者给接受者发送一个 HTTP 请求,或者 MySQL 客户端向 MySQL 服务器发送一条插入语句,然后超时了没有得到响应。请问服务器是写入成功了还是失败了?答案是不确定,有以下几种情况:

1)可能请求由于网络故障根本没有送到服务器,因此写入失败;

2)可能服务器收到了,也写入成功了,但是向客户端发送响应前服务器宕机了;

3)可能服务器收到了,也写入成功了,也向客户端发送了响应,但是由于网络故障未送到客户端。

无论哪种场景,在客户端看来都是一样的结果:它发出的请求没有得到响应。为了确保服务端成功写入数据,客户端只能重发请求,直至接收到服务端的响应。

类似的问题问题被称为网络二将军问题。

网络二将军问题的存在使得消息的发送者往往要重复发送消息,直到收到接收者的确认才认为发送成功,但这往往又会导致消息的重复发送。例如电商系统中订单模块调用支付模块扣款的时候,如果网络故障导致二将军问题出现,扣款请求重复发送,产生的重复扣款结果显然是不能被接受的。因此要保证一次事务中的扣款请求无论被发送多少次,接收方有且只执行一次扣款动作,这种保证机制叫做接收方的幂等性。

一万四千字分布式事务原理解析,全部掌握你还怕面试被问?

2.3 两阶段提交(2PC) & 三阶段提交(3PC)方案

2PC 是一种实现分布式事务的简单模型,这两个阶段是:

1)准备阶段:事务协调者向各个事务参与者发起询问请求:“我要执行全局事务了,这个事务涉及到的资源分布在你们这些数据源中,分别是……,你们准备好各自的资源(即各自执行本地事务到待提交阶段)”。各个参与者协调者回复 yes(表示已准备好,允许提交全局事务)或 no(表示本参与者无法拿到全局事务所需的本地资源,因为它被其他本地事务锁住了)或超时。

2)提交阶段:如果各个参与者回复的都是 yes,则协调者向所有参与者发起事务提交操作,然后所有参与者收到后各自执行本地事务提交操作并向协调者发送 ACK;如果任何一个参与者回复 no 或者超时,则协调者向所有参与者发起事务回滚操作,然后所有参与者收到后各自执行本地事务回滚操作并向协调者发送 ACK。

2PC 的流程如下图所示:

一万四千字分布式事务原理解析,全部掌握你还怕面试被问?

从上图可以看出,要实现 2PC,所有的参与者都要实现三个接口:

Prepare():TM 调用该接口询问各个本地事务是否就绪

Commit():TM 调用该接口要求各个本地事务提交

Rollback():TM 调用该接口要求各个本地事务回滚

可以将这三个接口简单地(但不严谨地)理解成 XA 协议。XA 协议是 X/Open 提出的分布式事务处理标准。MySQL、Oracle、DB2 这些主流数据库都实现了 XA 协议,因此都能被用于实现 2PC 事务模型。

2PC 简明易懂,但存在如下的问题:

1)性能差,在准备阶段,要等待所有的参与者返回,才能进入阶段二,在这期间,各个参与者上面的相关资源被排他地锁住,参与者上面意图使用这些资源的本地事务只能等待。因为存在这种同步阻塞问题,所以影响了各个参与者的本地事务并发度;

2)准备阶段完成后,如果协调者宕机,所有的参与者都收不到提交或回滚指令,导致所有参与者“不知所措”;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwdfjp.html