分布式数据一致性常见协议总结 NWR、Gossip、Paxos、Raft、Lease
分布式事务一致性和数据一致性的理解
分布式数据一致性,是保证同一个数据能在系统不同节点间保持一致状态,让一个数据或者状态的变更,在整个系统上看起来是一致的。CAP理论就是针对的分布式存储系统数据一致性的。
分布式事务一致性,是让一个事务发生前后,其涉及的数据库数据不论成功还是失败系统的数据状态能继续保持一致。
一、NWR协议
1.1 NWR协议介绍
NWR协议是一种分布式存储系统中,用于控制一致性级别的一种策略。亚马逊的云存储中,就是用NWR来控制一致性。
- N :在分布式存储系统中标识有多少份备份数据。可以理解为节点
- W:代表一次成功的更新操作至少成功写入的数据份数
- R:代表一次成功读取数据,至少要求读取的数份数
1.2 原理
NWR值的不同组合可以达到不同的一致性效果。
- 当W+R>N 系统数据一致性级别达到强一致性,也就是说一次成功读取数据一定会读取到最新的数据节点。因为R>N-W,N-W代表未写入更新的节点数量。
- 当 W+R ≤ N 系统无法达到强一致性,因为R无法完全覆盖未更新数据的节点。
二、Gossip协议
2.1 Gossip 协议介绍
Gossip ( /ˈɡɒsɪp/ 流言) 协议也叫Epidemic协议(流行病协议)。原本用于分布式数据库中节点同步数据使用,后面又被用于数据库复制、信息扩散、集群成员身份确认、故障探测等。
Gossip 协议利用一种随机的方式将信息传播到整个网络中,并在一段时间内使得系统内所有节点数据一致。Gossip其实是一种去中心化思路的分布式协议,解决状态在集群中传播和状态一致性的保证两个问题。
2.2 Gossip协议原理
Gossip协议的消息传播方式有两种
- 反熵传播 以固定的概率传播所有的节点,所有参与的节点只有两种状态 Suspective(病原体)和Infective(感染)。过程是种子节点会把所有的数据都跟其他节点共享,以便消除节点之间数据的任何不一致,可以保证最终、完全的一致。缺点是消息数量非常庞大,且无限制;一般用于新加入节点的数据初始化!
- 谣言传播 以固定概率传播新到达的数据,所有参与节点有三种状态:Suspective(病原体)、Infective(感染)、Removed(愈除)。过程消息只包含最新update,谣言消息在某个时间点之后会被标记为removed,并且不再被传播。缺点是系统会有一定的概率不一致,通常用于节点间数据增量同步。
2.3 Gossip协议通信方式
Gossip协议最终目的是将数据分发到网络中的没一个节点,根据不同的具体应用场景,网络中两个节点间存在三种通信方式:推送模式、拉取模式、推/拉模式
PUSH模式
节点A将数据(key,value,version)以及对应的版本号推送给B节点,B节点更新A中比自己新的数据。
Pull模式
A将自己数据的key,version发送给B,B将本地比A新的数据推送给A,A更新本地。
Push/pull
与pull类似,只是多了一步,A再将比B新的数据推送给B,B则更新本地
2.4 Gossip协议优缺点
Gossip是一种去中心化的分布式协议,数据通过节点像病毒一样逐个传播。因为是指数传播,整体速度非常快。
优点:
- 拓展性:允许节点的任意增加和减少,新增节点的状态最终会与其他节点一致。
- 容错性:任意节点的宕机和重启都不会影响Gossip消息的传播,具有天然的分布式系统容错性特性。
- 最终一致性:Gossip协议实现消息指数级的快速传播,因此在有新消息需要传播时,消息可以快速的传播到全局节点。
缺点:
- 消息延迟:节点随机向少数几个节点发送消息,消息最终通过多个轮次的散播而达到全网,不可避免的造成消息延迟。
- 消息冗余:节点定期随机选择周围节点发送消息,收到的消息节点也会重复改步骤,不可避免的引起同意节点消息多次接收,增大消息压力。
场景:适合AP(可用性、分区一致性)场景的数据一致性处理,例如 p2p网路通信,Redis Cluster 、Consul
三、Paxos协议
3.1 什么是Paxos协议
Paxos由莱斯利·兰伯特(Leslie Lamport)于1998年在《The Part-Time Parliament》论文中首次公开,最初的描述使用希腊的一个小岛Paxos,描述了Paxos小岛中通过决议的流程,并以此命名这个算法,但是这个描述理解起来比较有挑战性。后来在2001年,莱斯利·兰伯特重新发表了朴实的算法描述版本《Paxos Made Simple》
paxos 是一个共识协议
paxos协议就是paxos算法,Paxos算法是基于消息传递且具有高度容错性的一致性算法,是目前公认的解决分布式一致性问题最有效的算法之一。
自从Paxos问世,就持续垄断了分布式一致性算法,Paxos这个名词几乎等同于分布式一致性,很多大型分布式系统都采用了Paxos算法来解决分布式一致性问题,比如Chubby、Megastore、Spanner、Zookeeper、Mysql5.7的Group Replication
3.2 Paxos解决了什么问题
分布式系统中常见的问题,例如 机器宕机、网络异常(消息延迟、丢失、重复、乱序、网络分区)等情况。
Paxos算法就是解决在可能发生上述异常的分布式系统中,快速且正确的在集群内部对某个数据的值达成一致(数据的值是范指),并且保证不论发生以上任何一场,都不会破坏系统的一致性。
3.3 Paxos的版本
- Paxos的版本有:Basic Paxos、Multi Paxos、Fast-Paxos、ZAB 具体落地有Raft和zk的ZAB协议。zab是Paxos的工业实现。
- 其他的分布式一致性协议还有Raft协议
3.4 Basic Paxos介绍
角色介绍
- Client 客户端 :客户端向分布式系统发出请求,并且等待响应。例如对分布式文件服务器文件的更新请求
- Proposer 提议者:提案者提倡客户端请求,尝试说服Acceptor达成一致,并在发生冲突时充当协调者以推动协议向前发展。
- Acceptor 决策者:可以批提案,Acceptor可以接受提案,并且进行投票,投票结果是否通过以多数派为准,如果某个提案被选定,那么该提案的value就被选定了。
- Learner 学习者,学习者充当该协议的复制因素 不参与投票
流程 basic paxos 流程分为四个步骤
- Prepare proposer提出一个提案,编号为N,N大于这个proposer之前提出的所有编号,请求Accpetor的多数人接受这个提案
- Promise 如果编号N大于此之前Accpetor之前接受过的所有提案编号就接受,否则就拒绝。
- Accept 如果达到多数派,Proposer会发出accept请求,请求包含提案编号和对应的内容
- Accepted 如果此Acceptor再次期间没有接受到任何大于N的提案,则接收此提案内容,否则就忽略。
时序流程图
- 无故障的basic Paxos
- Acceptor失败时的basic Paxos,在下图中,多数派中的一个Acceptor发生故障,因此多数派大小变为2。在这种情况下,Basic Paxos协议仍然成功。
- Proposer失败时的basic Paxos Proposer在提出提案之后但在达成协议之前失败。具体来说,传递到Acceptor的时候失败了,这个时候需要选出新的Proposer(提案人),那么 Basic Paxos协议仍然成功
活锁是指任务或者执行者没有被阻塞,由于某些条件没有满足,导致一直重复尝试,失败,尝试,失败的过程。处于活锁的实体是在不断的改变状态,活锁有可能自行解开。
- 当多个提议者发生冲突时的basic Paxos 最复杂的情况是多个Proposer都进行提案,导致Paxos的活锁问题。只需要在每个Proposer 重复提案时加上一个随机等待时间即可解决。
3.5 Multi-Paxos 介绍
Basic Paxos存在的不足
- 流程复杂,实现困难
- 效率有点低,一轮一次性的达成,需要2轮RPC调用
Mulit-Paxos 流程图
- 情况1 未确定Leader 先确定Leader再复制
- 情况2 已确定Leader 直接由Leader确定,并复制
Mulit-Paxos 合并角色流程图
Multi-Paxos 实施时会将Proposer、Acceptor、Learner合并,统称为服务器,这样到最后只有 客户端和服务器交互
四、Raft协议
4.1 Raft协议介绍
- Paxos算法论证了一致性协议的可行性,但是论证过程晦涩难懂。缺少必要的实现细节,而且工程实现难度较高,广为人知的只有Zk的实现,ZAB协议。但是Paxos为分布式强一致性提供了很好的理论基础。
- 斯坦福大学RamCloud项目中提出了易实现,易理解的分布式一致性复制协议 Raft。
- paxos是唯一正确的共识协议(共识算法),但是没有工程实践上的直接意义。所有的工程实践,都需要对Paxos进行优化,最后都优化成了Raft的样子,Raft不仅仅是一个共识算法,而是一套完整的工程实践。
Raft引入主节点,通过竞选确定主节点。节点类型有 Follower(追随者)、Candidate(竞选者)、Leader。
Leader节点会周期性的发送心跳包给 Follower 每个Follower都设置了一个随机的竞选超时时间,一般 150~300ms,这个时间内没有收到Leader的心跳包,就会变成Candidate进入竞选阶段。通过竞选阶段的投票多的就成为Leader
4.2 Raft 概念说明
节点状态
- Leader 主节点:接受Client更新请求,写入本地后同步至其他副本
- Follower 从节点:从Leader中接受更新请求,写入本地日志文件。对客户端提供读请求
- Candidate 候选节点:如果follower节点一段时间内没有收到Leader心跳,就会变成Candidate节点,进入选举阶段直至选出新的Leader节点 Candidate状态才结束。
TermId 任期号
- 时间被划分为一个个任期,每次选举后都会产生一个新的termId,一个任期内只有一个Leader
RequestVote 请求投票
- candidate状态节点在选举过程中发起,收到多数派响应后称为Leader
两个超时时间
- Follower节点超时时间 election timeout ,对每个节点来说这个时间是随机的一般在150~300ms
4.3 Leader 竞选流程
可参考的完整动画,动画非常清晰:http://thesecretlivesofdata.com/raft/
可参考github的动画 https://raft.github.io/
- 某个Flower状态节点在election timeout 时间内未收到来自Leader节点的心跳。这种情况可能是服务刚启动,还没有Leader节点,也有可能是Leader节点掉线了。
- Flower 节点进入 Candidate 候选状态,此时生成一个新的 TermId 并且先算上自己的一票
- Candidate 状态的节点向其他节点发起投票 RequestVote
- 收到投票请求的其他节点,如果在这个TermId任期号中还没有投票,那么就会将票投给该Candidate节点
- 当Candidate节点收到的票数超过半数,它就成为了新的Leader节点
- 称为Leader节点后,会给其他的Follower节点发送心跳包,Follower节点每次收到心跳包,就会重置他们的election timeout 计时。
4.4 Leader节点接受请求流程
这是通过使用与用于心跳的相同的 AppendEntry 消息来完成的。
修改会在下一次心跳时发送给Follower节点
- 外部请求都由集群的Leader节点处理
- Leader节点每收到一个更改就写入Leader节点的日志
- Leader 节点写入日志后并未正式提交数据的修改,因为要提交修改必须要在复制给所有Follower节点之后才可以。
- Leader节点将修改复制到Flower节点
- Leader节点等待收到大多数Follower节点反馈写入完成
- Leader 提交修改,并且通知其他的Follower节点,修改已提交。
- Leader 节点返回Client操作结果
- 这个过程称之为 日志复制
4.5 Leader节点宕机重选举流程
- Leader节点突然下线
- 此时最先超时的Follower节点进入Candidate状态,开始重新选举
- 重走选举流程,选出新的Leader节点
4.6 多个Candidate竞选
- 如过多个Follower节点同时超时进入Candidate状态
- 并且发起投票后收到了相同的票数,那么系统会开始等待超时重新投票
- 由于每个节点的超时时间不一样,所以出现多个Candidate的概率非常小
4.7 出现网络分区的一致性流程
- 出现网络分区后,在多个分区可能都会出现对应的Leader节点
- 如果某个分区的Leader收到了客户端的更新条目,因为他无法将更新复制给大多数的节点,所以修改一致处于未提交状态。
- 如果某个分区的Leader收到了客户端更新条目,并且可以复制给大多数节点,那么修改会被正常提交。
- 如果网络分区消失,任期较小的leader将下台,并且回滚未提交的修改。会匹配随较大任期的Leader的日志数据记录
- 也就是说raft在发生网络分区的时候,是没有办法在半数以下的节点的网络分区中进行更改的
五、Lease机制
5.1 什么是Lease机制
Lease(租约) 机制是一种在分布式系统常用的协议,是维护分布式系统数据一致性的一种常用工具。
Lease机制有以下几个特点
- Lease是颁发者对一段时间内数据一致性的承诺
- 颁发者发出Lease后,不管是否被接收,只要Lease租期内,颁发者都会按照协议遵守承诺
- Lease的持有者只能在Lease有效期内使用承诺,一旦Lease超时,持有者需要放弃执行重新申请Leasedddd
5.2 Lease机制使用场景
分布式系统中,主节点网络波动,导致从节点无法正常收到,可能发生重新选举造成同时存在多个主节点的场景。
该场景解决方式有如下几种
- 设计容忍双主节点的分布式协议
- 使用Raft协议,根据TermId的高低,低版本跟随高版本同步。
- 使用lease机制,租期到期前无法重新选举
- 使用去中心化的 Gossip 协议
5.3 Lease工作流程
- 引入中心节点负责下发Lease
- 假设 主节点 node1 租期从 01:00~01:10
- 01:00~01:10 期间node节点网络出现问题
- 其他子节点开始尝试重新选举主节点,并尝试向中心节点申请租期
- 中心节点拒绝下发周期,因为当前你时间段已经对 node1 下发 Lease
- 如果网络恢复 node1继续发送心跳,仍然是主节点
- 在01:10后 Lease到期,主节点node1继续申请续期操作,中心节点会下发新的Lease。此时如果node1主节点宕机,重新选举出来的主节点向中心节点申请Lease则可以申请成功,称为新的主节点。
5.4 Lease机制的容错
- 主节点宕机 Lease机制可以容忍网络、Lease接收方的出错
- 中心节点异常 颁发者宕机可能会导致系统不可用,可以使用中心节点集群,避免单点失效问题。
- 时差问题 中心节点和主节点时钟可能存在误差,需要中心节点考虑时钟误差。
- lease时长 一般1~10秒,太短的话网络压力大,太长则收回时间过长,影响可用性。
5.5 Lease机制的应用
- 谷歌文件系统 GFS中,Master通过Lease机制,决定哪个是主副本,lease在给个节点的心跳响应消息中歇尔代。收不到心跳时,等待lease过期后再颁发给其他节点。
- 谷歌分布式文件系统 chubby 中 paxos选主后,从节点会给主节点颁发Lease,期限内不选其他节点为主。另一方面主节点给每个client发送Lease用于判断client的存活性。