写点什么

带你厘清事务一致性(中篇)

用户头像
小舰
关注
发布于: 2021 年 04 月 10 日

在上篇中,我们了解了单机数据库的事务一致性,分布式事务的一致性问题更加棘手,本文就来介绍分布式事务是如何解决这一难题的。

1 分布式事务

在说分布式事务之前,首先要说一下数据分布,准确的说是数据分布式的分布。分布式分布的一个重要原因是组织机构自身分布在若干个节点。例如银行中,尽管用户的某个信息表在逻辑上只有一张表,但是在物理上,在各个分行的数据库中都有一份。

数据分布的结果导致一个事务可能涉及多个节点的处理。因此需要重新构建一个事务处理模型。

2 分布式事务一致性问题

上面提到的,涉及到多个节点的数据处理,我们之前的单机事务模式可能就不合适了,比如我们要怎么管理分布事务的提交或者终止回滚?

考虑这样一个常见的场景:在某个银行转账场景中,小舰和小花的账户数据分别在 A 节点和 B 节点的数据库中,如果小舰想给小花转账 50 元,那么应该在 A 节点的数据库中给小舰的账户余额减去 50,然后再 B 节点的数据库中给小花的账户余额加上 50,这样就保证了数据的一致性。但是如果在 A 节点上执行的扣款操作成功,而在 B 节点上的充值操作失败,亦或者在 B 节点充值成功,A 节点由于余额不足无法完成扣款导致扣款失败,这都会导致出现数据不一致的问题。

3 分布式事务一致性解决方案

分布式数据库决定是否提交一个分布式事务可能使用很复杂的协议,但是它们都基于两阶段提交的基本思想。

两阶段提交:2PC(Two-phase commit protocol),两阶段提交是一种强一致性设计,2PC 引入一个事务协调器的角色来协调管理各节点(也可称之为参与者或各本地资源)的提交和回滚,二阶段分别指的是准备(投票)和提交两个阶段。我们来看下两个阶段的具体流程。


 

图 1 两阶段提交的第一阶段中的消息

提交请求(投票)阶段

· 协调器向所有节点发送 prepare 请求与事务内容,询问是否可以准备事务提交,并等待各个节点的响应。

· 节点执行事务中包含的操作,并记录 undo 日志(用于回滚)和 redo 日志(用于重放),但不真正提交。

· 节点向协调器返回事务操作的执行结果,执行成功返回 ready,否则返回 don't commit。


 

图 2 两阶段提交的第二阶段中的消息

 

提交(执行)阶段

分为成功与失败两种情况。

若所有节点(参与者)都返回 ready,说明事务可以提交:

· 协调器在其节点中记录<commit T>日志;

· 协调器向所有参与者发送 commit 请求。

· 各节点收到 commit 请求后,将事务真正地提交上去,并在此过程中记录日志<commit T>并释放占用的事务资源,并向协调器返回 ack。

· 协调器收到所有节点的 ack 消息,事务成功提交完成。

若有一个或多个节点(参与者)返回 don't commit 或者超时未返回,说明事务中断,需要回滚:

· 协调器在其节点中记录<abort T>日志记录

· 协调器向所有节点发送 abort T 消息

· 各节点收到 abort T 消息后,将各节点中止或者根据 undo 日志回滚到事务执行前的状态,并记录<abort T>日志,释放占用的事务资源,并向协调器返回 ack。

· 协调器收到所有节点的 ack 消息,事务中止或回滚完成。

 

4.总结

以上就是分布式事务采用的两阶段提交的思想,正如前面所讲到的,两阶段提交其实只是一个基本思想,除了 2PC,还有 3PC,TCC 等协议,也是类似的套路,只是进一步的完善,或者扩大了适用范围。

 

发布于: 2021 年 04 月 10 日阅读数: 20
用户头像

小舰

关注

公众号:DLab数据实验室 2020.11.12 加入

中国人民大学硕士

评论

发布
暂无评论
带你厘清事务一致性(中篇)