zookeeper 原理、應用總結

Zookeeper綜述

背景

分佈式系統的特點有:分佈性、對等性、併發性、缺乏全局時鐘、故障隨時會發生。

分佈性
既然是分佈式系統,最顯著的特點肯定就是分佈性,從簡單來看,如果我們做的是個電商項目,整個項目會分成不同的功能,專業點就不同的微服務,比如用戶微服務,產品微服務,訂單微服務,這些服務部署在不同的tomcat中,不同的服務器中,甚至不同的集羣中,整個架構都是分佈在不同的地方的,在空間上是隨意的,而且隨時會增加,刪除服務器節點,這是第一個特性

對等性
對等性是分佈式設計的一個目標,還是以電商網站爲例,來說明下什麼是對等性,要完成一個分佈式的系統架構,肯定不是簡單的把一個大的單一系統拆分成一個個微服務,然後部署在不同的服務器集羣就夠了,其中拆分完成的每一個微服務都有可能發現問題,而導致整個電商網站出現功能的丟失。
比如訂單服務,爲了防止訂單服務出現問題,一般情況需要有一個備份,在訂單服務出現問題的時候能頂替原來的訂單服務。
這就要求這兩個(或者2個以上)訂單服務完全是對等的,功能完全是一致的,其實這就是一種服務副本的冗餘。
還一種是數據副本的冗餘,比如數據庫,緩存等,都和上面說的訂單服務一樣,爲了安全考慮需要有完全一樣的備份存在,這就是對等性的意思。

併發性
併發性其實對我們來說並不模式,在學習多線程的時候已經或多或少學習過,多線程是併發的基礎。
但現在我們要接觸的不是多線程的角度,而是更高一層,從多進程,多JVM的角度,例如在一個分佈式系統中的多個節點,可能會併發地操作一些共享資源,如何準確並高效的協調分佈式併發操作。
後面實戰部分的分佈式鎖其實就是解決這問題的。

缺乏全局時鐘
在分佈式系統中,節點是可能反正任意位置的,而每個位置,每個節點都有自己的時間系統,因此在分佈式系統中,很難定義兩個事務糾結誰先誰後,原因就是因爲缺乏一個全局的時鐘序列進行控制,當然,現在這已經不是什麼大問題了,已經有大把的時間服務器給系統調用
故障隨時會發生
任何一個節點都可能出現停電,死機等現象,服務器集羣越多,出現故障的可能性就越大,隨着集羣數目的增加,出現故障甚至都會成爲一種常態,怎麼樣保證在系統出現故障,而系統還是正常的訪問者是作爲系統架構師應該考慮的。

分佈式系統帶來的問題
如果把分佈式系統和平時的交通系統進行對比,哪怕再穩健的交通系統也會有交通事故,分佈式系統也有很多需要攻克的問題,比如:通訊異常,網絡分區,三態,節點故障等。

通信異常
通訊異常其實就是網絡異常,網絡系統本身是不可靠的,由於分佈式系統需要通過網絡進行數據傳輸,網絡光纖,路由器等硬件難免出現問題。只要網絡出現問題,也就會影響消息的發送與接受過程,因此數據消息的丟失或者延長就會變得非常普遍。

網絡分區
網絡分區,其實就是腦裂現象,本來有一個交通警察,來管理整個片區的交通情況,一切井然有序,突然出現了停電,或者出現地震等自然災難,某些道路接受不到交通警察的指令,可能在這種情況下,會出現一個零時工,片警零時來指揮交通。
但注意,原來的交通警察其實還在,只是通訊系統中斷了,這時候就會出現問題了,在同一個片區的道路上有不同人在指揮,這樣必然引擎交通的阻塞混亂。
這種由於種種問題導致同一個區域(分佈式集羣)有兩個相互衝突的負責人的時候就會出現這種精神分裂的情況,在這裏稱爲腦裂,也叫網絡分區。

三態
三態是什麼?三態其實就是成功,與失敗以外的第三種狀態,當然,肯定不叫變態,而叫超時態。
在一個jvm中,應用程序調用一個方法函數後會得到一個明確的相應,要麼成功,要麼失敗,而在分佈式系統中,雖然絕大多數情況下能夠接受到成功或者失敗的相應,但一旦網絡出現異常,就非常有可能出現超時,當出現這樣的超時現象,網絡通訊的發起方,是無法確定請求是否成功處理的。

節點故障
這個其實前面已經說過了,節點故障在分佈式系統下是比較常見的問題,指的是組成服務器集羣的節點會出現的宕機或“僵死”的現象,這種現象經常會發生。

CAP理論
CAP其實就是一致性,可用性,分區容錯性這三個詞的縮寫

一致性
一致性是事務ACID的一個特性【原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)】,學習數據庫優化的時候deer老師講過。
這裏講的一致性其實大同小異,只是現在考慮的是分佈式環境中,還是不單一的數據庫。
在分佈式系統中,一致性是數據在多個副本之間是否能夠保證一致的特性,這裏說的一致性和前面說的對等性其實差不多。如果能夠在分佈式系統中針對某一個數據項的變更成功執行後,所有用戶都可以馬上讀取到最新的值,那麼這樣的系統就被認爲具有【強一致性】。

可用性
可用性指系統提供服務必須一直處於可用狀態,對於用戶的操作請求總是能夠在有限的時間內訪問結果。
這裏的重點是【有限的時間】和【返回結果】
爲了做到有限的時間需要用到緩存,需要用到負載,這個時候服務器增加的節點是爲性能考慮;
爲了返回結果,需要考慮服務器主備,當主節點出現問題的時候需要備份的節點能最快的頂替上來,千萬不能出現OutOfMemory或者其他500404錯誤,否則這樣的系統我們會認爲是不可用的。

分區容錯性
分佈式系統在遇到任何網絡分區故障的時候,仍然需要能夠對外提供滿足一致性和可用性的服務,除非是整個網絡環境都發生了故障。
不能出現腦裂的情況

來看下CAP理論具體描述:

一個分佈式系統不可能同時滿足一致性、可用性和分區容錯性這三個基本需求,最多隻能同時滿足其中的兩項
TIPS:不可能把所有應用全部放到一個節點上,因此架構師的精力往往就花在怎麼樣根據業務場景在A和C直接尋求平衡;

BASE理論
根據前面的CAP理論,架構師應該從一致性和可用性之間找平衡,系統短時間完全不可用肯定是不允許的,那麼根據CAP理論,在分佈式環境下必然也無法做到強一致性。
BASE理論:即使無法做到強一致性,但分佈式系統可以根據自己的業務特點,採用適當的方式來使系統達到最終的一致性;

Basically Avaliable  基本可用
當分佈式系統出現不可預見的故障時,允許損失部分可用性,保障系統的“基本可用”;體現在“時間上的損失”和“功能上的損失”;
e.g:部分用戶雙十一高峯期淘寶頁面卡頓或降級處理;

Soft state 軟狀態
其實就是前面講到的三態,既允許系統中的數據存在中間狀態,既系統的不同節點的數據副本之間的數據同步過程存在延時,並認爲這種延時不會影響系統可用性;
e.g:12306網站賣火車票,請求會進入排隊隊列;

Eventually consistent 最終一致性
所有的數據在經過一段時間的數據同步後,最終能夠達到一個一致的狀態;
e.g:理財產品首頁充值總金額短時不一致;

2PC 3PC Paxos Zab 算法

不管是CAP理論,還是BASE理論,他們都是理論,這些理論是需要算法來實現的, 2PC、3PC、Paxos算法,ZAB算法就是幹這事情, 解決的問題全部都是在分佈式環境下,怎麼讓系統儘可能的高可用,而且數據能最終能達到一致。

兩階段提交 two-phase commit (2PC)

兩階段提交 two-phase commit (2PC)
首先來看下2PC,翻譯過來叫兩階段提交算法,它本身是一致強一致性算法,所以很適合用作數據庫的分佈式事務。其實數據庫的經常用到的TCC本身就是一種2PC.

回想下數據庫的事務,數據庫不管是MySQL還是MSSql,本身都提供的很完善的事務支持。

MySQL後面學分表分庫的時候會講到在innodb存儲引擎,對數據庫的修改都會寫到undo和redo中,不只是數據庫,很多需要事務支持的都會用到這個思路。

對一條數據的修改操作首先寫undo日誌,記錄的數據原來的樣子,接下來執行事務修改操作,把數據寫到redo日誌裏面,萬一捅婁子,事務失敗了,可從undo裏面回覆數據。

不只是數據庫,在很多企業裏面,比如華爲等提交數據庫修改都回要求這樣,你要新增一個字段,首先要把修改數據庫的字段SQL提交給DBA(redo),這不夠,還需要把刪除你提交字段,把數據還原成你修改之前的語句也一併提交者叫(undo)

數據庫通過undo與redo能保證數據的強一致性,要解決分佈式事務的前提就是當個節點是支持事務的。

這在個前提下,2pc借鑑這失效,首先把整個分佈式事務分兩節點,首先第一階段叫準備節點,事務的請求都發送給一個個的資源,這裏的資源可以是數據庫,也可以是其他支持事務的框架,他們會分別執行自己的事務,寫日誌到undo與redo,但是不提交事務。

當事務管理器收到了所以資源的反饋,事務都執行沒報錯後,事務管理器再發送commit指令讓資源把事務提交,一旦發現任何一個資源在準備階段沒有執行成功,事務管理器會發送rollback,讓所有的資源都回滾。這就是2pc,非常非常簡單。

說他是強一致性的是他需要保證任何一個資源都成功,整個分佈式事務才成功。

優點:原理簡單,實現方便
缺點:同步阻塞,單點問題,數據不一致,容錯性不好

同步阻塞
在二階段提交的過程中,所有的節點都在等待其他節點的響應,無法進行其他操作。這種同步阻塞極大的限制了分佈式系統的性能。

單點問題
協調者在整個二階段提交過程中很重要,如果協調者在提交階段出現問題,那麼整個流程將無法運轉。更重要的是,其他參與者將會處於一直鎖定事務資源的狀態中,而無法繼續完成事務操作。

數據不一致
假設當協調者向所有的參與者發送commit請求之後,發生了局部網絡異常,或者是協調者在尚未發送完所有 commit請求之前自身發生了崩潰,導致最終只有部分參與者收到了commit請求。這將導致嚴重的數據不一致問題。

容錯性不好
二階段提交協議沒有設計較爲完善的容錯機制,任意一個節點是失敗都會導致整個事務的失敗。

三階段提交 three-phase commit (3PC)

由於二階段提交存在着諸如同步阻塞、單點問題,所以,研究者們在二階段提交的基礎上做了改進,提出了三階段提交。

第一階段canCommit

確認所有的資源是否都是健康、在線的,以約女孩舉例,你會打個電話問下她是不是在家,而且可以約個會。

如果女孩有空,你在去約她。

就因爲有了這一階段,大大的減少了2段提交的阻塞時間,在2段提交,如果有3個數據庫,恰恰第三個數據庫出現問題,其他兩個都會執行耗費時間的事務操作,到第三個卻發現連接不上。3段優化了這種情況

第二階段PreCommit

如果所有服務都ok,可以接收事務請求,這一階段就可以執行事務了,這時候也是每個資源都回寫redo與undo日誌,事務執行成功,返回ack(yes),否則返回no

第三階段doCommit

這階段和前面說的2階段提交大同小異,這個時候協調者發現所有提交者事務提交者事務都正常執行後,給所有資源發送commit指令。

和二階段提交有所不同的是,他要求所有事務在協調者出現問題,沒給資源發送commit指令的時候,三階段提交算法要求資源在一段時間超時後回默認提交做commit操作。

這樣的要求就減少了前面說的單點故障,萬一事務管理器出現問題,事務也回提交。

但回顧整個過程,不管是2pc,還是3pc,同步阻塞,單點故障,容錯機制不完善這些問題都沒本質上得到解決,尤其是前面說得數據一致性問題,反而更糟糕了。

所有數據庫的分佈式事務一般都是二階段提交,而者三階段的思想更多的被借鑑擴散成其他的算法。

Paxos算法

這個算法還是有點難度的,本身這算法的提出者萊斯利·蘭伯特在前面幾篇論文中都不是以嚴謹的數學公式進行的。

其實這個paxos算法也分成兩階段。首先這個圖有2個角色,提議者與接收者

第一階段

提議者對接收者吼了一嗓子,我有個事情要告訴你們,當然這裏接受者不只一個,它也是個分佈式集羣

相當於星期一開早會,可恥的領導吼了句:“要開會了啊,我要公佈一個編號爲001的提案,收到請回復”。

這個時候領導就會等着,等員工回覆1“好的”,如果回覆的數目超過一半,就會進行下一步。

如果由於某些原因(接收者死機,網絡問題,本身業務問題),導通過的協議未超過一半,

這個時候的領導又會再吼一嗓子,當然氣勢沒那兇殘:“好了,怕了你們了,我要公佈一個新的編號未002的提案,收到請回復1”【就其實和老師講課很像,老師經常問聽懂了嗎?聽懂的回1,沒懂的回2,只有回覆1的佔了大多數,才能講下個知識點】

第二階段

接下來到第二階段,領導苦口婆心的把你們叫來開會了,今天編號002提案的內容是:“由於項目緊張,今天加班到12點,同意的請舉手”這個時候如果絕大多少的接收者都同意,那麼好,議案就這麼決定了,如果員工反對或者直接奪門而去,那麼領導又只能從第一個階段開始:“大哥,大姐們,我有個新的提案003,快回會議室吧。。”


詳細說明:
上面那個故事描繪的是個苦逼的領導和凶神惡煞的員工之間的鬥爭,通過這個故事你們起碼要懂paxos協議的流程是什麼樣的(paxos的核心就是少數服從多數)。

上面的故事有兩個問題:
苦逼的領導(單點問題):有這一幫兇殘的下屬,這領導要不可能被氣死,要不也會辭職,這是單點問題。
凶神惡煞的下屬(一致性問題):如果員工一種都拒絕,故意和領導擡杆,最終要產生一個一致性的解決方案是不可能的。

所以paxos協議肯定不會只有一個提議者,作爲下屬的員工也不會那麼強勢
協議要求:如果接收者沒有收到過提案編號,他必須接受第一個提案編號
          如果接收者沒有收到過其他協議,他必須接受第一個協議。

舉一個例子:
有2個Proposer(老闆,老闆之間是競爭關係)和3個Acceptor(政府官員):

階段一
1.現在需要對一項議題來進行paxos過程,議題是“A項目我要中標!”,這裏的“我”指每個帶着他的祕書Proposer的Client老闆。
2.Proposer當然聽老闆的話了,趕緊帶着議題和現金去找Acceptor政府官員。
3.作爲政府官員,當然想誰給的錢多就把項目給誰。
4.Proposer-1小姐帶着現金同時找到了Acceptor-1~Acceptor-3官員,12號官員分別收取了10比特幣,找到第3號官員時,沒想到遭到了3號官員的鄙視,3號官員告訴她,Proposer-2給了11比特幣。不過沒關係,Proposer-1已經得到了1,2兩個官員的認可,形成了多數派(如果沒有形成多數派,Proposer-1會去銀行提款在來找官員們給每人20比特幣,這個過程一直重複每次+10比特幣,直到多數派的形成),滿意的找老闆覆命去了,但是此時Proposer-2保鏢找到了1,2號官員,分別給了他們11比特幣,1,2號官員的態度立刻轉變,都說Proposer-2的老闆懂事,這下子Proposer-2放心了,搞定了3個官員,找老闆覆命去了,當然這個過程是第一階段提交,只是官員們初步接受賄賂而已。故事中的比特幣是編號,議題是value。

這個過程保證了在某一時刻,某一個proposer的議題會形成一個多數派進行初步支持

階段二
5. 現在進入第二階段提交,現在proposer-1小姐使用分身術(多線程併發)分了3個自己分別去找3位官員,最先找到了1號官員籤合同,遭到了1號官員的鄙視,1號官員告訴他proposer-2先生給了他11比特幣,因爲上一條規則的性質proposer-1小姐知道proposer-2第一階段在她之後又形成了多數派(至少有2位官員的贓款被更新了);此時她趕緊去提款準備重新賄賂這3個官員(重新進入第一階段),每人20比特幣。剛給1號官員20比特幣, 1號官員很高興初步接受了議題,還沒來得及見到2,3號官員的時候

這時proposer-2先生也使用分身術分別找3位官員(注意這裏是proposer-2的第二階段),被第1號官員拒絕了告訴他收到了20比特幣,第2,3號官員順利簽了合同,這時23號官員記錄client-2老闆用了11比特幣中標,因爲形成了多數派,所以最終接受了Client2老闆中標這個議題,對於proposer-2先生已經出色的完成了工作;

這時proposer-1小姐找到了2號官員,官員告訴她合同已經簽了,將合同給她看,proposer-1小姐是一個沒有什麼職業操守的聰明人,覺得跟Client1老闆混沒什麼前途,所以將自己的議題修改爲“Client2老闆中標”,並且給了2號官員20比特幣,這樣形成了一個多數派。順利的再次進入第二階段。由於此時沒有人競爭了,順利的找3位官員籤合同,3位官員看到議題與上次一次的合同是一致的,所以最終接受了,形成了多數派,proposer-1小姐跳槽到Client2老闆的公司去了。

總結:Paxos過程結束了,這樣,一致性得到了保證,算法運行到最後所有的proposer都投“client2中標”所有的acceptor都接受這個議題,也就是說在最初的第二階段,議題是先入爲主的,誰先佔了先機,後面的proposer在第一階段就會學習到這個議題而修改自己本身的議題,因爲這樣沒職業操守,才能讓一致性得到保證,這就是paxos算法的一個過程。原來paxos算法裏的角色都是這樣的不靠譜,不過沒關係,結果靠譜就可以了。該算法就是爲了追求結果的一致性。

Zookeeper集羣一致性協議ZAB解析

懂了paxos算法,其實zab就很好理解了。很多論文和資料都證明zab其實就是paxos的一種簡化實現,但Apache 自己的立場說zab不是paxos算法的實現,這個不需要去計較。

zab協議解決的問題和paxos一樣,是解決分佈式系統的數據一致性問題

zookeeper就是根據zab協議建立了主備模型完成集羣的數據同步(保證數據的一致性),前面介紹了集羣的各種角色,這說所說的主備架構模型指的是,在zookeeper集羣中,只有一臺leader(主節點)負責處理外部客戶端的事務請求(寫操作),leader節點負責將客戶端的寫操作數據同步到所有的follower節點中。

zab協議核心是在整個zookeeper集羣中只有一個節點既leader將所有客戶端的寫操作轉化爲事務(提議proposal).leader節點再數據寫完之後,將向所有的follower節點發送數據廣播請求(數據複製),等所有的follower節點的反饋,在zab協議中,只要超過半數follower節點反饋ok,leader節點會向所有follower服務器發送commit消息,既將leader節點上的數據同步到follower節點之上。

發現,整個流程其實和paxos協議其實大同小異。說zab是paxos的一種實現方式其實並不過分。

Zab再細看可以分成兩部分。

第一的消息廣播模式,第二是崩潰恢復模式。

正常情況下當客戶端對zk有寫的數據請求時,leader節點會把數據同步到follower節點,這個過程其實就是消息的廣播模式
在新啓動的時候,或者leader節點奔潰的時候會要選舉新的leader,選好新的leader之後會進行一次數據同步操作,整個過程就是奔潰恢復。

消息廣播模式

爲了保證分區容錯性,zookeeper是要讓每個節點副本必須是一致的

在zookeeper集羣中數據副本的傳遞策略就是採用的廣播模式
Zab協議中的leader等待follower的ack反饋,只要半數以上的follower成功反饋就好,不需要收到全部的follower反饋。

zookeeper中消息廣播的具體步驟如下:

1. 客戶端發起一個寫操作請求 
2. Leader服務器將客戶端的request請求轉化爲事物proposql提案,同時爲每個proposal分配一個全局唯一的ID,即ZXID。 
3. leader服務器與每個follower之間都有一個隊列,leader將消息發送到該隊列 
4. follower機器從隊列中取出消息處理完(寫入本地事物日誌中)畢後,向leader服務器發送ACK確認。 
5. leader服務器收到半數以上的follower的ACK後,即認爲可以發送commit 
6. leader向所有的follower服務器發送commit消息。

zookeeper採用ZAB協議的核心就是只要有一臺服務器提交了proposal,就要確保所有的服務器最終都能正確提交proposal。這也是CAP/BASE最終實現一致性的一個體現。

回顧一下:前面還講了2pc協議,也就是兩階段提交,發現流程2pc和zab還是挺像的,
zookeeper中數據副本的同步方式與二階段提交相似但是卻又不同。二階段提交的要求協調者必須等到所有的參與者全部反饋ACK確認消息後,再發送commit消息。要求所有的參與者要麼全部成功要麼全部失敗。二階段提交會產生嚴重阻塞問題,但paxos和2pc沒有這要求。

爲了進一步防止阻塞,leader服務器與每個follower之間都有一個單獨的隊列進行收發消息,使用隊列消息可以做到異步解耦。leader和follower之間只要往隊列中發送了消息即可。如果使用同步方式容易引起阻塞。性能上要下降很多

崩潰恢復

背景(什麼情況下會崩潰恢復)
zookeeper集羣中爲保證任何所有進程能夠有序的順序執行,只能是leader服務器接受寫請求,即使是follower服務器接受到客戶端的請求,也會轉發到leader服務器進行處理。

如果leader服務器發生崩潰(重啓是一種特殊的奔潰,這時候也沒leader),則zab協議要求zookeeper集羣進行崩潰恢復和leader服務器選舉。

最終目的(恢復成什麼樣)

ZAB協議崩潰恢復要求滿足如下2個要求:
確保已經被leader提交的proposal必須最終被所有的follower服務器提交。
確保丟棄已經被leader出的但是沒有被提交的proposal。

新選舉出來的leader不能包含未提交的proposal,即新選舉的leader必須都是已經提交了的proposal的follower服務器節點。同時,新選舉的leader節點中含有最高的ZXID。這樣做的好處就是可以避免了leader服務器檢查proposal的提交和丟棄工作。

每個Server會發出一個投票,第一次都是投自己。投票信息:(myid,ZXID)
收集來自各個服務器的投票
處理投票並重新投票,處理邏輯:優先比較ZXID,然後比較myid
統計投票,只要超過半數的機器接收到同樣的投票信息,就可以確定leader
改變服務器狀態

問題:爲什麼優先選大的zxid

zookeeper

介紹

ZooKeeper致力於提供一個高性能、高可用,且具備嚴格的順序訪問控制能力的分佈式協調服務,是雅虎公司創建,是Google的Chubby一個開源的實現,也是Hadoop和Hbase的重要組件。

設計目標

簡單的數據結構:共享的樹形結構,類似文件系統,存儲於內存;
可以構建集羣:避免單點故障,3-5臺機器就可以組成集羣,超過半數正常工作就能對外提供服務;
順序訪問:對於每個讀請求,zk會分配一個全局唯一的遞增編號,利用這個特性可以實現高級協調服務;
高性能:基於內存操作,服務於非事務請求,適用於讀操作爲主的業務場景。3臺zk集羣能達到13w QPS;

zookeeper 應用場景

數據發佈訂閱
負載均衡
命名服務
Master選舉
集羣管理
配置管理
分佈式隊列
分佈式鎖

zookeeper 安裝

下載安裝 JDK 1.8 & http://zookeeper.apache.org/

zookeeper 目錄結構

bin              存放系統腳本
conf             存放配置文件
contrib          zk附加功能支持
dist-maven       maven倉庫文件
docs             zk文檔
lib              依賴的第三方庫
recipes          經典場景樣例代碼
src              zk源碼

運維的配置conf/zoo.cfg

clientPort:參數無默認值,必須配置,用於配置當前服務器對外的服務端口,客戶端必須使用這端口才能進行連接
dataDir:用於存放內存數據庫快照的文件夾,同時用於集羣的myid文件也存在這個文件夾裏(注意:一個配置文件只能包含一個dataDir字樣,即使它被註釋掉了。)
dataLogDir:用於單獨設置transaction log的目錄,transaction log分離可以避免和普通log還有快照的競爭

dataDir:新安裝zk這文件夾裏面是沒有文件的,可以通過snapCount參數配置產生快照的時機

以下配置集羣中才會使用
tickTime:心跳時間,爲了確保連接存在的,以毫秒爲單位,最小超時時間爲兩個心跳時間
initLimit:多少個心跳時間內,允許其他server連接並初始化數據,如果ZooKeeper管理的數據較大,則應相應增大這個值
syncLimit:多少個tickTime內,允許follower同步,如果follower落後太多,則會被丟棄。

使用命令行

服務端常用命令
在準備好相應的配置之後,可以直接通過zkServer.sh 這個腳本進行服務的相關操作 
啓動ZK服務:       sh bin/zkServer.sh start ·
查看ZK服務狀態:    sh bin/zkServer.sh status · 
停止ZK服務:       sh bin/zkServer.sh stop · 
重啓ZK服務:       sh bin/zkServer.sh restart 

客戶端常用命令
使用 zkCli.sh -server 127.0.0.1:2181 連接到 ZooKeeper 服務,連接成功後,系統會輸出 ZooKeeper 的相關環境以及配置信息。 命令行工具的一些簡單操作如下:
顯示根目錄下、文件:       ls / 使用 ls 命令來查看當前 ZooKeeper 中所包含的內容 
顯示根目錄下、文件:       ls2 / 查看當前節點數據並能看到更新次數等數據 
創建文件,並設置初始內容:  create /zk "test" 創建一個新的 znode節點“ zk ”以及與它關聯的字符串【-e 零時節點】 【-s 順序節點】
獲取文件內容:             get /zk 確認 znode 是否包含我們所創建的字符串  [watch]【watch 監聽】
修改文件內容:             set /zk "zkbak" 對 zk 所關聯的字符串進行設置 ·
刪除文件:                 delete /zk 將剛纔創建的 znode 刪除,如果存在子節點刪除失敗 
遞歸刪除:                 rmr  /zk將剛纔創建的 znode 刪除,子節點同時刪除
退出客戶端:               quit ·
幫助命令:                 help

zookeeper 特性

Zk的特性會從會話、數據節點,版本,Watcher,ACL權限控制,集羣角色這些部分來了解,其中重點需要掌握的數據節點與Watcher

zookeeper 會話

客戶端與服務端的一次會話連接,本質是TCP長連接,通過會話可以進行心跳檢測和數據傳輸;
會話(session)是zookepper非常重要的概念,客戶端和服務端之間的任何交互操作都與會話有關

會話狀態

Zk客戶端和服務端成功連接後,就創建了一次會話,ZK會話在整個運行期間的生命週期中,會在不同的會話狀態之間切換,這些狀態包括:
CONNECTING、CONNECTED、RECONNECTING、RECONNECTED、CLOSE

一旦客戶端開始創建Zookeeper對象,那麼客戶端狀態就會變成CONNECTING狀態,同時客戶端開始嘗試連接服務端,連接成功後,客戶端狀態變爲CONNECTED,通常情況下,由於斷網或其他原因,客戶端與服務端之間會出現斷開情況,一旦碰到這種情況,Zookeeper客戶端會自動進行重連服務,同時客戶端狀態再次變成CONNCTING,直到重新連上服務端後,狀態又變爲CONNECTED,在通常情況下,客戶端的狀態總是介於CONNECTING和CONNECTED之間。但是,如果出現諸如會話超時、權限檢查或是客戶端主動退出程序等情況,客戶端的狀態就會直接變更爲CLOSE狀態

zookeeper 數據模型

ZooKeeper的視圖結構和標準的Unix文件系統類似,其中每個節點稱爲“數據節點”或ZNode,每個znode可以存儲數據,還可以掛載子節點,因此可以稱之爲“樹”
第二點需要注意的是,每一個znode都必須有值,如果沒有值,節點是不能創建成功的。

在Zookeeper中,znode是一個跟Unix文件系統路徑相似的節點,可以往這個節點存儲或獲取數據
通過客戶端可對znode進行增刪改查的操作,還可以註冊watcher監控znode的變化。

zookeeper 節點類型

a、Znode有兩種類型:
短暫(ephemeral)  (create -e /app1/test1 “test1” 客戶端斷開連接zk刪除ephemeral類型節點) 
持久(persistent) (create -s /app1/test2 “test2” 客戶端斷開連接zk不刪除persistent類型節點)

b、Znode有四種形式的目錄節點(默認是persistent )
PERSISTENT 
PERSISTENT_SEQUENTIAL(持久序列/test0000000019 ) 
EPHEMERAL 
EPHEMERAL_SEQUENTIAL

c、創建znode時設置順序標識,znode名稱後會附加一個值,順序號是一個單調遞增的計數器,由父節點維護 
       
d、在分佈式系統中,順序號可以被用於爲所有的事件進行全局排序,這樣客戶端可以通過順序號推斷事件的順序

zookeeper 節點狀態屬性

czxid             節點被創建的zxid
mzxid             節點被修改的zxid
pzxid             子節點最後一次被修改的事務id
ctime			  節點被創建的時間
mtime			  子節點最後一次被修改的時間
version           節點被修改的版本號
cversion          子節點最後一次被修改的版本號
aversion          節點的ACL被修改的版本號
emphemeralOwner   臨時節點回話的ID
dataLength        節點數據長度
numChildren       節點的子節點個數

zookeeper ACL

ACL保障數據的安全
ACL機制,表示爲scheme:id:permissions,第一個字段表示採用哪一種機制,第二個id表示用戶,permissions表示相關權限(如只讀,讀寫,管理等)。

zookeeper提供瞭如下幾種機制(scheme):

world: 它下面只有一個id, 叫anyone, world:anyone代表任何人,zookeeper中對所有人有權限的結點就是屬於world:anyone的
auth: 它不需要id, 只要是通過authentication的user都有權限(zookeeper支持通過kerberos來進行authencation, 也支持username/password形式的authentication)
digest: 它對應的id爲username:BASE64(SHA1(password)),它需要先通過username:password形式的authentication
ip: 它對應的id爲客戶機的IP地址,設置的時候可以設置一個ip段,比如ip:192.168.1.0/16, 表示匹配前16個bit的IP段

Zookeeper的ACL(Access Control List),分爲三個維度:scheme、id、permission

通常表示爲:scheme:id:permission
schema:代表授權策略
id:代表用戶
permission:代表權限

Scheme
world:
	默認方式,相當於全世界都能訪問
auth:
	代表已經認證通過的用戶(可以通過addauth digest user:pwd 來添加授權用戶)
digest:
	即用戶名:密碼這種方式認證,這也是業務系統中最常用的
ip:
	使用Ip地址認證

id
id是驗證模式,不同的scheme,id的值也不一樣。

scheme爲auth時:
username:password
scheme爲digest時:
	username:BASE64(SHA1(password))
scheme爲ip時:
	客戶端的ip地址。
scheme爲world時
	anyone。

Permission
CREATE、READ、WRITE、DELETE、ADMIN 也就是 增、刪、改、查、管理權限,這5種權限簡寫爲crwda(即:每個單詞的首字符縮寫)
CREATE(c):創建子節點的權限 
DELETE(d):刪除節點的權限 
READ(r):讀取節點數據的權限 
WRITE(w):修改節點數據的權限 
ADMIN(a):設置子節點權限的權限
world
getAcl /testDir/testAcl   # 獲取該節點的acl權限信息,成功後,該節點就少了d權限
setAcl /testDir/testAcl world:anyone:crwa   # 設置該節點的acl權限

auth
addauth digest user1:123456                # 需要先添加一個用戶
setAcl /testDir/testAcl auth:user1:123456:crwa   # 然後纔可以拿着這個用戶去設置權限

digest
addauth digest user1:123456
setAcl /testDir/testDigest digest:user1:HYGa7IZRm2PUBFiFFu8xY2pPP/s=:crwa   # 使用digest來設置權限
通過明文獲得密文
shell> java -Djava.ext.dirs=/soft/zookeeper-3.4.12/lib -cp /soft/zookeeper-3.4.12/zookeeper-3.4.12.jar org.apache.zookeeper.server.auth.DigestAuthenticationProvider user1:123456
user1:123456->user1:ACFm5rWnnKn9K9RN/Oc8qEYGYDs=

ip
setAcl  /testDir/testIp ip:192.168.30.10:cdrwa

setAcl權限的時候由於失誤,導致節點無法刪除

create /enjoy1/node1  enjoy
setAcl /enjoy1  world:anyone:r

這個時候無論是delete 還是rmr都沒有權限刪除
 
解決方式:啓用super權限
使用DigestAuthenticationProvider.generateDigest("super:admin"); 獲得密碼
修改zkServer啓動腳本增加
"-Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBvst5y6rkB6HQs="
啓動客戶端用管理員登陸
addauth digest super:admin

zookeeper 常用四字命令

ZooKeeper 支持某些特定的四字命令字母與其的交互。用來獲取 ZooKeeper 服務的當前狀態及相關信息。可通過 telnet 或 nc 向 ZooKeeper 提交相應的命令 :

當然,前提是安裝好了nc

echo stat|nc 127.0.0.1 2181 來查看哪個節點被選擇作爲follower或者leader ·
使用echo ruok|nc 127.0.0.1 2181 測試是否啓動了該Server,若回覆imok表示已經啓動。 · 

echo dump | nc 127.0.0.1 2181 ,列出未經處理的會話和臨時節點。 · 
echo kill | nc 127.0.0.1 2181 ,關掉server · 
echo conf | nc 127.0.0.1 2181 ,輸出相關服務配置的詳細信息。 · 
echo cons | nc 127.0.0.1 2181 ,列出所有連接到服務器的客戶端的完全的連接 / 會話的詳細信息 · 
echo envi | nc 127.0.0.1 2181 ,輸出關於服務環境的詳細信息(區別於 conf 命令)。 · 
echo reqs | nc 127.0.0.1 2181 ,列出未經處理的請求。 · 
echo wchs | nc 127.0.0.1 2181 ,列出服務器 watch 的詳細信息。 · 
echo wchc | nc 127.0.0.1 2181 ,通過 session 列出服務器 watch 的詳細信息,它的輸出是一個與 watch 相關的會話的列表。 · 
echo wchp | nc 127.0.0.1 2181 ,通過路徑列出服務器 watch 的詳細信息。它輸出一個與 session 相關的路徑。

zookeeper 日誌可視化

前面以及講了兩個非常重要的配置一個是dataDir,存放的快照數據,一個是dataLogDir,存放的是事務日誌文件

java -cp /soft/zookeeper-3.4.12/zookeeper-3.4.12.jar:/soft/zookeeper-3.4.12/lib/slf4j-api-1.7.25.jar org.apache.zookeeper.server.LogFormatter log.1

java -cp /soft/zookeeper-3.4.12/zookeeper-3.4.12.jar:/soft/zookeeper-3.4.12/lib/slf4j-api-1.7.25.jar org.apache.zookeeper.server.SnapshotFormatter log.1

ZK集羣解析

Zookeeper集羣特點

順序一致性
客戶端的更新順序與它們被髮送的順序相一致。

原子性
更新操作要麼成功要麼失敗,沒有第三種結果。

單一視圖
無論客戶端連接到哪一個服務器,客戶端將看到相同的 ZooKeeper 視圖。

可靠性
一旦一個更新操作被應用,那麼在客戶端再次更新它之前,它的值將不會改變。

實時性
連接上一個服務端數據修改,所以其他的服務端都會實時的跟新,不算完全的實時,有一點延時的

角色輪換避免單點故障
當leader出現問題的時候,會選舉從follower中選舉一個新的leader

集羣中的角色

Leader  集羣工作機制中的核心
		事務請求的唯一調度和處理者,保證集羣事務處理的順序性
		集羣內部個服務器的調度者(管理follower,數據同步)

Follower  集羣工作機制中的跟隨者
    	處理非事務請求,轉發事務請求給Leader
		參與事務請求proposal投票
		參與leader選舉投票

Observer 觀察者  
	3.30以上版本提供,和follower功能相同,但不參與任何形式投票
	處理非事務請求,轉發事務請求給Leader
	提高集羣非事務處理能力

Zookeeper集羣配置

修改zoo_sample.cfg文件

dataDir=/usr/local/zookeeper/data
同時創建data目錄 
mkdir /usr/local/zookeeper/data 
vim /usr/local/zookeeper/data/myid(0,1,2,.....)

#集羣配置(主機:心跳端口:數據端口)
server.0=xxx.xxx.xxx.xxx:2888:3888
server.1=xxx.xxx.xxx.xxx:2888:3888
server.2=xxx.xxx.xxx.xxx:2888:3888

Java客戶端連接集羣

ZK連接集羣很簡單,只需要把連接地址用逗號分隔就好。

ZkClient client = new ZkClient("host1,host2,host3")

典型應用場景

數據發佈與訂閱(配置中心)

集羣管理(服務註冊於發現)

分佈式鎖

基於同名節點的分佈式鎖

高性能分佈式鎖

Master選舉

命名服務

ZK使用注意事項

Zk數據與日誌清理
  dataDir目錄、dataLogDir兩個目錄會隨着時間推移變得龐大,容易造成硬盤滿了,
  清理辦法: 自己編寫shell腳本,保留最新的n個文件
  			使用zk自帶的zkClient.sh保留最新的n個文件,zkClient.sh –n 15
  配置autopurge.snapRetainCount和autopurge.purgeInterval兩個參數配合使用;

Too many connections
  配置maxClientCnxns參數,配置單個客戶端機器創建的最大連接數;

磁盤管理
  磁盤的I/O性能直接制約zookeeper更新操作速度,爲了提高zk的寫性能建議:
  使用單獨的磁盤
  Jvm堆內存設置要小心

磁盤管理集羣數量
  集羣中機器的數量並不是越多越好,一個寫操作需要半數以上的節點ack,所以集羣節點數越多,整個集羣可以抗掛點的節點數越多(越可靠),但是吞吐量越差。集羣的數量必須爲奇數;

磁盤管理集羣數據
  zk是基於內存進行讀寫操作的,有時候會進行消息廣播,因此不建議在節點存取容量比較大的數據;

zookeeper Java客戶端框架

Zookeeper原生客戶端
ZkClient
Curator

zookeeper 面試

zk面試問題全解析
Zookeeper是什麼框架
應用場景
Paxos算法& Zookeeper使用協議
選舉算法和流程
Zookeeper有哪幾種節點類型
Zookeeper對節點的watch監聽通知是永久的嗎?
部署方式?集羣中的機器角色都有哪些?集羣最少要幾臺機器
集羣如果有3臺機器,掛掉一臺集羣還能工作嗎?掛掉兩臺呢?
集羣支持動態添加機器嗎?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章