看了一本书《从Paxos到Zookeeper》,里面讲到二阶段提交协议的缺点有4个,第一个是同步阻塞,引用书里的话是:
二阶段提交协议存在的最明显也是最大的一个问题就是同步阻塞,这会极大地限制分布式系统的性能。在二阶段提交的执行过程中,所有参与事务操作的逻辑都是处于阻塞状态,也就是说,各个参与者在等待其他参与者响应的过程中,将无法进行其他任何操作。
看到这段话,觉得甚是不解啊!
按理来说,按照数据库事务并发执行的理论,只要事务之间没有共同需要访问的的数据,各个事务是可以无序并发执行的。而对于事务之间有共同需要访问的数据的话,按照二阶段锁(2PL)协议,也可以以任意顺序执行,只不过因为有锁,所以其他的事务会阻塞。联系一下,发现这段话少了个前提---就是访问相同的数据(资源)。
还有就是,同步阻塞是保证数据一致性的手段之一,牺牲了并发性能,这在单个数据库也存在这样的问题,在一个分布式系统里面提出这样一个无法解决的问题,似乎没事找事的感觉。
再看三阶段。书里介绍三阶段引入了一个canCommit询问阶段和超时机制,最后说:
相较于二阶段提交协议,三阶段提交协议最大的优点是降低了参与者的阻塞范围,并且能够在出现单点故障后继续达成一致性。
单点故障的解决就是通过超时机制完成的,我就纳闷了,如果我在二阶段也加上超时机制,不也可以解决单点故障后出现的不一致性么?难道只许三阶段加超时,不准二阶段加?还是二阶段加了超时就不叫二阶段了么?
当然了,三阶段的canCommit阶段还是有点作用了,试想以下场景:
场景A:1个协调者,9个参与者,协调者发出canCommit消息后,最后一个参与者断了,协调者收不到最后一个Yes响应。
如果是二阶段,那么协调者需要向另外8个发送Rollback,浪费了很多操作。
如果是三阶段,就不会有这样的问题。
场景B:一个协调者,9个参与者,其中的一个参与者占用着需要访问的资源。
如果是二阶段,那么参与者会阻塞,直到资源可用,才执行事务操作。即使加入了超时,也会跟场景A一样,协调者需要向另外的8个发Rollback,浪费。
如果是三阶段,这时协调者发送canCommit消息,之后收到其中一个No响应,协调者放弃执行事务,其他参与者不做任何处理。
由此可以看出,三阶段多出的这个预先检查阶段好处多多。之后的两个阶段就跟二阶段一样的了。还是会同步阻塞。
所以书里说,
降低了参与者的阻塞范围。
这我同意!
但后一段又说:
三阶段提交协议的缺点:三阶段提交协议在去除阻塞的同时也引入了新的问题,那就是在参与者接收到preCommit消息后,如果网络出现分区,此时协调者所在的节点和参与者无法进行正常的网络通信,在这种情况下,该参与者依然会进行事务的提交,这必然出现数据的不一致性。
刚刚才说降低了参与者的阻塞范围,现在又说去除了阻塞!什么鬼啊,三阶段的后两个阶段不也会占用资源么,其他访问相同资源的进程不也会阻塞么?哪里来的去除了阻塞啊?
还有就是,哪里也引入的了新的问题,出现网络分区后,二阶段也会有数据不一致问题啊。
实在无语。。。就不能用词准备一点么