数据不一致问题
因为协调者和参与者之间的交流是经过网络的,而网络有时候就会抽风的或者发生局部网络异常。
那么就有可能导致某些参与者无法收到协调者的请求,而某些收到了。比如是提交请求,然后那些收到命令的参与者就提交事务了,此时就产生了数据不一致的问题。
小结一下 2PC
至此我们来先小结一些 2PC ,它是一个同步阻塞的强一致性两阶段提交协议,分别是准备阶段和提交/回滚阶段。
2PC 的优势在于对业务没有侵入,可以利用数据库自身机制来进行事务的提交和回滚。
它的缺点:是一个同步阻塞协议,会导致高延迟和性能的下降,并且存在协调者单点故障问题,极端情况下会有数据不一致的问题。
当然这只是协议,具体的落地还是可以变通了,比如协调者单点问题,我就搞个主从来实现协调者,对吧。
分布式数据库的 2PC 改进模型
可能有些人对分布式数据库不熟悉,没有关系,我们主要学的是思想,看看人家的思路。
我简单的讲下 Percolator 模型,它是基于分布式存储系统 BigTable 建立的模型,BigTable 是啥也不清楚的同学没有关系影响不大。
还是拿转账的例子来说,我现在有 200 块钱,你现在有 100 块钱,为了突出重点我也不按正常的结构来画这个表。
此时事务管理器发起了准备请求,然后我账上的钱就少了,你账上的钱就多了,而且事务管理器还记录下这次操作的日志。
此时的数据还是私有版本,别的事务是读不到的,简单的理解 Lock 上有值就还是私有的。
可以看到我的记录 Lock 标记的是 PK,你的记录标记的是指向我的记录指针,这个 PK 是随机选择的。
然后事务管理器会向被选择作为 PK 的那条记录发起提交指令。
此时就会把我的记录的锁给抹去了,这等于我的记录不再是私有版本了,别的事务就都能访问了。
那你的记录上还有锁啊?不用更新吗?
嘿嘿不需要及时更新,因为访问你的这条记录的时候会去根据指针找我的那个记录,发现记录已经提交了所以你的记录就可以被访问了。
有人说这效率不就差了,每次都要去找一次,别急。
后台会有个线程来扫描,然后更新把锁记录给去了。
这不就稳了嘛。
相比于 2PC 的改进
首先 Percolator 在提交阶段不需要和所有的参与者交互,主需要和一个参与者打交道,所以这个提交是原子的!解决了数据不一致问题。
然后事务管理器会记录操作日志,这样当事务管理器挂了之后选举的新事务管理器就可以通过日志来得知当前的情况从而继续工作,解决了单点故障问题。
并且 Percolator 还会有后台线程,会扫描事务状况,在事务管理器宕机之后会回滚各个参与者上的事务。
可以看到相对于 2PC 还是做了很多改进的,也是巧妙的。
其实分布式数据库还有别的事务模型,不过我也不太熟悉,就不多哔哔了,有兴趣的同学可以自行了解。
还是挺能拓宽思想的。
XA 规范
让我们再回来 2PC,既然说到 2PC 了那么也简单的提一下 XA 规范,XA 规范是基于两阶段提交的,它实现了两阶段提交协议。
在说 XA 规范之前又得先提一下 DTP 模型,即 Distributed Transaction Processing,这模型规范了分布式事务的模型设计。
而 XA 规范又约束了 DTP 模型中的事务管理器(TM) 和资源管理器(RM)之间的交互,简单的说就是你们两之间要按照一定的格式规范来交流!
我们先来看下 XA 约束下的 DTP 模型。
- AP 应用程序,就是我们的应用,事务的发起者。
- RM 资源管理器,简单的认为就是数据库,具备事务提交和回滚能力,对应我们上面的 2PC 就是参与者。
- TM 事务管理器,就是协调者了,和每个 RM 通信。
简单的说就是 AP 通过 TM 来定义事务操作,TM 和 RM 之间会通过 XA 规范进行通信,执行两阶段提交,而 AP 的资源是从 RM 拿的。
从模型上看有三个角色,而实际实现可以由一个角色实现两个功能,比如 AP 来实现 TM 的功能,TM 没必要抽出来单独部署。
MySQL XA
知晓了 DTP 之后,我们就来看看 XA 在 MySQL 中是如何操作的,不过只有 InnoDB 支持。
简单的说就是要先定义一个全局唯一的 XID,然后告知每个事务分支要进行的操作。
可以看到图中执行了两个操作,分别是改名字和插入日志,等于先注册下要做的事情,通过 XA START XID 和 XA END XID 来包裹要执行的 SQL。
基本上就是这么个流程,不过 MySQL XA 的性能不高这点是需要注意的。
可以看到虽说 2PC 有缺点,但是还是有基于 2PC 的落地实现的,而 3PC 的引出是为了解决 2PC 的一些缺点,但是它整体下来开销更大,也解决不了网络分区的问题,我也没有找到 3PC 的落地实现。
不过我还是稍微提一下,知晓一下就行,纯理论。