1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

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

        共 4629字,需瀏覽 10分鐘

         ·

        2021-10-13 04:38

        前言

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

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

        其實很多的分布式中間件的選舉和同步,都和zk有異曲同工之妙。這篇文章我就來重點聊下關于zk集群之間的選舉和同步機制。

        ZK集群的部署

        首先我們來看下半數(shù)運行機制:

        集群至少需要三臺服務器,且官方文檔強烈建議使用奇數(shù)個服務器,因為zookeeper是通過判斷大多數(shù)節(jié)點的的存活來判斷整個服務集群是否可用的,比如3個節(jié)點,它的一半是1.5,向上取整就是2。掛掉了2個就是表示整個集群掛掉。而用偶數(shù)4個的話,掛掉2個也表示不是大部分存活,因此也會掛掉。所以用4臺服務器的話 ,從使用資源上來說,并不劃算。

        配置語法:

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

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

        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ù)指定的是一個目錄,用來存放zk的數(shù)據(jù),里面有個文件myid,3臺機器上myid文件里面分別存放1,2,3。對應各自節(jié)點ID。

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

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

        ZK集群中的角色

        zookeeper集群中公共有三種角色,分別是leader,followerobserver。

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

        關于observer的配置:

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

        server.3=127.0.0.1:2883:3883:observer

        其中l(wèi)eader只有一個,剩下的都是follower和observer,但是我們一般生產上不會配置observer,因為observer并沒有選舉權,可以理解為observer是一個臨時工,不是正式員工,沒法獲得晉升。除此之外,它和follower的功能是一樣的。

        什么時候需要用到observer呢,因為zk一般讀的請求會大于寫。當整個集群壓力過大時,我們可以增加幾個臨時工observer來獲得性能的提升。在不需要的時候的時候,可以隨時撤掉observer。

        zk進行連接時,一般我們都會把zk所有的節(jié)點都配置上去,用逗號分隔。其實連接集群中的任意一個或者多個都是可以的。只是如果只連一個節(jié)點,當這個節(jié)點宕機的時候,我們就斷開了連接。所以還是推薦配置多個節(jié)點進行連接。

        如何查看ZK集群中的角色

        我們可以利用以下命令來查看zk集群中的角色

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

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


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


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

        ZK集群的選舉機制

        我們就拿3個節(jié)點的zk作一個簡單選舉的說明


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

        • 第一輪,每個節(jié)點啟動時投票給自己,那這樣zk1,zk2,zk3各有一票。
        • 第二輪,每個節(jié)點投票給大于自己myid,那這樣zk2啟動時又獲得一票。加上自己給自己投的那一票??偣灿?票。2票大于了當前節(jié)點總數(shù)的半數(shù),所以投票終止。zk2當選leader。

        有的童鞋會問,zk3呢,因為zk2已經(jīng)當選了,投票終止了。所以zk2也不會投票給zk3了。

        當然這是一個比較簡單版的選舉,其實真正的選舉還要比較zxid,這個后面會講到。

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

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

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

        正??蛻舳藬?shù)據(jù)提交流程

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


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

        的確,客戶端會和所有的節(jié)點建立鏈接,并且發(fā)起寫入請求是挨個遍歷節(jié)點進行的,比如第一次是節(jié)點1,第二次是節(jié)點2。以此類推。

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


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

        那我們再來說說節(jié)點宕機后的數(shù)據(jù)同步流程

        當zookeeper集群中的Leader宕機后,會觸發(fā)新的選舉,選舉期間,整個集群是沒法對外提供服務的。直到選出新的Leader之后,才能重新提供服務。

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

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

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

        先進入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é)點名稱
        stat?/test

        執(zhí)行結果為:


        可以看到,有3個ZXID,這3個ZXID各自代表:

        cZxid:該節(jié)點創(chuàng)建時的事務ID

        mZxid:該節(jié)點最近一次更新時的事務ID

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

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

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


        這里的ZXID就是當前節(jié)點最后一次事務的ID。

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

        再看ZK中的選舉

        我們帶著ZXID的概念再來看ZK中的選舉機制。

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

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

        答案為否,最后當選的為zk1。

        這是為什么呢。

        因為zk2的最新ZXID已經(jīng)不是最新了,zk的選舉過程會優(yōu)先考慮ZXID大的節(jié)點。這時ZXID最大的有zk1和zk3,選舉只會在這2個節(jié)點中產生,根據(jù)之前說的選舉規(guī)則。在第一輪投票的時候,zk1只要獲得1票,就能達到半數(shù)了,就能順利當選為Leader了。

        最后

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

        最后,喜歡本篇內容的朋友希望點贊,關注,轉發(fā)。

        1.?100萬人同時搶1萬張火車票,極限并發(fā)帶來的思考

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

        3.?從0到1帶你手擼一個請求重試組件,不信你學不會!

        4.?最牛逼的 Java 日志框架,性能無敵,橫掃所有對手.....

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

        獲取方式:點“在看”,關注公眾號并回復?Java?領取,更多內容陸續(xù)奉上。

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

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

        瀏覽 86
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            成年人视频中文字幕在线播放 | cosplay18xxxxhdpictures | zzji欧美成熟丰满 | 人妻在线导航 | 国产精品扒开腿做爽爽爽免费网站 | 日韩色视频 | 一级片网址大全 | 一级特黄60分钟高清免费观看 | 色噜噜狠狠一区二区三区牛牛影视 | 成人黄色在线网站 |