日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

zookeeper的ZAB协议学习

發(fā)布時(shí)間:2024/2/28 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 zookeeper的ZAB协议学习 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

    • 1. zookeeper的復(fù)制狀態(tài)機(jī)
    • 2. zookeeper的角色
    • 3. zab協(xié)議的階段
    • 4. zookeeper的數(shù)據(jù)模型
      • 1. 在zookeeper每個(gè)服務(wù)節(jié)點(diǎn)的持久化數(shù)據(jù)
      • 2. 內(nèi)存中的狀態(tài)
      • 3. 選舉過程中發(fā)送的信息
    • 5.消息通信機(jī)制
    • 6. zab的幾個(gè)過程
      • 1. leader選舉過程 zabState為ELECTION
      • 2. leader確認(rèn)階段
      • 3. leader的數(shù)據(jù)同步階段
      • 4. 原子播報(bào)階段,這個(gè)時(shí)候使用的是二階段提交模式
    • 7. 小結(jié)
      • 1. 線性一致性讀
      • 2. 與client的線性一致性保持
    • 部分源碼,附
    • 腦圖,幫助理解
    • 部分參考鏈接

??看完raft的論文,再來看zookeeper關(guān)于ZAB協(xié)議的介紹,感覺raft寫的真是好,zookeeper我能夠搜索到的論文實(shí)際上都只是講了一個(gè)大概,感覺 這一篇還算是稍微講了一些東西,但是還是很不全面。迫不得已看了一下源碼,只看了leader選舉部分的實(shí)現(xiàn) FastLeaderElection,以及l(fā)eader選舉相關(guān)的工作,其實(shí)zookeeper的項(xiàng)目對(duì)于java開發(fā)人員還是很友好的,直接 git clone下來,在本地看的很爽。

下面嘗試按照raft論文的方式來對(duì)zab協(xié)議進(jìn)行闡述

1. zookeeper的復(fù)制狀態(tài)機(jī)

zk的數(shù)據(jù)存在內(nèi)存當(dāng)中(高性能),但是同時(shí)記錄操作日志+內(nèi)存快照(二進(jìn)制),持久化(類似于Redis)。
狀態(tài)機(jī)+命令日志:內(nèi)存中保存數(shù)據(jù)的最終狀態(tài),命令日志中保存所有的操作過程,內(nèi)存快照中保存某一時(shí)間節(jié)點(diǎn)的狀態(tài)機(jī)中的數(shù)據(jù)。
所以zk和raft基本一致,也是復(fù)制狀態(tài)機(jī)的工作模式,由日志復(fù)制的線性化來保證系統(tǒng)的線性化。

2. zookeeper的角色

  • LOOKING:進(jìn)入leader選舉狀態(tài)
  • FOLLOWING:leader選舉結(jié)束,進(jìn)入follower狀態(tài)
  • LEADING:leader選舉結(jié)束,進(jìn)入leader狀態(tài)
  • OBSERVING:處于觀察者狀態(tài)
    寫的話寫leader,讀取的話可以通過FOLLOWING,OBSERVING,而且拓展OBSERVING的話可以提供更多讀的能力,但是不會(huì)降低寫入的速度。
  • 3. zab協(xié)議的階段

    ??這個(gè)階段的劃分不同的論文好像有不同的說法,這里先以zookeeper的代碼中的為準(zhǔn)介紹一下,再引述一些其他的方式,在zookeeper的源碼中對(duì)zabState是這樣定義的,有4種狀態(tài)

    ELECTION : leader選舉階段
    DISCOVERY: leader確認(rèn)階段
    SYNCHRONIZATION: 數(shù)據(jù)同步階段
    BROADCAST: 原子播報(bào)階段
    也有一些文章前面三個(gè)階段合起來稱為崩潰恢復(fù)階段,這種也是可以的,這種情況下zab協(xié)議就被描述為奔潰恢復(fù)和原子播報(bào)兩個(gè)階段。

    4. zookeeper的數(shù)據(jù)模型

    1. 在zookeeper每個(gè)服務(wù)節(jié)點(diǎn)的持久化數(shù)據(jù)

    這一塊兒介紹的可能不是很全,主要關(guān)注了和選舉相關(guān)的一些數(shù)據(jù)

    字段含義
    logs[]:日志
    zxid :最后的log的zxid,這個(gè)zxid是一個(gè)64位的數(shù)字,高32位被稱為epoch,類似raft日志中的term, 低32位是遞增的counter類似于raft中的index,但是這里的counter不是全局遞增的,每次leader選舉出來之后,counter會(huì)被初始化為0,但是zxid還是全局遞增的。所以日志是全局有效的。
    epoch:zxid的高32位,會(huì)單獨(dú)持久化
    lastCommited最新的commited的zxid

    2. 內(nèi)存中的狀態(tài)

    字段含義
    logicalclock :這個(gè)是選舉專用的邏輯時(shí)鐘,在服務(wù)啟動(dòng)后第一次選舉開始的時(shí)候會(huì)初始化一個(gè)FastLeaderElection實(shí)例,logicalclock是他的一個(gè)屬性,會(huì)被初始化為0;后期有可能因?yàn)橐恍┊惓T蛑亟ㄟ@個(gè)實(shí)例,默認(rèn)情況下服務(wù)不重啟,這個(gè)logicalclock會(huì)是遞增的狀態(tài),而且在zookeeper的代碼中,有些地方把這個(gè)也叫epoch或electEpoch,頗具迷惑性
    proposedLeader:當(dāng)前節(jié)點(diǎn)認(rèn)為的應(yīng)該做leader的server id,根據(jù)當(dāng)前節(jié)點(diǎn)收到的廣播消息會(huì)動(dòng)態(tài)變化,選舉剛開始的時(shí)候初始化為當(dāng)前節(jié)點(diǎn)的sid
    proposedZxid:對(duì)應(yīng)的應(yīng)該做leader的server的zxid,根據(jù)當(dāng)前節(jié)點(diǎn)收到的廣播消息會(huì)動(dòng)態(tài)變化,選舉剛開始的時(shí)候初始化為當(dāng)前節(jié)點(diǎn)的zxid
    proposedEpoch:對(duì)應(yīng)的應(yīng)該做leader的server的epoch,這個(gè)epoch是zxid中的epoch,但是不一定相等,因?yàn)樾碌膃poch生成了,但是包含這個(gè)epoch的zxid可能還沒有生成,,根據(jù)當(dāng)前節(jié)點(diǎn)收到的廣播消息會(huì)動(dòng)態(tài)變化,選舉剛開始的時(shí)候初始化為當(dāng)前節(jié)點(diǎn)的epoch
    state每個(gè)節(jié)點(diǎn)處于的角色狀態(tài),可能是LOOKING,FOLLOWING,LEADING,OBSERVING,會(huì)隨著選舉過程逐漸變化,在節(jié)點(diǎn)啟動(dòng)或者當(dāng)前節(jié)點(diǎn)要發(fā)起leader選舉的時(shí)候是LOOKING,leader選出來后是后面三種的一種
    zabState每個(gè)節(jié)點(diǎn)處于的zab協(xié)議的階段,可能是ELECTION,DISCOVERY,SYNCHRONIZATION,BROADCAST,在節(jié)點(diǎn)啟動(dòng)或者leader選舉開始的時(shí)候初始化為ELECTION,選舉完成后epoch的確認(rèn)階段為DISCOVERY,數(shù)據(jù)同步階段為SYNCHRONIZATION,數(shù)據(jù)同步完成之后是原子播報(bào)階段,對(duì)應(yīng)的則是BROADCAST
    Map<Long, Vote> recvset:用來收集looking狀態(tài)下的大家的選票信息,key是投票者的server id, Vote是對(duì)應(yīng)的server投出的票,這個(gè)map數(shù)據(jù)結(jié)構(gòu)是當(dāng)前server用來記錄同樣處于LOOKING狀態(tài)的server發(fā)出來的投票信息,如果這個(gè)達(dá)到了多數(shù)一致,那么久認(rèn)為leader選出來了。
    Map<Long, Vote> outofelection :這個(gè)對(duì)應(yīng)收集的是leader或者是follower或者leader發(fā)出來的信息,這個(gè)也是按照多數(shù)生效(也就是超過半數(shù)的leader+follower信息發(fā)過來才認(rèn)為真正找到了leader,感覺這個(gè)還是比較嚴(yán)格的),同時(shí)還會(huì)要求必須有l(wèi)eader廣播的信息認(rèn)為自己是leader.

    上面字段中的proposedLeader,proposedZxid,proposedEpoch,logicalclock是創(chuàng)建本地廣播的選票信息的主要來源(new Vote對(duì)象的時(shí)候使用到這些變量),所以我們?yōu)榱讼旅婷枋銎饋砀臃奖?#xff0c;將這些變量稱為本地選票信息。

    vote的信息

    字段含義
    leader投票認(rèn)為的leader的server id
    zxid認(rèn)為的leader的zxid
    electionEpoch選舉的邏輯時(shí)鐘logicalclock
    state投票者的server state ,一般是LOOKING
    configData集群的服務(wù)器配置,用來驗(yàn)證quorum,這個(gè)字段應(yīng)該是包含了當(dāng)前集群有哪些節(jié)點(diǎn)
    peerEpoch被認(rèn)為是leader的節(jié)點(diǎn)的epoch

    vote的信息是一個(gè)選票的信息,就是下面廣播的投票信息是一致的

    3. 選舉過程中發(fā)送的信息

    字段含義
    leader投票認(rèn)為的leader的server id
    zxid認(rèn)為的leader的zxid
    electionEpoch選舉的邏輯時(shí)鐘logicalclock
    state投票者的server state ,一般是LOOKING
    configData集群的服務(wù)器配置,用來驗(yàn)證quorum,這個(gè)字段應(yīng)該是包含了當(dāng)前集群有哪些節(jié)點(diǎn)
    peerEpoch被認(rèn)為是leader的節(jié)點(diǎn)的epoch

    5.消息通信機(jī)制

    在正式了解zookeeper的zab工作模式以前有必要先簡單介紹一下zookeeper的通信方式,更加有助于理解。

  • 在zookeeper中,服務(wù)器中的連接是兩兩互聯(lián),構(gòu)成網(wǎng)狀狀態(tài),server與server之間直接使用的socket的長連接(俗稱BIO),每兩個(gè)server之間只會(huì)建立一個(gè)連接,sid大的去主動(dòng)連接sid小的。
  • 消息的發(fā)送不像http模式下一個(gè)請(qǐng)求過來之后要返回一個(gè)相應(yīng)那樣一一對(duì)應(yīng)。因?yàn)閠cp是全雙工的,流式的,所以這里請(qǐng)求和相應(yīng)是獨(dú)立的,也就是可能連續(xù)發(fā)了5條消息,后面又收到其中3個(gè)消息的答復(fù),這種哪條消息是請(qǐng)求,哪條消息是答復(fù),需要通過消息的類型進(jìn)行識(shí)別,消息之間的配對(duì)(a是b的答復(fù))也需要通過消息號(hào)等匹配起來。
  • 同樣的,zookeeper是使用tcp長連接來保證接收方接收到的消息的順序是和發(fā)送方發(fā)送消息的順序是一致的,這個(gè)也是實(shí)現(xiàn)數(shù)據(jù)全局有序的重要保證
  • 6. zab的幾個(gè)過程

    1. leader選舉過程 zabState為ELECTION

    下面的代碼部分都在FastLeaderElection,方法lookForLeader()作為入口

  • 選舉開始之后,每個(gè)server都會(huì)初始化內(nèi)存中的狀態(tài)部分中的proposedLeader(使用當(dāng)前節(jié)點(diǎn)的sid),proposedZxid(使用當(dāng)前節(jié)點(diǎn)的zxid),proposedEpoch(使用當(dāng)前節(jié)點(diǎn)的epoch),state(為LOOKING),zabState(為ELECTION) 作為當(dāng)前節(jié)點(diǎn)的本地選票信息,然后廣播出去一個(gè)投票信息,廣播的信息的格式就是上面的選舉過程中發(fā)送的信息,leader字段使用的是proposedLeader,zxid是proposedZxid,peerEpoch 是proposedEpoch (注意著三個(gè)信息因?yàn)樽铋_始初始化的時(shí)候是本機(jī)的信息,所以這里廣播出去的也是本機(jī)的信息,但是隨著選舉過程的推進(jìn),后面可能就不是本機(jī)的信息了,但是后面介紹的其他幾個(gè)字段都還是本機(jī)的信息) electionEpoch是當(dāng)前機(jī)器的logicalclock,state是當(dāng)前節(jié)點(diǎn)的state,configData是當(dāng)前節(jié)點(diǎn)的config,等不再贅述,可以直接參考上面的表格。
  • 然后如果當(dāng)前是looking狀態(tài)的話就會(huì)等待和收取廣播消息(可能是自己發(fā)出去的,也可能是別人發(fā)出去的)假設(shè)收取的廣播消息為n,
  • 如果是自己的,就直接記錄到recvset當(dāng)中,key是當(dāng)前的sid,

  • 如果是別人的,而且n.state是LOOKING,先比較選舉邏輯時(shí)鐘electionEpoch

  • 如果廣播消息中的邏輯時(shí)鐘和當(dāng)前節(jié)點(diǎn)的logicalclock一樣大小,則比較n的選票信息和當(dāng)前節(jié)點(diǎn)的本地選票信息比較(主要就是當(dāng)前節(jié)點(diǎn)的proposedLeader,proposedZxid,proposedEpoch),比較的規(guī)則參看下面的選票信息比較規(guī)則
  • 如果選票n勝出,則修改本地的選票信息,主要就是當(dāng)前節(jié)點(diǎn)的proposedLeader,proposedZxid,proposedEpoch
  • 如果n沒有本地選票信息新,則不作更新
  • 將選票n放入recvset當(dāng)中,key為n.sid,對(duì)應(yīng)消息的發(fā)送方sid
  • 廣播本地選票信息(可能會(huì)重復(fù)發(fā)送,不影響)
  • 如果本地邏輯時(shí)鐘落后,則直接把本地之前收到的選票全部作廢(清空recvset),重置當(dāng)前節(jié)點(diǎn)的logicalclock為消息中的electionEpoch,然后進(jìn)行選票信息比對(duì),注意這里收到的選票信息不是和本地選票信息比較(因?yàn)閜roposedLeader,proposedZxid,proposedEpoch在對(duì)應(yīng)的之前的electionEpoch中可能已經(jīng)被改變過了),而是和本機(jī)的sid,zxid,epoch信息比較
  • 如果選票n勝出,則修改本地的選票信息為n中對(duì)響應(yīng)的信息,主要就是當(dāng)前節(jié)點(diǎn)的proposedLeader,proposedZxid,proposedEpoch
  • 如果n沒有本地選票信息新,則更新本地選票信息為本機(jī)信息(和選舉剛開始時(shí)候的初始化信息是一致的)
  • 將選票n放入recvset當(dāng)中,key為n.sid,對(duì)應(yīng)消息的發(fā)送方sid
  • 廣播本地選票信息(可能會(huì)重復(fù)發(fā)送,不影響)
  • 如果n中的邏輯時(shí)鐘electionEpoch小于當(dāng)前節(jié)點(diǎn)的logicalclock,則忽略這個(gè)選票信息
  • 查看recvset中的信息是否對(duì)本地選票中的proposedLeader達(dá)成了多數(shù)一致
  • 如果未達(dá)成則進(jìn)入大步驟中的2,繼續(xù)處理收到的廣播消息
  • 如果達(dá)成多數(shù)贊成proposedLeader,則會(huì)繼續(xù)輪詢接收消息的隊(duì)列看看有沒有優(yōu)先級(jí)更高的選票(這里的優(yōu)先級(jí)更高的就是使用下面的選票信息比較規(guī)則最后勝出)
  • 如果在處理隊(duì)列中的消息發(fā)現(xiàn)有優(yōu)先級(jí)更高的消息,則會(huì)把這個(gè)消息再放回到接收消息的隊(duì)列中,跳到大步驟中的2,繼續(xù)處理收到的廣播消息,選出更加合適的leader
  • 如果接收消息的隊(duì)列已經(jīng)空了,且沒有優(yōu)先級(jí)更高的選票,則會(huì)等待200ms
  • 有優(yōu)先級(jí)更高的消息的話,同3.2.1,跳到下一輪大循環(huán)
  • 有消息,優(yōu)先級(jí)不高,同3.2.2,繼續(xù)消費(fèi)隊(duì)列
  • 還是沒有消息,可以認(rèn)為這次選舉結(jié)束了,將當(dāng)前server的state設(shè)置為leading,following,observing三個(gè)狀態(tài)中的一個(gè),同時(shí)清空接收消息的隊(duì)列
  • 如果是別人的,而且n.state是OBSERVING,接著進(jìn)入步驟2,不以O(shè)BSERVING的消息為準(zhǔn),因?yàn)樗麤]有選舉權(quán)限

  • 如果是別人的,而且n.state是FOLLOWING,LEADING,這個(gè)時(shí)候

  • 判斷n和本地是否處于用一個(gè)選舉周期中n.electionEpoch == logicalclock.get(),如果在一個(gè)選舉周期中則放入recvset,并查看recvset中的信息是否對(duì)n選票中的n.leader達(dá)成了多數(shù)一致,如果達(dá)成了并且leader的選票也認(rèn)為自己是leader,那么就結(jié)束選舉,這種情況應(yīng)該是本次選舉基本可以認(rèn)為結(jié)束了,但是當(dāng)前節(jié)點(diǎn)收到的消息比較滯后的情況,這個(gè)時(shí)候可能會(huì)受到leader和其他follower的信息,這個(gè)時(shí)候還是按照原來的規(guī)則計(jì)算即可
  • 如果上一步?jīng)]有計(jì)算出來leader放入另一個(gè)計(jì)票容器outofelection當(dāng)中,這一步?jīng)]有要求選舉周期是一致的,然后看看outofelection中是否對(duì)n.leader達(dá)到了多數(shù)一致性,如果達(dá)成了也會(huì)結(jié)束選舉,這個(gè)應(yīng)該應(yīng)用的場(chǎng)景就是類似某個(gè)follower和leader失去聯(lián)系了,然后發(fā)起選舉,結(jié)果收到了其他人都告訴他leader存在的消息(這個(gè)時(shí)候消息的選舉周期和當(dāng)前節(jié)點(diǎn)肯定不一致),然后,當(dāng)前節(jié)點(diǎn)就會(huì)接受當(dāng)前l(fā)eader存在的事實(shí),防止頻繁進(jìn)行選舉過程。
  • 選票信息比較規(guī)則

    1.誰的peerEpoch高誰誰勝利
    2.如果peerEpoch相等,則誰的zxid更大誰勝出
    3.如果peerEpoch,zxid都相等,那么誰的sid大誰勝出
    4.這里補(bǔ)充一個(gè)疑惑點(diǎn),為什么還要先比較peerEpoch,直接比較zxid不就行了么,因?yàn)閦xid不是包含了epoch的信息么,肯能是因?yàn)槟硞€(gè)節(jié)點(diǎn)當(dāng)選了master然后很快超時(shí)了重新選舉了?有待后續(xù)探索

    2. leader確認(rèn)階段

    ??zabState為DISCOVERY,對(duì)應(yīng)代碼在QuorumPeer的run()方法之中,這里針對(duì)不用角色的節(jié)點(diǎn)leading,following,observing,都會(huì)有DISCOVERY階段。
    ??這個(gè)階段就是leader會(huì)生成新的epoch(從各個(gè)follower收集到的最大的epoch+1),并使用(epoch,0)組合生成zxid,把自己的zxid封裝成Leader.LEADERINFO包發(fā)送給發(fā)送給follower,然后follower確認(rèn)這個(gè)epoch是大于等于自己當(dāng)前看到的epoch的。如果不是就會(huì)拋異常,不承認(rèn)當(dāng)前l(fā)eader(理論上不應(yīng)該發(fā)生),如果接受了就會(huì)更新當(dāng)前服務(wù)器的epoch,封裝成Leader.LEADERINFO包發(fā)送給leader,在leader收到過半的follower的ack消息之后就說明大家都承認(rèn)他是leader了,后面就可以開始數(shù)據(jù)同步工作了。
    這里的epoch一般是和zxid中的一致的,因?yàn)閒ollower的都是從master的消息當(dāng)中得到的。

    3. leader的數(shù)據(jù)同步階段

    ??在過半follower回復(fù)了ack消息之后,leader就可以開始數(shù)據(jù)同步工作了,數(shù)據(jù)同步的時(shí)候是采用強(qiáng)leader的方式,也就是大家的數(shù)據(jù)都要和leader的對(duì)齊,這時(shí)zabState為SYNCHRONIZATION

  • 如果follower的zxid比leader的小則leader會(huì)發(fā)送后面的數(shù)據(jù)給對(duì)應(yīng)的follower(也是使用兩階段提交的方式),在發(fā)送完后會(huì)發(fā)送一個(gè)Leader.NEWLEADER數(shù)據(jù)包,follower在同步完成后發(fā)送響應(yīng)的ack消息
  • 如果follower的數(shù)據(jù)zxid比leader的大,則對(duì)應(yīng)的數(shù)據(jù)都會(huì)被刪除,完成后也要發(fā)送ack消息
    在leader收到過半的follower的ack消息之后就認(rèn)為數(shù)據(jù)同步完成了,后面就可以進(jìn)入原子播報(bào)階段了
  • 4. 原子播報(bào)階段,這個(gè)時(shí)候使用的是二階段提交模式

    zabState為 BROADCAST

  • 對(duì)于每一個(gè)事務(wù)請(qǐng)求過來的時(shí)候,都要由leader進(jìn)行FIFO處理,假如是follower或者observer接收到了這個(gè)請(qǐng)求,那么會(huì)把這個(gè)請(qǐng)求轉(zhuǎn)發(fā)給leader
  • leader接收到事務(wù)請(qǐng)求后,會(huì)先生成一個(gè)zxid(epoch+有序遞增的事務(wù)id),然后將該事務(wù)存儲(chǔ)到本地日志,
  • 接著將這個(gè)事務(wù)廣播所有的follower進(jìn)行事務(wù)日志存儲(chǔ),
  • follower 在接收到leader事務(wù)請(qǐng)求時(shí),要么選擇執(zhí)行該事務(wù),要么選擇拋棄leader,重新發(fā)起leader選舉(但是會(huì)變成無效,直到他重新認(rèn)領(lǐng)原來的leader,又會(huì)通過同步的方式進(jìn)行數(shù)據(jù)同步)
  • 等待過半的follower都回應(yīng)ack表示可以存儲(chǔ)之后,再發(fā)送一個(gè)commit信息給所有的follower進(jìn)行提交(更新lastcommited并應(yīng)用log到狀態(tài)機(jī)當(dāng)中),然后本地也進(jìn)行一個(gè)提交(更新lastcommited并應(yīng)用log到狀態(tài)機(jī)當(dāng)中),之后返回給客戶端成功。
  • ??zk的leader處理事務(wù)時(shí)FIFO機(jī)制保持了數(shù)據(jù)的一致性,這個(gè)可以保證leader上的順序性,同時(shí),leader在給follower的信息傳遞中也通過tcp的有序機(jī)制保證了follower每臺(tái)節(jié)點(diǎn)上的日志的順序一致性。所以日志可以保持全局有序性,這個(gè)和raft是一致的。

    7. 小結(jié)

    1. 線性一致性讀

    zk的寫是具備線性一致性的,但是讀的話要分兩種情況,如果是普通的read,則不滿足線性一致性,因?yàn)樽x取沒有走zab的流程,這個(gè)時(shí)候這個(gè)請(qǐng)求可能到了某個(gè)follower,而該follower還沒有同步到這個(gè)數(shù)據(jù)的話,可能讀不到最新的數(shù)據(jù),但是這只是zookeeper對(duì)讀的一種優(yōu)化,可以更快響應(yīng),如果對(duì)數(shù)據(jù)的及時(shí)性有非常高的要求的話,那么園長(zookeeper也被稱為動(dòng)物園園長)也提供了線性一致性的讀方式,就是在真正讀取之前調(diào)用一下zk.sync()方法,這個(gè)方法會(huì)獲取當(dāng)前最大的zxid,知道本機(jī)提交這個(gè)zxid才會(huì)返回,也就保證了在這之前執(zhí)行的操作在本機(jī)都是可見的了。

    2. 與client的線性一致性保持

    從leader的選票比較規(guī)則以及多數(shù)投票一致性上可以得出,

  • 肯定不會(huì)丟commit的數(shù)據(jù),應(yīng)為這個(gè)log必然已經(jīng)存在了多個(gè)節(jié)點(diǎn)上
  • 同時(shí),對(duì)于只存在之前l(fā)eader上的數(shù)據(jù),如果leader掛了那么他的只有自己有的數(shù)據(jù)也會(huì)被忽略掉,即使他后來又回來,但是這個(gè)時(shí)候epoch偏低,所以不會(huì)接受他的日志。
  • 但是對(duì)于那種有部分機(jī)器接受到了廣播請(qǐng)求,只是存了log,這個(gè)時(shí)候leader掛了,該數(shù)據(jù)還沒有走到commit階段,這個(gè)時(shí)候如果新的leader恰好有這條數(shù)據(jù),那么從zookeeper來看他是會(huì)保留這一條數(shù)據(jù),在raft協(xié)議中,這樣的數(shù)據(jù)也是會(huì)被保留,但是raft要求client重試請(qǐng)求的時(shí)候也要攜帶請(qǐng)求編號(hào),來確認(rèn)這個(gè)請(qǐng)求是否已經(jīng)做了,而不會(huì)重復(fù)做兩次(比如是創(chuàng)建節(jié)點(diǎn)),zookeeper這塊是如何做的呢,解析zookeeper的log中發(fā)現(xiàn)石油session和cxid,zxid的,這樣的話也就滿足了冪等,可以通過這個(gè)來判斷這個(gè)操作是否已經(jīng)提交了。
  • 事務(wù)日志

    ZooKeeper Transactional Log File with dbid 0 txnlog format version 2 1/20/20 4:29:59 AM UTC session 0x30014da58050000 cxid 0x0 zxid 0x10000000c createSession 300001/20/20 4:30:00 AM UTC session 0x30014da58050000 cxid 0x4 zxid 0x10000000d create '/test_zookeeper/test/item,,v{s{31,s{'djdigest,'CgcA1GMivoBYyZZWuQDgeLuz5L45jmuVDyLKi2J0swQ=:MEonRpvlUHyT9yHsCnPddPJ0QVCMGVM5ylIV0Zv/VaY=}}},F,21/20/20 4:30:00 AM UTC session 0x30014da58050000 cxid 0x5 zxid 0x10000000e delete '/test_zookeeper/test/item1/20/20 4:30:00 AM UTC session 0x30014da58050000 cxid 0x6 zxid 0x10000000f setACL '/,v{s{31,s{'djdigest,'T9ihPbFmp0odTgrtigbbYJgBkC5Pe6XkWO543Hl1+jc=:dk8WmGqk2QsbWdyxv98BRJWaiW3xEGxpvbzVVx8z8ig=}}},21/20/20 4:30:00 AM UTC session 0x30014da58050000 cxid 0x8 zxid 0x100000010 setACL '/zookeeper,v{s{31,s{'djdigest,'V4AoltP7EqnmD6tlXT9D+yzozXnf2aN/FTmYOVekewQ=:vvEn1n8041x6LDHUgnGC/+tAAwKpFePtXZAdWP4hY3Y=}}},2

    部分源碼,附

    /*** Messages that a peer wants to send to other peers.* These messages can be both Notifications and Acks* of reception of notification.*/public static class ToSend {/** Proposed leader in the case of notification*/ long leader;/** id contains the tag for acks, and zxid for notifications*/ long zxid;/** Epoch*/ long electionEpoch;/** Current state;*/ QuorumPeer.ServerState state;/** Address of recipient,這里是接收端的server id,實(shí)際上這個(gè)字段的信息并不會(huì)發(fā)出去*/ long sid;/** Used to send a QuorumVerifier (configuration info)*/ byte[] configData = dummyData;/** Leader epoch*/ long peerEpoch;} public class Vote {private final int version;private final long id; //leader的idprivate final long zxid; // leader的zxidprivate final long electionEpoch; // leader的邏輯時(shí)鐘logicalclockprivate final long peerEpoch; //leader的epoch}

    zxid的初始化

    這個(gè)方法會(huì)找到當(dāng)前收到的最大epoch然后執(zhí)行+1操作得到當(dāng)前的epoch long epoch = getEpochToPropose(self.getId(), self.getAcceptedEpoch()); zk.setZxid(ZxidUtils.makeZxid(epoch, 0));

    epoch和clock是不是一個(gè),東西,每個(gè)選票的信息有

    每一個(gè)投票者會(huì)維護(hù)一個(gè)

    Map<Long, Vote> recvset = new HashMap<Long, Vote>();

    用來記錄自己收到的投票信息
    map的key是server id,也就可以收集當(dāng)前選舉輪次中每個(gè)server的投票信息

    vote的數(shù)據(jù)結(jié)構(gòu)是期望leader的id,期望leader的zxid,期望leader的投票周期(邏輯時(shí)鐘),期望leader的zxid中的epoch部分

    recvset.put(n.sid, new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch));

    找到和當(dāng)前認(rèn)為的leader是一致的vote

    voteSet = getVoteTracker(recvset, new Vote(proposedLeader, proposedZxid, logicalclock.get(), proposedEpoch));

    腦圖,幫助理解

    部分參考鏈接

    https://www.jianshu.com/p/90e00da6d780

    https://zhouj000.github.io/2019/02/11/zookeeper-03/

    https://www.cnblogs.com/leesf456/p/6140503.html

    總結(jié)

    以上是生活随笔為你收集整理的zookeeper的ZAB协议学习的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。