分布式核心技术
一、分布式一致性
基本问题
拜占庭将军问题,主要是两点:
1、无法保证信使不被暗杀,消息无法到达
2、无法保证信使是否叛徒,消息被更改
理论上的拜占庭问题无法达成消息一致,所以,退一步来考虑相对现实的场景:假设消息不被更改,那么就只考虑消息无法到达的问题了。
几个一致性算法
Paxos算法、<wiz_tmp_highlight_tag class="cm-searching">Raft算法、ZAB算法、Gossip算法
Paxos算法
基本思想就是多数通过
角色:Proposer、Acceptor、Learners
其实Paxos算法就下面这么几个原则:
1)Paxos算法包括两个阶段:第一个阶段主要是准备(prepare),还没有提出提议;第二个阶段是接受(accept), 主要根据第一阶段的结果,明确接受谁的提议,并明确提议的内容是什么(这个提议可能是贿选胜出“提议者”自己的提议,也可能是前任意见领袖的提议,具体是哪个提议,见下面第3点原则)。
2)编号(贿赂金额)很重要,无论在哪个阶段,编号(贿赂金额)小的,都会被鄙视(被拒绝)。
3)在第一阶段中,一旦“接受者”已经接受了之前意见领袖的提议,那后面再来找这个“接受者”的“提议者”,即便在贿赂中胜出,也要被洗脑,默默将自己的提议改为前任意见领袖的提议,然后他会在第二阶段提出该提议(也就是之前意见领袖的提议,以力争让大家的意见趋同)。如果“接受者”之前没有接受过任何提议,那贿选胜出的“提议者”就可以提出自己的提议了。
详细可参考:
<wiz_tmp_highlight_tag class="cm-searching">Raft共识算法
简单好理解的共识算法。
<wiz_tmp_highlight_tag class="cm-searching">Raft算法中,节点有三种角色:follower、candidate、leader(部下,候选人、领导)
<wiz_tmp_highlight_tag class="cm-searching">Raft包括两个重要过程:选主(Leader Election)和复制日志 (Log Replication)。
Leader Election过程:
1、一开始,大家都是follower, 没有leader、也没有candidate,然后大家都开始各自进行成为candidate倒计时。
2、计时结束后,节点没有收到任何leader的消息,则变成candidate,并给其他节点发送选举,期望成为leader
3、其他节点收到选举请求(vote request), 在之前没有vote给其他节点的情况下,会马上同意,并应答。
4、发送vote request的candidate一旦收到超过半数的agree, 就升级为leader。
5、leader每隔一小段时间就给所有follower一个heartbeat,告诉我还活着,不用再次Leader Election。
6、follower收到heartbeat后会重置计时、candidate收到heartbeat后会退化到follower。
问题1:原来的leader1选中后,掉线了,系统重新选主leader2,这时候leader1又连上了,会怎么办?
每次选举都有一个批号(term),从小到大, 低term服从高term,所以leader1自动退化为follower。
问题2:系统初始有4个follower,某个term时,两个follower同时成为candidate,并各自拿到2个follower的一个vote,无法选主怎么办?
会在超时之后,进行下一次Leader Election, 由于并非每次超时都一致,所以最终总会选出leader。
Log Replication
Log replication主要分为两个阶段,分发和提交。
1、客户端发送请求给 Leader,储存数据 “sally”,Leader 先将数据写在本地日志,这时候数据还是 Uncommitted 。
2、Leader 给 所有Follower 发送 AppendEntries 请求(分发),数据在 Follower 上没有冲突,则将数据暂时写在本地日志,Follower 的数据也还是 Uncommitted。
3、Follower 将数据写到本地后,返回 OK。Leader 收到后成功返回,只要收到的成功的返回数量超过半数 (包含Leader),Leader 将数据 “sally” 的状态改成 Committed。
4、leader应答客户端成功
5、Leader 再次给 Follower 发送 AppendEntries 请求(提交),收到请求后,Follower 将本地日志里 Uncommitted 数据改成 Committed。这样就完成了一整个复制日志的过程,三个节点的数据是一致的。
ZAB算法
zookeeper使用的算法。
Gossip算法
俗称“谣言传播算法”
数据可达到最终一致
Gossip 过程是由种子节点发起,当一个种子节点有状态需要更新到网络中的其他节点时,它会随机的选择周围几个节点散播消息,收到消息的节点也会重复该过程,直至最终网络中所有的节点都收到了消息。这个过程可能需要一定的时间,由于不能保证某个时刻所有节点都收到消息,但是理论上最终所有节点都会收到消息,因此它是一个最终一致性协议。
下面,我们通过一个具体的实例来体会一下 Gossip 传播的完整过程
为了表述清楚,我们先做一些前提设定:
(1)Gossip 是周期性的散播消息,把周期限定为 1 秒
(2)被感染节点随机选择 k 个邻接节点(fan-out)散播消息,这里把 fan-out 设置为 3,每次最多往 3 个节点散播。
(3)每次散播消息都选择尚未发送过的节点进行散播
(4)收到消息的节点不再往发送节点散播,比如 A -> B,那么 B 进行散播的时候,不再发给 A。
优点:简单、节点数不影响性能、去中心化、最终一致。
缺点:最终一致慢、消息重复冗余
二、分布式可用性
由于CAP理论表明,P不可避免,C和A需要根据业务特性选择
对于不同业务,对于可用性和一致性的权衡,大致分成两类:ACID和BASE
ACID强调强一致性,适用数据要求高度一致的业务场景,如事务,常见在银行、金融等
BASE强调基础可用,软着陆、达到最终一致。适合大部分互联网业务场景。
可用性涉及副本分发,副本分发对应三种:
1、全同步:强一致性
2、全异步:高可用
3、半同步:最终一致
三、分布式的可扩展性
扩展性的一些做法:
1、接入层:DNS+LVS
2、逻辑层:接入层通过负载均衡
四、分布式事务
(未完待续更新中)