两阶段提交php
Two-phase Commit(2PC):保证一个事务跨越多个节点时保持 ACID 特性;算法
两类节点:协调者(Coordinator)和参与者(Participants),协调者只有一个,参与者能够有多个。分布式
过程:url
-
准备阶段:协调者询问参与者事务是否执行成功;spa
-
提交阶段:若是事务在每一个参与者上都执行成功,协调者发送通知让参与者提交事务;不然,协调者发送通知让参与者回滚事务。.net
须要注意的是,在准备阶段,参与者执行了事务,可是还未提交。只有在提交阶段接收到协调者发来的通知后,才进行提交或者回滚。3d
存在的问题日志
-
参与者发生故障。解决方案:能够给事务设置一个超时时间,若是某个参与者一直不响应,那么认为事务执行失败。blog
-
协调者发生故障。解决方案:将操做日志同步到备用协调者,让备用协调者接替后续工做。进程
Paxos(Lamport):
分布式系统中的节点通讯存在两种模型:共享内存(Shared memory)和消息传递(Messages passing)。
基于消息传递通讯模型的分布式系统,不可避免的会发生如下错误:进程可能会慢、被杀死或者重启,消息可能会延迟、丢失、重复,在基础Paxos场景中,先不考虑可能出现消息篡改即拜占庭错误的状况。
Paxos算法解决的问题是在一个可能发生上述异常的分布式系统中如何就某个值达成一致,保证不论发生以上任何异常,都不会破坏决议的一致性。
主要有三类节点:
- 提议者(Proposer):提议一个值;
- 接受者(Acceptor):对每一个提议进行投票;
- 告知者(Learner):被告知投票的结果,不参与投票过程。
过程:
规定一个提议包含两个字段:[n, v],其中 n 为序号(具备惟一性),v 为提议值。
下图演示了两个 Proposer 和三个 Acceptor 的系统中运行该算法的初始过程,每一个 Proposer 都会向全部 Acceptor 发送提议请求。
当 Acceptor 接收到一个提议请求,包含的提议为 [n1, v1],而且以前还未接收过提议请求,那么发送一个提议响应,设置当前接收到的提议为 [n1, v1],而且保证之后不会再接受序号小于 n1 的提议。
以下图,Acceptor X 在收到 [n=2, v=8] 的提议请求时,因为以前没有接收过提议,所以就发送一个 [no previous] 的提议响应,而且设置当前接收到的提议为 [n=2, v=8],而且保证之后不会再接受序号小于 2 的提议。其它的 Acceptor 相似。
若是 Acceptor 接受到一个提议请求,包含的提议为 [n2, v2],而且以前已经接收过提议 [n1, v1]。若是 n1 > n2,那么就丢弃该提议请求;不然,发送提议响应,该提议响应包含以前已经接收过的提议 [n1, v1],设置当前接收到的提议为 [n2, v2],而且保证之后不会再接受序号小于 n2 的提议。
以下图,Acceptor Z 收到 Proposer A 发来的 [n=2, v=8] 的提议请求,因为以前已经接收过 [n=4, v=5] 的提议,而且 n > 2,所以就抛弃该提议请求;Acceptor X 收到 Proposer B 发来的 [n=4, v=5] 的提议请求,由于以前接收到的提议为 [n=2, v=8],而且 2 <= 4,所以就发送 [n=2, v=8] 的提议响应,设置当前接收到的提议为 [n=4, v=5],而且保证之后不会再接受序号小于 4 的提议。Acceptor Y 相似。
当一个 Proposer 接收到超过一半 Acceptor 的提议响应时,就能够发送接受请求。
Proposer A 接受到两个提议响应以后,就发送 [n=2, v=8] 接受请求。该接受请求会被全部 Acceptor 丢弃,由于此时全部 Acceptor 都保证不接受序号小于 4 的提议。
Proposer B 事后也收到了两个提议响应,所以也开始发送接受请求。须要注意的是,接受请求的 v 须要取它收到的最大 v 值,也就是 8。所以它发送 [n=4, v=8] 的接受请求。
Acceptor 接收到接受请求时,若是序号大于等于该 Acceptor 承诺的最小序号,那么就发送通知给全部的 Learner。当 Learner 发现有大多数的 Acceptor 接收了某个提议,那么该提议的提议值就被 Paxos 选择出来。
---------------------------------------------------------------------------------------------------
Raft(14年):简化,更容易理解,也更容易实现。
引入主节点,经过竞选。
节点类型:Follower、Candidate 和 Leader
Leader 会周期性的发送心跳包给 Follower。每一个 Follower 都设置了一个随机的竞选超时时间,通常为 150ms~300ms,若是在这个时间内没有收到 Leader 的心跳包,就会变成 Candidate,进入竞选阶段。
流程:
① 下图表示一个分布式系统的最初阶段,此时只有 Follower,没有 Leader。Follower A 等待一个随机的竞选超时时间以后,没收到 Leader 发来的心跳包,所以进入竞选阶段。
② 此时 A 发送投票请求给其它全部节点。
③ 其它节点会对请求进行回复,若是超过一半的节点回复了,那么该 Candidate 就会变成 Leader。
④ 以后 Leader 会周期性地发送心跳包给 Follower,Follower 接收到心跳包,会从新开始计时。
多个 Candidate 竞选
① 若是有多个 Follower 成为 Candidate,而且所得到票数相同,那么就须要从新开始投票,例以下图中 Candidate B 和 Candidate D 都得到两票,所以须要从新开始投票。
② 当从新开始投票时,因为每一个节点设置的随机竞选超时时间不一样,所以能下一次再次出现多个 Candidate 并得到一样票数的几率很低。
日志复制
① 来自客户端的修改都会被传入 Leader。注意该修改还未被提交,只是写入日志中。
② Leader 会把修改复制到全部 Follower。
③ Leader 会等待大多数的 Follower 也进行了修改,而后才将修改提交。
④ 此时 Leader 会通知的全部 Follower 让它们也提交修改,此时全部节点的值达成一致。