分布式基础理论和Raft算法

1.CAP理论

一个分布式系统的强一致性(Consistency)、可用性(Availability)、分区容错性(Partition Tolerance)只能同时满足其中两个。由于分布式系统必须保持分区容错性,即分布式集群系统某个节点挂掉不能导致整个系统不可用,因此基本只在AP和CP中做选择。

CP系统强调强一致性,发生写操作后各节点在数据同步的过程中会导致系统暂时不可用,牺牲可用性。用于数据重要或敏感的系统,如金融等。

AP强调可用性,每个节点快速响应,保证可用性,会导致从不同节点获取的信息不一致。如redis集群,快速返回节点结果后自动与其它节点同步。

2.BASE理论

BA(Basically Available):基本可用,一定程度的非核心系统不可用、请求时间一定程度的延长是允许的。

S(Soft State):分布式系统可以存在一种数据同步中的中间状态。

E(Eventually Consistent):最终一致性,不要求分布式系统数据实时一致,允许在一段时间后达到最终一致,在数据同步的过程中系统也是可用的。

 

3.分布式线性一致性和顺序一致性

线性一致性:分布式系统接受到读请求的时间点,总能读到最近的已提交的日志,并且日志都是按顺序提交的;如raft。

顺序一致性:只能保证日志提交的顺序,并不能保证读到最新的已提交日志,因为leader和follower不是同时commit的;如zab,某一日志leader已提交,但follower由于网络等原因还未提交就会读到旧值。

 

4.raft算法

raft算法属于multi-paxos,做了一些简化和限制,比如:日志必须连续没有空洞;节点只有leader、follower、candidate三种状态;用强领导者模型简单高效完成了分布式状态机复制的各种问题。

raft算法将复杂的分布式共识问题分解为2个rpc请求和3个子问题:

4.1 leader选举

①心跳机制:leader会定期向所有follower发送心跳来维持自己的地位。而follower一定超时时间内未收到leader心跳,则会认为leader宕机,切换为candidate状态,开始选举。

 

②选举过程:follower先将自己的任期term+1,切换到candidate状态并投自己一票,并且并行地向集群中其它节点发送请求投票请求RequestVote Rpc。最终会有3种结果:

1.获得多数节点的选票:成为leader,并开始发送心跳。 

2.收到其它leader的心跳:确认term不小于自己,回到follower状态。

3.没有获得多数选票:随机超时后开启下一轮选举。

 

RequestVote Rpc的请求结构:

①term        int        任期号

②candidateId        int        自己的id

③lastLogIndex        int        自己最新的日志号(包含未提交的日志)

④lastTerm        int        最新日志的任期号

(③④用于安全性子问题。)

 

RequestVote Rpc响应体的结构:

①term        int       投票者任期号

②voteGranted        bool        是否投票

 

4.2日志复制

日志的唯一性由日志号+任期号确定,由于leader和follower都有宕机或缓慢的可能,要保证每个副本顺序一致,有3种可能:

1.follower没有在leader发送AppendEntries Rpc后给出响应:leader会不断重新发送AppendEntries Rpc,即使leader已经将该日志应用到状态机并响应了client。

2.follower崩溃后恢复:由于AppendEntries Rpc包含前一个日志的序号和任期号,follower在本地日志中找不到则拒绝append该日志,leader收到拒绝后会发送之前一个AppendEntries Rpc,包含上上个日志的序号与任期,依次类推直到成功为止。

3.leader宕机:可能有某些未提交日志,部分follower有而新leader没有复制,这种情况会强制follower复制leader的未提交日志覆盖follower的未提交日志,由于未提交所以不违背外部一致性。

 

AppendEntries Rpc的请求结构:

①term        int        leader任期号

②leaderId        int        leader的id

③prevLogIndex        int        前一日志号

④prevLogTerm        int        前一日志任期号

⑤entries        int        日志体

⑥leaderCommit        leader最近已提交的日志号;follower可以提交之前的所有日志

 

AppendEntries Rpc的响应结构:

①term        int       follower任期号

②success        bool        是否接收

 

4.3安全性

要满足日志复制在节点宕机等问题下写入的一致性,还需满足以下限制:

①选举限制:follower会拒绝lastLogIndex和lastTerm小于自己的RequestVote Rpc。这样,只要日志被大多数节点提交,没有提交该日志的节点就无法获得多数选票成为leader。

②之前任期的未提交日志:新leader会复制给所有follower,但永远不会通过计算副本数的方式提交之前任期的日志,而是在当前任期第一条日志被提交时,之前任期的未提交日志全会被提交。no-op优化:新leader当选后,立即发送一条空entries的AppendEntries Rpc,将之前任期的日志提交并保护起来。

③follower和candidate宕机:无限重试,因为两个rpc都是幂等的

④时间与可用性限制:节点间的广播时间需要远小于选举超时时间,平均故障时间要远大于选举超时时间,这样选举才能完成。

 

4.4线性一致性读

readIndex:leader收到读请求的时间点已提交的最新的日志序号,线性一致性读的目标日志序号。

由于可能存在分区问题(脑裂),收到读请求的leader不再是集群的leader,集群新leader有新的已提交日志,为了满足线性一致性,有3种策略:

1.leader把读请求当作写log,在大多数节点达成共识后返回readIndex对应日志,开销较大。

2.在读之前发送心跳并得到大多数节点反馈,确认当前节点仍为leader。比较激进的做法是,在距上次心跳的间隔不超过选举超时时间下界时直接返回readIndex对应日志,但由于分布式系统时钟偏移、Full GC等情况,一般认为不可靠。

3.follower接受读请求不转发leader,向leader请求readIndex,等待自身状态机应用到readIndex后,返回readIndex对应日志。这么做能够多节点并发读,一般收益是大于开销的。当然在很多情况下不需要线性一致性读,为了提高读性能,也可以像zab一样直接读follower,不请求readIndex,满足顺序一致性即可。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值