Raft协议简述

Raft 是一种为了管理复制日志的一致性算法,该算法强依赖 Leader 节点的可用性来确保集群数据的一致性,即如果client向leader发起添加日志请求,如果leader回复client提交成功,那么该日志一定被过半数的server所提交,且是确定的不会被其他日志覆盖。

算法包含2类成员,server和client:

  • server:接受client的写日志请求,该类成员包含3种角色:
    • follower:跟随者,server集群首次启动时都是follower。
    • candidate:候选人,在follower的选举时间超时后会变为candidate。
    • leader:领导者,当server成为candidate后并发起选举投票请求收到过半数server的投票后会变为leader。
  • client:负责发起附加日志请求到server

算法包含两个过程:leader选举和日志复制:

1.leader选举

  • 该过程发生在server集群启动或leader宕机时,server最初都是follower,每个follower都维持一个选举超时时间,当选举超时时间到达后,follower会自动晋升为candidate,并发起投票请求给其他server,如果收到过半数server的投票同意响应,则晋升为leader,然后定时发送心跳请求给其他server(周期远小于选举超时时间),如果有了新的leader,那么其他server都变为follower,当收到leader的心跳请求后会重置自己的选举超时时间。
  • 每次选举都会产生一个新的递增的任期号。
  • 在server收到投票请求时,只有对方的最新日志比自己的日志新才会回复同意投票响应给对方,日志用任期号和日志索引来比较日志新旧,先比较任期号,再比较索引,任期号是日志从client发送到leader时该leader的任期号。
  • 在一次选举过程中,每个server最多只能投一次票。

2.日志复制

当选出一个leader后,便能够为client提供服务啦,即处理client的写日志请求,所有client的写请求最终都会发送到leader,leader收到client的写日志请求后,会执行如下:

  • 将日志写到本地文件;
  • 将日志复制给其他follower,其他follower收到日志后写到本地文件并响应leader写入成功;
  • 当leader收到follower的响应并且已经把日志复制到过半数的server节点(包括自己)后,commit该日志(把日志刷新到最终要保存的磁盘位置),并通知其他follower commit该日志。注意:只有该日志的任期号跟自己的任期号相同才能commit,上个任期号的日志在当前任期leader不能被直接commit,需要当前任期leader在commit当前任期日志时该日志索引之前的日志才会被自动commit

注意:当server节点宕机后节点数量不会发生变化,即该宕机的server还算做集群的一员,在选举和复制日志过程中还必须考虑其投票和复制日志响应。
日志处于两种状态才是安全的,如下:

  • 第一种状态是被commit的日志,该日志已经占据了日志索引位置,在以后才绝对不会被丢失和覆盖;
  • 第二种状态是该日志被复制到过半数的server,且该日志任期号与当前leader任期号相同;

第一种状态无需解释,针对第二种状态,即使该日志没有被commit,然后leader宕机了,那么没有该日志的server节点不可能选举成为leader,只有包含该日志的server才能被选举为leader,在选举成为leader后在复制日志给其他follower后并且也把自己任期的一条日志复制给过半数server后会commit自己任期的该条日志,那么上一个任期的日志也会被间接commit,注意,raft算法不会单纯的commit上一个任期的日志,只能在commit自己任期的日志时间接commit上一个任期日志。下面简单证明为什么leader把当前任期的日志复制到过半数的follower后相当于日志就是安全的了:

假设有5台server,包含1台leader4台follower,当有2台follower收到日志后该日志是安全的并且可以commit的,假设leader编号为1,任期号为1,收到日志的2台follower编号为2、3,没收到日志的3台follower编号为4、5,如下(表格第一行的1、2表示日志索引位置,日志内容<t,c>,t表示任期号,c表示日志内容):

1 2
server 1(master) <1,x->1>
server 2 <1,x->1>
server 3 <1,x->1>
server 4
server 5

如果这时server 1宕机了,但集群数量还是5(server节点宕机后也算做集群一员),那么只有比5/2+1=3台server(包括自己)的日志新才能选举为leader,所以只有follower 2、3才能成为leader,假设2成为了leader,任期号为2,它会将日志<1,x->1>复制给其他follower,如下:

1 2
server 1 <1,x->1>
server 2(master) <1,x->1>
server 3 <1,x->1>
server 4 <1,x->1>
server 5 <1,x->1>

然后server 2收到client的写日志请求,收到日志y->1,会把该日志复制给其他follower:

1 2
server 1 <1,x->1> <2,y->1>
server 2(master) <1,x->1> <2,y->1>
server 3 <1,x->1> <2,y->1>
server 4 <1,x->1>
server 5 <1,x->1>

如果server 2收到了过半数server的写日志成功响应,假设收到了server 1、3的响应,那么可以commit日志<2,y->1>了,如果通知其他follower commit成功那么之前的日志<1,x->1>也会被间接commit。

也就是说,过半数5/2+1=3,这个数量一定比未收到复制日志<1,x->1>的follower的总和2要大,所以不管有几台server宕机(当然不能超过5/2=2台节点宕机),未收到复制日志<1,x->1>的节点(server 4、5)都不会收到过半数server的投票而选举为leader(因为它一定没有比过半数server的日志新),只有包含那条复制到过半数server的日志<1,x->1>的server节点(server 1、2、3)才能选举成为leader,当其选举为leader后会把该日志<1,x->1>复制给其他follower,最终还是能成功commit该日志。由此可见,只有过半数5/2+1=3的server节点存活才能保证服务可用,如果server 1、2、3全宕机了那服务本身就不可用了,server 4、5不能提供服务不能接收日志写服务,也就不存在日志<1,x->1>被覆盖问题,在server 1、2、3重启之前永远不能提供服务。

下面解释下为什么leader在把上一个任期的日志复制到过半数server后该日志还是不安全的:

假设有5台server,1台leader,4台follower,leader编号为1,任期号位1,假设leader把上一个任期的日志复制给了follower 2,然后宕机了,如下(表格第一行的1、2表示日志索引位置,日志内容<t,c>,t表示任期号,c表示日志内容):

1 2
server 1(master) <1,x->1>
server 2 <1,x->1>
server 3
server 4
server 5

然后server 5通过server 3、4选举成为leader,任期号为2,并把一条新日志复制给了server 4,然后又宕机了如下:

1 2
server 1 <1,x->1>
server 2 <1,x->1>
server 3
server 4 <2,y->1>
server 5(master) <2,y->1>

然后server1通过server2、3选举成为leader,任期号为3,把日志<1,x->1>复制给了server 3,然后又宕机了,如下:

1 2
server 1(master) <1,x->1>
server 2 <1,x->1>
server 3 <1,x->1>
server 4 <2,y->1>
server 5 <2,y->1>

然后server 5又通过server 3、4选举成为leader,任期号为4,它会把日志<2,y->1>复制给其他follower,复制给server 1、2、3时会覆盖在索引位置为2的<1,x->1>日志,因为该日志没有被commit所以可以被覆盖,如下:

1 2
server 1 <2,y->1>
server 2 <2,y->1>
server 3 <2,y->1>
server 4 <2,y->1>
server 5(master) <2,y->1>

这种情况下虽然server 1在成为leader且任期号为3,把日志<1,x->1>复制到了过半数server,即server 1、2、3,该日志最后还是被server 5的<2,y->1>覆盖了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容