<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ZooKeeper的選舉機(jī)制和同步機(jī)制超詳細(xì)講解,面試經(jīng)常問(wèn)到!

          共 4629字,需瀏覽 10分鐘

           ·

          2021-10-13 04:38

          前言

          zookeeper相信大家都不陌生,很多分布式中間件都利用zk來(lái)提供分布式一致性協(xié)調(diào)的特性。dubbo官方推薦使用zk作為注冊(cè)中心,zk也是hadoop和Hbase的重要組件。其他知名的開(kāi)源中間件中也都出現(xiàn)了zk的身影。

          有很多童鞋認(rèn)識(shí)zk很久了,知道其基本理念,知道如何使用。但當(dāng)面試時(shí)問(wèn)到集群zk之間的選舉和數(shù)據(jù)同步機(jī)制時(shí),就陷入了盲區(qū)。

          其實(shí)很多的分布式中間件的選舉和同步,都和zk有異曲同工之妙。這篇文章我就來(lái)重點(diǎn)聊下關(guān)于zk集群之間的選舉和同步機(jī)制。

          ZK集群的部署

          首先我們來(lái)看下半數(shù)運(yùn)行機(jī)制:

          集群至少需要三臺(tái)服務(wù)器,且官方文檔強(qiáng)烈建議使用奇數(shù)個(gè)服務(wù)器,因?yàn)閦ookeeper是通過(guò)判斷大多數(shù)節(jié)點(diǎn)的的存活來(lái)判斷整個(gè)服務(wù)集群是否可用的,比如3個(gè)節(jié)點(diǎn),它的一半是1.5,向上取整就是2。掛掉了2個(gè)就是表示整個(gè)集群掛掉。而用偶數(shù)4個(gè)的話,掛掉2個(gè)也表示不是大部分存活,因此也會(huì)掛掉。所以用4臺(tái)服務(wù)器的話 ,從使用資源上來(lái)說(shuō),并不劃算。

          配置語(yǔ)法:

          server.<節(jié)點(diǎn)ID>=:<數(shù)據(jù)同步端口>:<選舉端口>
          • 節(jié)點(diǎn)ID:為1到125之間的數(shù)字,寫(xiě)到對(duì)應(yīng)服務(wù)節(jié)點(diǎn)的{dataDir}/myid文件中。
          • IP地址:節(jié)點(diǎn)的遠(yuǎn)程IP地址,可以相同,生產(chǎn)環(huán)境建議用不同的機(jī)器,否則無(wú)法達(dá)到容錯(cuò)的目的。
          • 數(shù)據(jù)同步端口:主從同步時(shí)數(shù)據(jù)復(fù)制端口。
          • 選舉端口:主從節(jié)點(diǎn)選舉端口。

          假設(shè)現(xiàn)在有3個(gè)zookeeper節(jié)點(diǎn),我們要為其編寫(xiě)config配置,也要編寫(xiě)3份,分別放在不同的服務(wù)器上,其配置如下:

          initLimit=10
          syncLimit=5
          dataDir=/data/zk_data
          clientPort=2181
          # 集群配置
          server.1=192.168.1.1:2888:3888
          server.2=192.168.1.2:2888:3888
          server.3=192.168.1.3:2888:3888

          其中dataDir參數(shù)指定的是一個(gè)目錄,用來(lái)存放zk的數(shù)據(jù),里面有個(gè)文件myid,3臺(tái)機(jī)器上myid文件里面分別存放1,2,3。對(duì)應(yīng)各自節(jié)點(diǎn)ID。

          配置好3個(gè)配置文件后,分別啟動(dòng),這樣我們一個(gè)3個(gè)節(jié)點(diǎn)的集群zookeeper就搭建好了。

          ./bin/zkServer.sh?start?conf/zoo.cfg

          ZK集群中的角色

          zookeeper集群中公共有三種角色,分別是leaderfollowerobserver

          角色描述
          leader主節(jié)點(diǎn),又名領(lǐng)導(dǎo)者。用于寫(xiě)入數(shù)據(jù),通過(guò)選舉產(chǎn)生,如果宕機(jī)將會(huì)選舉新的主節(jié)點(diǎn)。
          follower子節(jié)點(diǎn),又名追隨者。用于實(shí)現(xiàn)數(shù)據(jù)的讀取。同時(shí)他也是主節(jié)點(diǎn)的備選節(jié)點(diǎn),并擁有投票權(quán)。
          observer次級(jí)子節(jié)點(diǎn),又名觀察者。用于讀取數(shù)據(jù),與follower區(qū)別在于沒(méi)有投票權(quán),不能被選為主節(jié)點(diǎn)。并且在計(jì)算集群可用狀態(tài)時(shí)不會(huì)將observer計(jì)算入內(nèi)。

          關(guān)于observer的配置:

          只要在集群配置中加上observer后綴即可,示例如下:

          server.3=127.0.0.1:2883:3883:observer

          其中l(wèi)eader只有一個(gè),剩下的都是follower和observer,但是我們一般生產(chǎn)上不會(huì)配置observer,因?yàn)閛bserver并沒(méi)有選舉權(quán),可以理解為observer是一個(gè)臨時(shí)工,不是正式員工,沒(méi)法獲得晉升。除此之外,它和follower的功能是一樣的。

          什么時(shí)候需要用到observer呢,因?yàn)閦k一般讀的請(qǐng)求會(huì)大于寫(xiě)。當(dāng)整個(gè)集群壓力過(guò)大時(shí),我們可以增加幾個(gè)臨時(shí)工observer來(lái)獲得性能的提升。在不需要的時(shí)候的時(shí)候,可以隨時(shí)撤掉observer。

          zk進(jìn)行連接時(shí),一般我們都會(huì)把zk所有的節(jié)點(diǎn)都配置上去,用逗號(hào)分隔。其實(shí)連接集群中的任意一個(gè)或者多個(gè)都是可以的。只是如果只連一個(gè)節(jié)點(diǎn),當(dāng)這個(gè)節(jié)點(diǎn)宕機(jī)的時(shí)候,我們就斷開(kāi)了連接。所以還是推薦配置多個(gè)節(jié)點(diǎn)進(jìn)行連接。

          如何查看ZK集群中的角色

          我們可以利用以下命令來(lái)查看zk集群中的角色

          ./bin/zkServer.sh?status?conf/zoo.cfg

          我在自己機(jī)器上搭建了3個(gè)節(jié)點(diǎn)的偽集群(共用一臺(tái)機(jī)器),配置文件分別命名為zoo1.cfg,zoo2.cfg,zoo3.cfg。使用以上命令查看的結(jié)果為:


          可以看到,其中節(jié)點(diǎn)2為leader,其他的為follower。但是如果你按照zoo1.cfg,zoo2.cfg,zoo3.cfg的順序啟動(dòng),無(wú)論你啟動(dòng)多少遍,節(jié)點(diǎn)2總是leader,而這時(shí)如果把節(jié)點(diǎn)2關(guān)掉,進(jìn)行查看角色,發(fā)現(xiàn)節(jié)點(diǎn)3成了leader。


          以上這些現(xiàn)象都和zookeeper的選舉機(jī)制有關(guān)

          ZK集群的選舉機(jī)制

          我們就拿3個(gè)節(jié)點(diǎn)的zk作一個(gè)簡(jiǎn)單選舉的說(shuō)明


          zk會(huì)進(jìn)行多輪的投票,直到某一個(gè)節(jié)點(diǎn)的票數(shù)大于或等于半數(shù)以上,在3個(gè)節(jié)點(diǎn)中,總共會(huì)進(jìn)行2輪的投票:

          • 第一輪,每個(gè)節(jié)點(diǎn)啟動(dòng)時(shí)投票給自己,那這樣zk1,zk2,zk3各有一票。
          • 第二輪,每個(gè)節(jié)點(diǎn)投票給大于自己myid,那這樣zk2啟動(dòng)時(shí)又獲得一票。加上自己給自己投的那一票。總共有2票。2票大于了當(dāng)前節(jié)點(diǎn)總數(shù)的半數(shù),所以投票終止。zk2當(dāng)選leader。

          有的童鞋會(huì)問(wèn),zk3呢,因?yàn)閦k2已經(jīng)當(dāng)選了,投票終止了。所以zk2也不會(huì)投票給zk3了。

          當(dāng)然這是一個(gè)比較簡(jiǎn)單版的選舉,其實(shí)真正的選舉還要比較zxid,這個(gè)后面會(huì)講到。

          zk選舉什么時(shí)候會(huì)被觸發(fā)呢?一是啟動(dòng)時(shí)會(huì)被觸發(fā),二是leader宕機(jī)時(shí)會(huì)被觸發(fā)。上面的例子中,如果節(jié)點(diǎn)2宕機(jī),根據(jù)規(guī)則,那獲得leader的就應(yīng)該是zk3了。

          ZK集群的數(shù)據(jù)同步機(jī)制

          zookeeper的數(shù)據(jù)同步是為了保證每個(gè)節(jié)點(diǎn)的數(shù)據(jù)一致性,大致分為2個(gè)流程,一個(gè)是正常的客戶端數(shù)據(jù)提交流程,二是集群中某個(gè)節(jié)點(diǎn)宕機(jī)后數(shù)據(jù)恢復(fù)流程。

          正常客戶端數(shù)據(jù)提交流程

          客戶端寫(xiě)入數(shù)據(jù)提交流程大致為:leader接受到客戶端的寫(xiě)請(qǐng)求,然后同步給各個(gè)子節(jié)點(diǎn):


          但是有童鞋就產(chǎn)生疑惑了,客戶端一般連接的是所有節(jié)點(diǎn),客戶端并不知道哪個(gè)是leader呀。

          的確,客戶端會(huì)和所有的節(jié)點(diǎn)建立鏈接,并且發(fā)起寫(xiě)入請(qǐng)求是挨個(gè)遍歷節(jié)點(diǎn)進(jìn)行的,比如第一次是節(jié)點(diǎn)1,第二次是節(jié)點(diǎn)2。以此類推。

          如果客戶端正好鏈接的節(jié)點(diǎn)的角色是leader,那就按照上面的流程走。那如果鏈接的節(jié)點(diǎn)不是leader,是follower呢,則有以下流程:


          如果Client選擇鏈接的節(jié)點(diǎn)是Follower的話,這個(gè)Follower會(huì)把請(qǐng)求轉(zhuǎn)給當(dāng)前Leader,然后Leader會(huì)走藍(lán)色的線把請(qǐng)求廣播給所有的Follower,每個(gè)節(jié)點(diǎn)同步完數(shù)據(jù)后會(huì)走綠色的線告訴Leader數(shù)據(jù)已經(jīng)同步完成(但是還未提交),當(dāng)Leader收到半數(shù)以上的節(jié)點(diǎn)ACK確認(rèn)消息后,那么Leader就認(rèn)為這個(gè)數(shù)據(jù)可以提交了,會(huì)廣播給所有的Follower節(jié)點(diǎn),所有的節(jié)點(diǎn)就可以提交數(shù)據(jù)。整個(gè)同步工作就結(jié)束了。

          那我們?cè)賮?lái)說(shuō)說(shuō)節(jié)點(diǎn)宕機(jī)后的數(shù)據(jù)同步流程

          當(dāng)zookeeper集群中的Leader宕機(jī)后,會(huì)觸發(fā)新的選舉,選舉期間,整個(gè)集群是沒(méi)法對(duì)外提供服務(wù)的。直到選出新的Leader之后,才能重新提供服務(wù)。

          我們重新回到3個(gè)節(jié)點(diǎn)的例子,zk1,zk2,zk3,其中z2為L(zhǎng)eader,z1,z3為Follower,假設(shè)zk2宕機(jī)后,觸發(fā)了重新選舉,按照選舉規(guī)則,z3當(dāng)選Leader。這時(shí)整個(gè)集群只整下z1和z3,如果這時(shí)整個(gè)集群又創(chuàng)建了一個(gè)節(jié)點(diǎn)數(shù)據(jù),接著z2重啟。這時(shí)z2的數(shù)據(jù)肯定比z1和z3要舊,那這時(shí)該如何同步數(shù)據(jù)呢。

          zookeeper是通過(guò)ZXID事務(wù)ID來(lái)確認(rèn)的,ZXID是一個(gè)長(zhǎng)度為64位的數(shù)字,其中低32位是按照數(shù)字來(lái)遞增,任何數(shù)據(jù)的變更都會(huì)導(dǎo)致低32位數(shù)字簡(jiǎn)單加1。高32位是leader周期編號(hào),每當(dāng)選舉出一個(gè)新的Leader時(shí),新的Leader就從本地事務(wù)日志中取出ZXID,然后解析出高32位的周期編號(hào),進(jìn)行加1,再將低32位的全部設(shè)置為0。這樣就保證了每次選舉新的Leader后,保證了ZXID的唯一性而且是保證遞增的。

          查看某個(gè)數(shù)據(jù)節(jié)點(diǎn)的ZXID的命令為:

          先進(jìn)入zk?client命令行
          ./bin/zkCli.sh?-server?127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183?
          stat加上數(shù)據(jù)節(jié)點(diǎn)名稱
          stat?/test

          執(zhí)行結(jié)果為:


          可以看到,有3個(gè)ZXID,這3個(gè)ZXID各自代表:

          cZxid:該節(jié)點(diǎn)創(chuàng)建時(shí)的事務(wù)ID

          mZxid:該節(jié)點(diǎn)最近一次更新時(shí)的事務(wù)ID

          pZxid:該節(jié)點(diǎn)的子節(jié)點(diǎn)的最新一次創(chuàng)建/更新/刪除的事務(wù)ID

          查看節(jié)點(diǎn)最新ZXID的命令為:

          echo?stat|nc?127.0.0.1?2181
          這個(gè)命令需提前在cfg文件后追加:4lw.commands.whitelist=*,然后重啟


          這里的ZXID就是當(dāng)前節(jié)點(diǎn)最后一次事務(wù)的ID。

          如果整個(gè)集群數(shù)據(jù)為一致的,那么所有節(jié)點(diǎn)的ZXID應(yīng)該一樣。所以zookeeper就通過(guò)這個(gè)有序的ZXID來(lái)確保各個(gè)節(jié)點(diǎn)之間的數(shù)據(jù)的一致性,帶著之前的問(wèn)題,如果Leader宕機(jī)之后,再重啟后,會(huì)去和目前的Leader去比較最新的ZXID,如果節(jié)點(diǎn)的ZXID比最新Leader里的ZXID要小,那么就會(huì)去同步數(shù)據(jù)。

          再看ZK中的選舉

          我們帶著ZXID的概念再來(lái)看ZK中的選舉機(jī)制。

          假設(shè)還是有一個(gè)3個(gè)節(jié)點(diǎn)的集群,zk2為L(zhǎng)eader,這時(shí)候如果zk2掛了。zk3當(dāng)選Leader,zk1為Follower。這時(shí)候如果更新集群中的一個(gè)數(shù)據(jù)。然后把zk1和zk3都關(guān)閉。然后挨個(gè)再重啟zk1,zk2,zk3。這時(shí)候啟動(dòng)后,zk2還能當(dāng)選為L(zhǎng)eader嗎?

          其實(shí)這個(gè)問(wèn)題,換句話說(shuō)就是:在挨個(gè)啟動(dòng)zk節(jié)點(diǎn)的時(shí)候,zk1和zk3的數(shù)據(jù)為最新,而zk2的數(shù)據(jù)不是最新的,按照之前的選舉規(guī)則的話,zk2是否能順利當(dāng)選Leader?

          答案為否,最后當(dāng)選的為zk1。

          這是為什么呢。

          因?yàn)閦k2的最新ZXID已經(jīng)不是最新了,zk的選舉過(guò)程會(huì)優(yōu)先考慮ZXID大的節(jié)點(diǎn)。這時(shí)ZXID最大的有zk1和zk3,選舉只會(huì)在這2個(gè)節(jié)點(diǎn)中產(chǎn)生,根據(jù)之前說(shuō)的選舉規(guī)則。在第一輪投票的時(shí)候,zk1只要獲得1票,就能達(dá)到半數(shù)了,就能順利當(dāng)選為L(zhǎng)eader了。

          最后

          其實(shí)zk的選舉和同步并不復(fù)雜,如果能試著在本地去搭建3個(gè)節(jié)點(diǎn)的偽集群,去試著跑一下上面的案例。應(yīng)該就能明白整個(gè)過(guò)程。zk作為老牌的一致性協(xié)調(diào)中間件,也是諸多面試的頻次很高的問(wèn)點(diǎn)。如果你能理解本篇的核心內(nèi)容,再次碰到這類問(wèn)題的時(shí)候,這將不會(huì)是你的盲區(qū)。

          最后,喜歡本篇內(nèi)容的朋友希望點(diǎn)贊,關(guān)注,轉(zhuǎn)發(fā)。

          1.?100萬(wàn)人同時(shí)搶1萬(wàn)張火車票,極限并發(fā)帶來(lái)的思考

          2.?Git各指令的本質(zhì),真是通俗易懂啊

          3.?從0到1帶你手?jǐn)]一個(gè)請(qǐng)求重試組件,不信你學(xué)不會(huì)!

          4.?最牛逼的 Java 日志框架,性能無(wú)敵,橫掃所有對(duì)手.....

          最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊(cè),覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點(diǎn)“在看”,關(guān)注公眾號(hào)并回復(fù)?Java?領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

          文章有幫助的話,在看,轉(zhuǎn)發(fā)吧。

          謝謝支持喲 (*^__^*)

          瀏覽 86
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  黄片视频在线免费看 | 国产精品久久久久久久 | 黄色操逼网 | 极品色逼网 | 国产婷婷五月天 |