文章部分图片来自参考资料,侵删
概述
上一篇我们讲到CAP 理论,分区容错性,一致性,可用性三者不可能同时存在,而分区容错性又是客观存在的,那么为了保证可用性,我们牺牲了一致性,虽然我们保证不了强一致性,但是(Base理论)我们可以保证最终一致性。 而 2pc(两阶段提交) 和 3pc(三阶段提交)都是为了一致性协议,通过这些协议保证一致性。
2pc
2PC协议有两个阶段:Propose和Commit.在没有出错的情况下的2PC协议流程的画风是这样的:
- Propose阶段:
- coordinator : "你们准备执行什么什么"
- voter1/voter2/voter3: "收到!(各个节点写入要执行的动作)"
- Commit阶段
- coordinator: "确定执行"
- voter1/voter2/voter3: "好哒(执行的动作落地)
假如在 Propose 有节点没准备好,那协调者就对本次执行 abort
但是 2pc 存在以下问题 , 例如在准备 commit phase 阶段, coordinator 和 voter3 刚好都 crash 了,那么vote1 和 vote2 就尴尬了,为什么呢? 因为现在存在以下的情况 :
(1)上轮全票通过然后voter3第一个收到了commit的消息并在commit操作之后crash了
(2)上轮voter3反对所以干脆没有通过.
那么 vote1 和 vote2 就会处在不知是否是 commit 还是 abort 的困境。同时 2pc 还存在以下的优缺点 :
缺点 :
- 同步阻塞,第二阶段执行任务阶段,各节点都需要阻塞执行完成后,协调者才放开锁定的资源
- 单点问题,协调者要是第二阶段 crash ,部分收到 commit 部分没有收到的话,就会造成数据不一致。
优点 :
- 简单容易实现
2pc 在 CAP 中 属于 CA ,那么没办法解决 分区容错性的问题,但是它在性能和分区容错方面找到了平衡,使得关系数据库都喜欢使用 2pc 来实现分布式事务。
3pc
简单的说来, 3PC就是把2PC的Commit阶段拆成了PreCommit和Commit两个阶段. 通过进入增加的这一个PreCommit阶段, voter可以得到Propose阶段的投票结果, 但不会commit; 而通过进入Commit阶段, voter可以盘出其他每个voter也都打算commit了, 从而可以放心的commit.
换言之, 3PC在2PC的Commit阶段里增加了一个barrier(即相当于告诉其他所有voter, 我收到了Propose的结果啦). 在这个barrier之前coordinator掉线的话, 其他voter可以得出结论不是每个voter都收到Propose Phase的结果, 从而放弃或选出新的coordinator; 在这个barrier之后coordinator掉线的话, 每个voter会放心的commit, 因为他们知道其他voter也都做同样的计划.
下面的是 wiki 上的图 :
但是 3pc 也存在一定的问题 。
- 网络分区时无法恢复
网络划分(network partition)
网络划分指的是 节点互相不能通信。
假设在PreCommit阶段所有节点被一分为二, 收到preCommit消息的voter在一边, 而没有收到这个消息的在另外一边. 在这种情况下, 两边就可能会选出新的coordinator而做出不同的决定.
情景如下所示
fail-recover
fail-recover 就是失败后过一阵子再恢复过来。
当coordinator收到preCommit的确认前crash, 于是其他某一个voter接替了原coordinator的任务而开始组织所有voter commit. 而与此同时原coordinator重启后又回到了网络中, 开始继续之前的回合---发送abort给各位voter因为它并没有收到preCommit. 此时有可能会出现原coordinator和继任的coordinator给不同节点发送相矛盾的commit和abort指令, 从而出现个节点的状态分歧.
总结
可以看到无论是 2pc 还是 3pc
补充
replication 和 partition
我们运用分布式的时候时常会使用两种手段对数据进行处理。一种是 切分,一种是复制,这两种分别对应于 partition 和 replication . 两者的操作如下 :
先说复制吧,最常见的就是主从复制,优势很明显,可以很好地处理分区容错性,要是主挂了,从的马上就可以顶上。缺点数据的一致性,上面的二阶段提交和三阶段提交都是为了解决一致性的问题。而 partition 可以将多个任务分成一小块一小块,充分发挥并发计算,同时解决数据增长带来的冲击,因为每一块都分出去了,所以计算压力得到了平摊。但是也会存在例如分区之间跨区访问受限,数据增长速度不同等问题,还可能存在著名的 Byzantine_fault_tolerance (拜占庭问题)。
拜占庭问题
拜占庭将军问题是一个协议问题,拜占庭帝国军队的将军们必须全体一致的决定是否攻击某一支敌军。问题是这些将军在地理上是分隔开来的,并且将军中存在叛徒。叛徒可以任意行动以达到以下目标:欺骗某些将军采取进攻行动;促成一个不是所有将军都同意的决定,如当将军们不希望进攻时促成进攻行动;或者迷惑某些将军,使他们无法做出决定。如果叛徒达到了这些目的之一,则任何攻击行动的结果都是注定要失败的,只有完全达成一致的努力才能获得胜利。来源 ;百度百科
简单地来说就是协调者发出某个请求,要求各个节点达成共识,共同对外 ,但是内部出现奸细,出现返回来的信息使得大家达不到一致性。
Partition tolerant consensus algorithms
最著名的 partition tolerant consensus 算法就是 Paxos 了,还有 Raft .
network partition
以下的描述很好地解释了 network partition
A network partition is the failure of a network link to one or several nodes. The nodes themselves continue to stay active, and they may even be able to receive requests from clients on their side of the network partition. As we learned earlier
consistency(一致性分类)
Consistency models can be categorized into two types: strong and weak consistency models:
- Strong consistency models (capable of maintaining a single copy)
- Linearizable consistency
- Sequential consistency
- Weak consistency models (not strong)
- Client-centric consistency models
- Causal consistency: strongest model available
- Eventual consistency models (最终一致性)
其中强一致性包括 Linearizable consistency 和 Sequential consistency ,它们两者的差别在于 :
- Linearizable consistency: Under linearizable consistency, all operations appear to have executed atomically in an order that is consistent with the global real-time ordering of operations. (Herlihy & Wing, 1991)
- Sequential consistency: Under sequential consistency, all operations appear to have executed atomically in some order that is consistent with the order seen at individual nodes and that is equal at all nodes. (Lamport, 1979)
参考资料
- 推荐一看
- https://www.the-paper-trail.org/post/2008-11-29-consensus-protocols-three-phase-commit/
- https://www.zhihu.com/question/23645117 (知乎上重要的分布式资料)
- https://courses.cs.washington.edu/courses/csep552/16wi/ (552)
- https://courses.cs.washington.edu/courses/cse552/13au/calendar/lecturelist.html (552)
- 漫话分布式系统共识协议: 2PC/3PC篇
- http://book.mixu.net/distsys/intro.html (推荐一看)