zoukankan      html  css  js  c++  java
  • 二阶段提交抱不平

    看了一本书《从Paxos到Zookeeper》,里面讲到二阶段提交协议的缺点有4个,第一个是同步阻塞,引用书里的话是:

    二阶段提交协议存在的最明显也是最大的一个问题就是同步阻塞,这会极大地限制分布式系统的性能。在二阶段提交的执行过程中,所有参与事务操作的逻辑都是处于阻塞状态,也就是说,各个参与者在等待其他参与者响应的过程中,将无法进行其他任何操作。

    看到这段话,觉得甚是不解啊!

      按理来说,按照数据库事务并发执行的理论,只要事务之间没有共同需要访问的的数据,各个事务是可以无序并发执行的。而对于事务之间有共同需要访问的数据的话,按照二阶段锁(2PL)协议,也可以以任意顺序执行,只不过因为有锁,所以其他的事务会阻塞。联系一下,发现这段话少了个前提---就是访问相同的数据(资源)

     

      还有就是,同步阻塞是保证数据一致性的手段之一,牺牲了并发性能,这在单个数据库也存在这样的问题,在一个分布式系统里面提出这样一个无法解决的问题,似乎没事找事的感觉。

     

    再看三阶段。书里介绍三阶段引入了一个canCommit询问阶段和超时机制,最后说:

    相较于二阶段提交协议,三阶段提交协议最大的优点是降低了参与者的阻塞范围,并且能够在出现单点故障后继续达成一致性。

      单点故障的解决就是通过超时机制完成的,我就纳闷了,如果我在二阶段也加上超时机制,不也可以解决单点故障后出现的不一致性么?难道只许三阶段加超时,不准二阶段加?还是二阶段加了超时就不叫二阶段了么?

     

    当然了,三阶段的canCommit阶段还是有点作用了,试想以下场景:

    场景A:1个协调者,9个参与者,协调者发出canCommit消息后,最后一个参与者断了,协调者收不到最后一个Yes响应。

      如果是二阶段,那么协调者需要向另外8个发送Rollback,浪费了很多操作。

      如果是三阶段,就不会有这样的问题。

    场景B:一个协调者,9个参与者,其中的一个参与者占用着需要访问的资源。

      如果是二阶段,那么参与者会阻塞,直到资源可用,才执行事务操作。即使加入了超时,也会跟场景A一样,协调者需要向另外的8个发Rollback,浪费。

      如果是三阶段,这时协调者发送canCommit消息,之后收到其中一个No响应,协调者放弃执行事务,其他参与者不做任何处理。

     

    由此可以看出,三阶段多出的这个预先检查阶段好处多多。之后的两个阶段就跟二阶段一样的了。还是会同步阻塞。

    所以书里说,

    降低了参与者的阻塞范围。

      这我同意!

    但后一段又说:

    三阶段提交协议的缺点:三阶段提交协议在去除阻塞的同时也引入了新的问题,那就是在参与者接收到preCommit消息后,如果网络出现分区,此时协调者所在的节点和参与者无法进行正常的网络通信,在这种情况下,该参与者依然会进行事务的提交,这必然出现数据的不一致性。

      刚刚才说降低了参与者的阻塞范围,现在又说去除了阻塞!什么鬼啊,三阶段的后两个阶段不也会占用资源么,其他访问相同资源的进程不也会阻塞么?哪里来的去除了阻塞啊?

    还有就是,哪里也引入的了新的问题,出现网络分区后,二阶段也会有数据不一致问题啊。

     

    实在无语。。。就不能用词准备一点么

     

  • 相关阅读:
    虚拟机VirtualBox 共享挂载问题:mount: /mnt/xxx: wrong fs type, bad option, bad superblock on xxx
    git 设置和取消代理
    (转载)数据库连接池到底应该设多大?这篇文章可能会颠覆你的认知
    关于golang中IO相关的Buffer类浅析
    (转)golang获取当前时间、时间戳和时间字符串及它们之间的相互转换
    FFmpeg常用命令
    go cmd nohup 的坑
    Nginx配置详解(转)
    记录一次go性能调试的过程
    github徽标引入
  • 原文地址:https://www.cnblogs.com/cool-fire/p/10736487.html
Copyright © 2011-2022 走看看