链接:http://blog.chinaunix.net/uid-27105712-id-3274863.html
上图中每个节点,每一步都有log记录,以准备rollback,其中任何一步都有失败的可能,收不到对方的消息。
在 phase 1阶段,任何错误包括超时错误,都不会产生任何问题。
在 phase 2阶段,如果是coordinator发出global commit后,有个或几个cohorts失效。就发生了数据不一致的错误,存在一些cohorts更新数据,一些cohorts没有更新数据。但是,coordinator没有机会向所有cohorts发出global abort撤销提交。
在实际生产环境中,2PC很少被使用。一般使用其改进版:如D2PC()
疑问是:
分布式系统的一次请求的结果是三态的,即1.成功 2.失败 3.超时;
2PC 的思想是“一损俱损,共荣俱荣”
那么可能在phase2 阶段,提交一个commit请求到各个参与者去执行,就有可能遇到分布式系统的分区错误(网络失连)、或者某个参与者就是commit错误了,导致了协调者认为此次事务失败,应该回滚操作;(如何实现回滚,是依据被认为不可丢失不会被破坏的日志来做实现的。)
到了这一步:出现的情形就是有的节点数据其实是提交成功了,有的节点数据可能没有提交成功,如果此时协调者发起回滚请求,由于存在网络分区,那么无法保证这些节点的数据最终全部都恢复到了事务操作之前的状态;经过这一事务操作之后,节点数据不一致了,虽然别认为此次操作失败的,但是客户端如何还是会读取各个节点,怎么知道数据上次的操作是成功了还是失败了呢,怎么保证做了2PC之后的节点数据的一致性呢。
这样看来,读一致性的保证与写的一致性的保证是两个应该隔离开来对待的问题,不能以为写的一致性算法保证了写的一致性,而执行读操作时就相信了数据是一致性的。
应该这样理解:分布式系统的一致性问题,有丰富的含义,可以细分很多的一致性问题来,必须细究其准备的描述对象与意义所在
那么对待这个读一致性的问题,可以这样做解决,读的时候,也可以通过协调者走两个阶段的请求,第一个阶段协调者负责随机从一个参与者哪里获得数据,如果得到数据就进入第二阶段:协调者去所有的参与者查询下是否都有这个数据;按照2PC的原则,返回结果给客户端; 怎么感觉,这么两个阶段完全可以反着来啊,反着来效率还高一点。
至于文中描述的D2PC 是啥意思,难道是Double的意思;如果是失败一次再重试一次2PC ,感觉也无法解决问题; 重试的结果往往就是结果的重复,除非重试很多次;