Zookeeper vs Chubby

上一篇博客Chubby的鎖服務(wù)中已經(jīng)對(duì)Chubby的設(shè)計(jì)和實(shí)現(xiàn)做了比較詳細(xì)的實(shí)現(xiàn),但由于其閉源身份,工程中接觸比較多的還是它的一個(gè)非常類似的開源實(shí)現(xiàn)Zookeeper。Zookeeper作為后起之秀,應(yīng)該對(duì)Chubby有很多的借鑒,他們有眾多的相似之處,比如都可以提供分布式鎖的功能;都提供類似于UNIX文件系統(tǒng)的數(shù)據(jù)組織方式;都提供了事件通知機(jī)制Event或Watcher;都在普通節(jié)點(diǎn)的基礎(chǔ)上提供了臨時(shí)節(jié)點(diǎn)來(lái)滿足服務(wù)存活發(fā)現(xiàn)的功能;都以集群的方式提供服務(wù);都通過(guò)選舉產(chǎn)生Master并在集群間以Quorum的方式副本數(shù)據(jù)。但他們并不完全相同,并且Zookeeper還擁有后發(fā)優(yōu)勢(shì),本文將重點(diǎn)介紹他們之間的區(qū)別,并試著分析這些區(qū)別的原因以和結(jié)果。

區(qū)別根源

一個(gè)設(shè)計(jì)良好的系統(tǒng)應(yīng)該是圍繞并為其設(shè)計(jì)目標(biāo)服務(wù)的,因此通過(guò)對(duì)Chubby及Zookeeper的目標(biāo)比較或許能對(duì)其區(qū)別的本質(zhì)略窺一二:

  • Chubby:provide coarse-grained locking as well as reliable storage for a loosely-coupled distributed system.
  • Zookeeper:provide a simple and high performance kernel for building more complex coordination primitives at the client.

可以看出,Chubby旗幟鮮明的表示自己是為分布式鎖服務(wù)的,而Zookeeper則傾向于構(gòu)造一個(gè)“Kernel”,而利用這個(gè)“Kernel”客戶端可以自己實(shí)現(xiàn)眾多更復(fù)雜的分布式協(xié)調(diào)機(jī)制。自然的,Chubby傾向于提供更精準(zhǔn)明確的操作來(lái)免除使用者的負(fù)擔(dān),Zookeeper則需要提供更通用,更原子的原材料,留更多的空白和自由給Client。也正是因此,為了更適配到更廣的場(chǎng)景范圍,Zookeeper對(duì)性能的提出了更高的要求。

比較

圍繞上述思路,接下來(lái)將從一致性、分布式鎖的實(shí)現(xiàn)及使用、客戶端Cache等方面來(lái)對(duì)比他們的不同。

一致性

  • Chubby:線性一致性(Linearizability)
  • Zookeeper:寫操作線性(Linearizable writes) + 客戶端有序(FIFO client order)

Chubby所要實(shí)現(xiàn)的一致性是分布式系統(tǒng)中所能實(shí)現(xiàn)的最高級(jí)別的一致性,簡(jiǎn)單的說(shuō)就是每次操作時(shí)都可以看到其之前的所有成功操作按順序完成,而Zookeeper將一致性弱化為兩個(gè)保證,其中寫操作線性(Linearizable writes)指的是所有修改集群狀態(tài)的操作按順序完成,客戶端有序(FIFO client order)指對(duì)任意一個(gè)client來(lái)說(shuō),他所有的讀寫操作都是按順序完成。從實(shí)現(xiàn)上來(lái)看:

  • Chubby的所有讀寫請(qǐng)求都需要交給Leader串行執(zhí)行,并且Leader會(huì)用一致性協(xié)議復(fù)制到集群所有節(jié)點(diǎn)。
  • Zookeeper僅將寫操作交給Leader串行執(zhí)行,也就保證了寫操作線性。對(duì)于讀操作,則由與客戶端連接的Server自行處理,客戶端有序的保證也很簡(jiǎn)單,Zookeeper給每個(gè)寫入后的狀態(tài)一個(gè)唯一自增的Zxid,并通過(guò)寫請(qǐng)求的答復(fù)告知客戶端,客戶端之后的讀請(qǐng)求都會(huì)攜帶這個(gè)Zxid,直連的Server通過(guò)比較Zxid判斷自己是否滯后,如果是則讓讀操作等待。

對(duì)比Chubby及Zookeeper的一致性保證可以看出,Zookeeper損失的是不同客戶端的讀寫操作的一致性,如下圖所示:

損失一致性

Zookeeper集群的初始狀態(tài)為x;Client A發(fā)起寫操作將狀態(tài)修改為y,寫操作由于寫操作線性的保證轉(zhuǎn)發(fā)給Leader通過(guò)一致性協(xié)議復(fù)制到整個(gè)集群,過(guò)半數(shù)節(jié)點(diǎn)成功后返回成功;此時(shí)ClientB讀還未同步到的Server,獲得x。這種一致性的損失,換來(lái)的是集群讀請(qǐng)求的高性能。對(duì)于不能容忍這種不一致的場(chǎng)景,Zookeeper提供兩種機(jī)制滿足:

  • Watcher通知跟Read操作一樣是由客戶端鎖連接Server本地處理的,所以Client B收到對(duì)應(yīng)的事件通知后再Read就一定能看到最新的狀態(tài)y;
  • 由于客戶端有序的保證,Client B可以在Read操作前加一條Write操作,來(lái)保證看到最新狀態(tài),為了避免這個(gè)不必要的Write操作Zookeeper提供Sync命令,相當(dāng)于一條空的寫操作。

這也符合Zookeeper的設(shè)計(jì)思路:提供更高效更原子的操作,通過(guò)這些操作客戶端可以自行組裝滿足各種需求,即便是對(duì)一致性要求更高的需求。

分布式鎖

上一篇博客Chubby和鎖服務(wù)中已經(jīng)分析了Chubby的分布式鎖的設(shè)計(jì)實(shí)現(xiàn),分布式鎖從實(shí)現(xiàn)到使用認(rèn)為可以分為一致性協(xié)議,鎖的實(shí)現(xiàn)和鎖的使用三個(gè)部分,相對(duì)于Chubby,Zookeeper傾向于實(shí)現(xiàn)更少的部分,而將更多的選擇交給用戶:

  • Chubby:提供準(zhǔn)確語(yǔ)義的Lock,Release操作,內(nèi)部完成了一致性協(xié)議,鎖的實(shí)現(xiàn)的內(nèi)容,僅將鎖的使用部分留給用戶;
  • Zookeeper:并沒有提供加鎖放鎖操作,用戶需要利用Zookeeper提供的基礎(chǔ)操作,完成鎖的實(shí)現(xiàn)和鎖的使用部分的內(nèi)容,如下圖所示:
分布式鎖

因?yàn)槿绱?,用戶在使用Zookeeper來(lái)獲得鎖功能的時(shí)候會(huì)稍顯復(fù)雜,以讀寫所為例,Chubby可以通過(guò)接口直接使用,而Zookeeper需要的操作如下:

Write Lock
1 n = create(l + “/write-”, EPHEMERAL|SEQUENTIAL) 
2 C = getChildren(l, false)
3 if n is lowest znode in C, exit
4 p = znode in C ordered just before n
5 if exists(p, true) wait for event 
6 goto 2

Read Lock
1 n = create(l + “/read-”, EPHEMERAL|SEQUENTIAL)
2 C = getChildren(l, false)
3 if no write znodes lower than n in C, exit
4 p = write znode in C ordered just before n
5 if exists(p, true) wait for event
6 goto 3

用戶需要在某個(gè)ZNode下創(chuàng)建代表自己的臨時(shí)子節(jié)點(diǎn)來(lái)?yè)寣戞i,同時(shí)這個(gè)子節(jié)點(diǎn)有一個(gè)自增的編號(hào),編號(hào)最小的節(jié)點(diǎn)獲得寫鎖,其他節(jié)點(diǎn)關(guān)注其前一個(gè)ZNode的存在,如果消失會(huì)收到watcher通知,之后繼續(xù)嘗試加寫鎖;讀鎖稍寬松,只要沒有比自己編號(hào)更小的寫節(jié)點(diǎn)就可以加讀鎖成功。

客戶端Cache

  • Chubby:內(nèi)部維護(hù),一致性cache;
  • Zookeeper:Client自己實(shí)現(xiàn),通過(guò)watcher控制;

Chubby和鎖服務(wù)介紹過(guò),Chubby通過(guò)Server和客戶端Lib的配合在內(nèi)部維護(hù)了完整的客戶端緩存功能,并且這個(gè)客戶端緩存是一致性的,這就極大的簡(jiǎn)化了用戶的使用成本,因?yàn)橛脩舾静恍枰繡ache的存在。相對(duì)應(yīng),Zookeeper根本沒有實(shí)現(xiàn)Cache功能,用戶如果需要必須自己實(shí)現(xiàn),利用watcher機(jī)制,用戶能方便的按自己需求實(shí)現(xiàn)一致或不一致的Cache語(yǔ)義。

API

比較Chubby和Zookeeper的API設(shè)計(jì)可以看出Zookeeper圍繞自己設(shè)計(jì)目標(biāo)的接口設(shè)計(jì):

  • Zookeeper取消Handle,因此省略了Open,Close接口,這就要求所有對(duì)ZNode的訪問都需要提供完整的Path。這樣是很合理的,因?yàn)閆ookeeper定位提供基礎(chǔ)接口,那么上層使用時(shí)很有可能是需要很多個(gè)ZNode配合完成的,從上面介紹的鎖的實(shí)現(xiàn)便可以看出,這樣一來(lái)維護(hù)多個(gè)Handle反而造成了使用負(fù)擔(dān);
  • Zookeeper沒有提供Lock,Release等精確語(yǔ)義的鎖操作;
  • Zookeeper提供Sync操作來(lái)滿足對(duì)更高的一致性要求的場(chǎng)景。

總結(jié)

通過(guò)上面的分析可以看出Chubby和Zookeeper設(shè)計(jì)定位的區(qū)別,以及為了各自目標(biāo)作出的設(shè)計(jì)實(shí)現(xiàn)的努力。Chubby追求使用簡(jiǎn)單,Zookeeper追求使用自由,簡(jiǎn)單就一定有更多的限制,自由就一定更多的使用成本,究竟孰好孰壞,就是個(gè)見仁見智的問題了。其實(shí)類似的權(quán)衡在計(jì)算機(jī)科學(xué)中是非常常見,比如庫(kù)或框架的設(shè)計(jì),比如高級(jí)語(yǔ)言的語(yǔ)法設(shè)計(jì)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容