dynamic programming
2PC:
几个缺点:
1、同步阻塞问题。执行过程中,所有参与节点都是事务阻塞型的。当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态。
2、单点故障。由于协调者的重要性,一旦协调者发生故障。参与者会一直阻塞下去。尤其在第二阶段,协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作。(如果是协调者挂掉,可以重新选举一个协调者,但是无法解决因为协调者宕机导致的参与者处于阻塞状态的问题)
3、数据不一致。在二阶段提交的阶段二中,当协调者向参与者发送commit请求之后,发生了局部网络异常或者在发送commit请求过程中协调者发生了故障,这回导致只有一部分参与者接受到了commit请求。而在这部分参与者接到commit请求之后就会执行commit操作。但是其他部分未接到commit请求的机器则无法执行事务提交。于是整个分布式系统便出现了数据部一致性的现象。
4、二阶段无法解决的问题:协调者再发出commit消息之后宕机,而唯一接收到这条消息的参与者同时也宕机了。那么即使协调者通过选举协议产生了新的协调者,这条事务的状态也是不确定的,没人知道事务是否被已经提交。
3PC:
与两阶段提交不同的是,三阶段提交有两个改动点。
•引入超时机制。同时在协调者和参与者中都引入超时机制。•在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。
也就是说,除了引入超时机制之外,3PC把2PC的准备阶段再次一分为二,这样三阶段提交就有CanCommit、PreCommit、DoCommit三个阶段。
canCommit阶段有任何一个参与者向协调者发送了No响应,或者等待超时之后,协调者都没有接到参与者的响应,那么就执行事务的中断。
在doCommit阶段,如果参与者无法及时接收到来自协调者的doCommit或者abort请求时,会在等待超时之后,会继续进行事务的提交。(其实这个应该是基于概率来决定的,当进入第三阶段时,说明参与者在第二阶段已经收到了PreCommit请求,那么协调者产生PreCommit请求的前提条件是他在第二阶段开始之前,收到所有参与者的CanCommit响应都是Yes。(一旦参与者收到了PreCommit,意味他知道大家其实都同意修改了)所以,一句话概括就是,当进入第三阶段时,由于网络超时等原因,虽然参与者没有收到commit或者abort响应,但是他有理由相信:成功提交的几率很大。)
Gossip:
最终一致算法
Gossip协议执行过程:
种子节点周期性的散播消息 【假定把周期限定为 1 秒】。
被感染节点随机选择fanout个邻接节点散播消息【假定fan-out(扇出)设置为6,每次最多往6个节点散播】。
节点只接收消息不反馈结果。
每次散播消息都选择尚未发送过的节点进行散播。
收到消息的节点不再往发送节点散播:A -> B,那么B进行散播的时候,不再发给 A。
Gossip 协议的消息传播方式有两种:Anti-Entropy(反熵传播)和Rumor-Mongering(谣言传播)。
反熵传播是以固定的概率传播所有的数据。
谣言传播是以固定的概率仅传播新到达的数据。
Gossip协议是可扩展的,因为它只需要O(logN) 个周期就能把消息传播给所有节点。某个节点在往固定数量节点传播消息过程中,并不需要等待确认(ack),并且,即使某条消息传播过程中丢失,它也不需要做任何补偿措施。
反熵(Anti-Entropy)指的是集群中的节点,每隔段时间就随机选择某个其他节点,然后通过互相交换自己的所有数据来消除两者之间的差异,实现数据的最终一致性。
同步方式:push,pull, push&pull
缺点:
消息冗余
消息延迟
常见应用有:P2P网络通信、Apache Cassandra、Redis Cluster、Consul。
raft: term
第一次选举:随机超时结束的节点率先发起选举。已经投票的节点会拒绝后发起的选举请求。
leader挂掉的选举:收不到leader的AppendEntry的节点等待随机时间结束,则发起选举。
网络分区后leader下台:
日志复制过程:
1、client发给leader,日志为uncommitted。
2、leader发给follower,follower日志为uncommitted。
3、超过一半follower回ack,leader回复client已收到,leader日志为commited。
4、leader发送给follower可以commit,follower的日志为commited。
网络分区:
节点数少于一半的分区日志复制会失败。
下台leader的分区rollback日志,然后匹配新leader的日志。
paxos:
prepare:
1、需要获取过半acceptor的promise:假设某个提案[M0,V0]已经被选定了,证明任何编号Mn>M0的提案,其Value值都是V0。
2、如果一个Acceptor收到一个编号为Mn的Prepare请求,且编号Mn大于该Acceptor已经响应的所有 Prepare 请求的编号,那么它就会将它已经批准过的最大编号的提案作为响应反馈给Proposer,同时该Acceptor会承诺不会再批准任何编号小于Mn的提案。
accept:
1.如果Proposer收到来自半数以上的Acceptor对于其发出的编号为Mn的Prepare请求的响应,那么它就会发送一个针对[Mn,Vn]提案的Accept请求给Acceptor。注意,Vn的值就是收到的响应中编号最大的提案的值,如果响应中不包含任何提案,那么它就是任意值。
2.如果Acceptor收到这个针对[Mn,Vn]提案的Accept请求,只要该Acceptor尚未对编号大于Mn的Prepare请求做出响应,它就可以通过这个提案。
P1:一个Acceptor必须批准它收到的第一个提案。
P1a:一个Acceptor只要尚未响应过任何编号大于Mn的Prepare请求,那么它就可以接受这个编号为Mn的提案。
P2:如果编号为 M0、Value值为 V0的提案(即[M0,V0])被选定了,那么所有比编号M0更高的,且被选定的提案,其Value值必须也是V0。
P2a:如果编号为M0、Value值为V0的提案(即[M0,V0])被选定了,那么所有比编号M0更高的,且被Acceptor批准的提案,其Value值必须也是V0。
P2b:如果一个提案[M0,V0]被选定后,那么之后任何Proposer产生的编号更高的提案,其Value值都为V0。
P2c:对于任意的 Mn和 Vn,如果提案[Mn,Vn]被提出,那么肯定存在一个由半数以上的Acceptor组成的集合S,满足以下两个条件中的任意一个。
· S中不存在任何批准过编号小于Mn的提案的Acceptor。
· 选取S中所有Acceptor批准的编号小于Mn的提案,其中编号最大的那个提案其Value值是Vn。
P2c=>P2b=>P2a=>P2,然后通过P2和P1来保证一致性。
算法优化:
每个Acceptor只需要记住它已经批准的提案的最大编号以及它已经做出Prepare 请求响应的提案的最大编号,以便在出现故障或节点重启的情况下,也能保证P2c 的不变性。而对于 Proposer 来说,只要它可以保证不会产生具有相同编号的提案,那么就可以丢弃任意的提案以及它所有的运行时状态信息。
随机数生成:
线性同余法:https://zhidao.baidu.com/question/500175878.html