學習zookeeper

最近研究了一下zookeeper(后續(xù)以zk簡稱),對于一個自認為泡在服務器領域多年的老油條來說伟阔,現(xiàn)在才開始關注zk這個東西,其實有點晚了蒸痹,但沒辦法抡笼,以前的工作經(jīng)歷讓我壓根用不到這個玩意推姻。只是最近因為要考慮做ledisdb的cluster方案校翔,以及重新考慮mixer的協(xié)調(diào)管理,才讓我真正開始嘗試去了解zk饲嗽。

什么是zookeeper

根據(jù)官網(wǎng)的介紹,zookeeper是一個分布式協(xié)調(diào)服務沉馆,主要用來處理分布式系統(tǒng)中各系統(tǒng)之間的協(xié)作問題的缨叫。

其實這么說有點抽象渣叛,初次接觸zk丈秩,很多人真不知道用它來干啥,你可以將它想成一個總控節(jié)點(當然它能用多機實現(xiàn)自身的HA)淳衙,能對所有服務進行操作蘑秽。這樣就能實現(xiàn)對整個分布式系統(tǒng)的統(tǒng)一管理饺著。

譬如我現(xiàn)在有n臺機器,需要動態(tài)更新某一個配置肠牲,一些做法可能是通過puppet或者salt將配置先分發(fā)到不同機器幼衰,然后運行指定的reload命令。zk的做法可能是所有服務都監(jiān)聽一個配置節(jié)點缀雳,直接更改這個節(jié)點的數(shù)據(jù)渡嚣,然后各個服務就能收到更新消息,然后同步最新的配置肥印,再自行reload了严拒。

上面只是一個很簡單的例子,其實通過它并不能過多的體現(xiàn)zk的優(yōu)勢(沒準salt可能還更簡單)竖独,但zk不光只能干這些,還能干更awesome的事情挤牛。網(wǎng)上有太多關于zk應用場景一覽的文章了莹痢,這里就不詳細說明,后續(xù)我只會說一下自己需要用zk解決的棘手問題墓赴。

架構

zk使用類paxos算法來保證其HA竞膳,每次通過選舉得到一個master用來處理client的請求,client可以掛載到任意一臺zk server上面诫硕,因為paxos這種是強一致同步算法坦辟,所以zk能保證每一臺server上面數(shù)據(jù)都是一致的。架構如下:

?????????????????????????????????????????????????????????????????????
??????????????????????+-------------------------------+?????????????????????????
??????????????????????|???????????????????????????????|?????????????????????????
??????????????+----+--++??????????+----+---+????????+-+--+---+??????????????????
??????????????|?server?|??????????|?server?|????????|?server?|??????????????????
??????????????|????????+----------+?master?+--------+????????|??????????????????
??????????????+--^--^--+??????????+----^---+????????+----^---+??????????????????
?????????????????|??|??????????????????|?????????????????|??????????????????????
?????????????????|??|??????????????????|?????????????????|??????????????????????
?????????????????|??|??????????????????|?????????????????|??????????????????????
???????????+-----+??+-----+????????????+------+??????????+---------+????????????
???????????|??????????????|???????????????????|????????????????????|????????????
???????????|??????????????|???????????????????|????????????????????|????????????
??????+----+---+????????+-+------+?????????+--+-----+???????????+--+-----+??????
??????|?client?|????????|?client?|?????????|?client?|???????????|?client?|??????
??????+--------+????????+--------+?????????+--------+???????????+--------+??????

Data Model

zk內(nèi)部是按照類似文件系統(tǒng)層級方式進行數(shù)據(jù)存儲的章办,就像這樣:

                        +---+             
                        | / |             
                        +++-+             
                         ||               
                         ||               
          +-------+------++----+-------+  
          | /app1 |            | /app2 |  
          +-+--+--+            +---+---+  
            |  |                   |      
            |  |                   |      
            |  |                   |      
+----------++ ++---------+    +----+-----+
| /app1/p1 |  | /app1/p2 |    | /app2/p1 |
+----------+  +----------+    +----------+

對于任意一個節(jié)點锉走,我們稱之為znode,znode有很多屬性藕届,譬如Zxid(每次更新的事物ID)等挪蹭,具體可以詳見zk的文檔。znode有ACL控制休偶,我們可以很方便的設置其讀寫權限等梁厉,但個人感覺對于內(nèi)網(wǎng)小集群來說意義不怎么大,所以也就沒深入研究踏兜。

znode有一種Ephemeral Node词顾,也就是臨時節(jié)點,它是session有效的碱妆,當session結束之后肉盹,這個node自動刪除,所以我們可以用這種node來實現(xiàn)對服務的監(jiān)控山橄。譬如一個服務啟動之后就向zk掛載一個ephemeral node垮媒,如果這個服務崩潰了舍悯,那么連接斷開,session無效了睡雇,這個node就刪除了萌衬,我們也就知道該服務出了問題。

znode還有一種Sequence Node它抱,用來實現(xiàn)序列化的唯一節(jié)點秕豫,我們可以通過這個功能來實現(xiàn)一個簡單地leader服務選舉,譬如每個服務啟動的時候都向zk注冊一個sequence node观蓄,誰最先注冊混移,zk給的sequence最小,這個最小的就是leader了侮穿,如果leader當?shù)袅烁杈叮敲淳哂械诙equence node的節(jié)點就成為新的leader。

Znode Watch

我們可以watch一個znode亲茅,用來監(jiān)聽對應的消息回铛,zk會負責通知,但只會通知一次克锣。所以需要我們再次重新watch這個znode茵肃。那么如果再次watch之前,znode又有更新了袭祟,client不是收不到了嗎验残?這個就需要client不光要處理watch,同時也需要適當?shù)闹鲃觛et相關的數(shù)據(jù)巾乳,這樣就能保證得到最新的消息了您没。也就是消息系統(tǒng)里面典型的推拉結合的方式。推只是為了提升性能胆绊,快速響應紊婉,而拉則為了更好的保證消息不丟失。

但是辑舷,我們需要注意一點喻犁,zk并不能保證client收到消息之后同時處理,譬如配置文件更新何缓,zk可能通知了所有client肢础,但client并不能全部在同一個時間同時reload,所以為了處理這樣的問題碌廓,我們需要額外的機制來保證传轰,這個后續(xù)說明。

watch只能應用于data(通過get谷婆,exists函數(shù))以及children(通過getChildren函數(shù))慨蛙。也就是監(jiān)控znode數(shù)據(jù)更新以及znode的子節(jié)點的改變辽聊。

API

zk的API時很簡單的,如下:

  • create
  • delete
  • exists
  • set data
  • get data
  • get chilren
  • sync

就跟通常的文件系統(tǒng)操作差不多期贫,就不過多說明了跟匆。

Example

總的來說,如果我們不深入zk的內(nèi)部實現(xiàn)通砍,譬如paxos等玛臂,zk還是很好理解的,而且使用起來很簡單封孙。通常我們需要考慮的就是用zk來干啥迹冤,而不是為了想引入一個牛的新特性而用zk。

Lock

用zk可以很方便的實現(xiàn)一個分布式lock虎忌,記得最開始做企業(yè)群組盤的時候泡徙,我需要實現(xiàn)一個分布式lock,然后就用redis來弄了一個膜蠢,其實當時就很擔心redis單點當?shù)舻膯栴}锋勺,如果那時候我就引入了zk,可能就沒這個擔心了狡蝶。

官方文檔已經(jīng)很詳細的給出了lock的實現(xiàn)流程:

  1. create一個類似path/lock-n的臨時序列節(jié)點
  2. getChilren相應的path,注意這里千萬不能watch贮勃,不然驚群很恐怖的
  3. 如果1中n是最小的贪惹,則獲取lock
  4. 否則,調(diào)用exists watch到上一個比自己小的節(jié)點寂嘉,譬如我現(xiàn)在n是5奏瞬,我就可能watch node-4
  5. 如果exists失敗,表明前一個節(jié)點沒了泉孩,則進入步驟2硼端,否則等待,直到watch觸發(fā)重新進入步驟2

Codis

最近在考慮ledisdb的cluster方案寓搬,本來也打算用proxy來解決的珍昨,然后就在想用zk來處理rebalance的問題,結果這時候codis橫空出世句喷,發(fā)現(xiàn)不用自己整了镣典,于是就好好的研究了一下codis的數(shù)據(jù)遷移問題。其實也很簡單:

  1. config發(fā)起pre migrate action
  2. proxy接收到這個action之后唾琼,將對應的slot設置為pre migrate狀態(tài)兄春,同時等待config發(fā)起migrate action
  3. config等待所有的proxy返回pre migrate之后,發(fā)起migrate action
  4. proxy收到migrate action锡溯,將對應的slot設置為migrate狀態(tài)

上面這些赶舆,都是通過zk來完成的哑姚,這里需要關注一下為啥要有pre migrate這個狀態(tài),如果config直接發(fā)起migrate芜茵,那么zk并不能保證proxy同一時間全部更新成migrate狀態(tài)叙量,所以我們必須有一個中間狀態(tài),在這個中間狀態(tài)里面夕晓,proxy對于特定的slot不會干任何事情宛乃,只能等待config將其設置為migrate。雖然proxy對于相應slot一段時間無法處理外部請求蒸辆,但這個時間是很短的(不過此時config當?shù)袅司蛻K了)征炼。config知道所有proxy都變成pre migrate狀態(tài)之后,就可以很放心的發(fā)送migrate action了躬贡。因為這時候谆奥,proxy只有兩種可能,變成migrate狀態(tài)拂玻,能正常工作酸些,仍然還是pre migrate狀態(tài),不能工作檐蚜,也自然不會對數(shù)據(jù)造成破壞魄懂。

其實上面也就是一個典型的2PC,雖然仍然可能有隱患闯第,譬如config當?shù)羰欣酰⒉粫嶋H數(shù)據(jù)造成破壞。而且config當?shù)袅宋覀円材芎芸熘獣圆⒅匦聠涌榷蹋詥栴}不大填帽。

總結

總的來說,zk的使用還是挺簡單的咙好,只要我們知道它到底能用到什么地方篡腌,那zk就真的是分布式開發(fā)里面一把瑞士軍刀了。不過我挺不喜歡裝java那套東西勾效,為了zk也沒辦法嘹悼,雖然go現(xiàn)在也有etcd這些類zk的東西了,但畢竟還沒經(jīng)受過太多的考驗层宫,所以現(xiàn)在還是老老實實的zk吧绘迁。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市卒密,隨后出現(xiàn)的幾起案子缀台,更是在濱河造成了極大的恐慌,老刑警劉巖哮奇,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件膛腐,死亡現(xiàn)場離奇詭異睛约,居然都是意外死亡,警方通過查閱死者的電腦和手機哲身,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門辩涝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人勘天,你說我怎么就攤上這事怔揩。” “怎么了脯丝?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵商膊,是天一觀的道長。 經(jīng)常有香客問我宠进,道長晕拆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任材蹬,我火速辦了婚禮实幕,結果婚禮上,老公的妹妹穿的比我還像新娘堤器。我一直安慰自己昆庇,他們只是感情好,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布闸溃。 她就那樣靜靜地躺著整吆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪圈暗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天裕膀,我揣著相機與錄音员串,去河邊找鬼。 笑死昼扛,一個胖子當著我的面吹牛寸齐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播抄谐,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼渺鹦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蛹含?” 一聲冷哼從身側響起毅厚,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎浦箱,沒想到半個月后吸耿,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體祠锣,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年咽安,在試婚紗的時候發(fā)現(xiàn)自己被綠了伴网。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡妆棒,死狀恐怖澡腾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情糕珊,我是刑警寧澤动分,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站放接,受9級特大地震影響刺啦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜纠脾,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一玛瘸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧苟蹈,春花似錦糊渊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至菱鸥,卻和暖如春宗兼,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背氮采。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工殷绍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鹊漠。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓主到,卻偏偏與公主長得像,于是被迫代替她去往敵國和親躯概。 傳聞我的和親對象是個殘疾皇子登钥,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內(nèi)容