1 前言
談到分布式應(yīng)用沪曙,就離不開(kāi)ZooKeeper痘括,那么ZooKeeper是怎么來(lái)的歇竟,它又是做什么的挥唠?通過(guò)這篇文章,希望大家最ZooKeeper有個(gè)基本的了解焕议。
本篇文章主要介紹ZooKeeper的基本概念及其在并發(fā)情況下的讀寫(xiě)流程分析宝磨,希望能對(duì)大家有所幫助!
2 ZooKeeper簡(jiǎn)介
2.1 背景
眾所周知,分布式應(yīng)用程序都需要一個(gè)協(xié)調(diào)服務(wù)唤锉,那么為什么分布式應(yīng)用程序需要協(xié)調(diào)服務(wù)呢世囊?因?yàn)榉植际綉?yīng)用程序是分布在多臺(tái)主機(jī)上面的,分布在多臺(tái)主機(jī)上面的應(yīng)用要想共同地去很好地完成任務(wù)窿祥,當(dāng)然得需要一個(gè)協(xié)調(diào)者了株憾,ZooKeeper就是這樣一個(gè)協(xié)調(diào)者。其實(shí)分布式應(yīng)用程序就跟團(tuán)隊(duì)一樣晒衩,團(tuán)隊(duì)要想高效的完成任務(wù)嗤瞎,當(dāng)然需要一個(gè)協(xié)調(diào)者去協(xié)調(diào)各項(xiàng)工作了,這個(gè)協(xié)調(diào)者就是團(tuán)隊(duì)Leader啦浸遗。
我們都知道協(xié)調(diào)者不是這么好當(dāng)?shù)拿ㄐ玻瑢?duì)于分布式應(yīng)用程序來(lái)說(shuō)也是如此箱亿,協(xié)調(diào)服務(wù)很容易出現(xiàn)競(jìng)態(tài)條件跛锌、死鎖等問(wèn)題。為了減少分布式應(yīng)用程序開(kāi)發(fā)協(xié)調(diào)服務(wù)的成本届惋,所以就誕生了ZooKeeper——開(kāi)源的分布式協(xié)調(diào)服務(wù)髓帽。
2.2 基本概念
ZooKeeper 是一個(gè)開(kāi)源的分布式協(xié)調(diào)服務(wù),由雅虎創(chuàng)建脑豹,是 Google Chubby 的開(kāi)源實(shí)現(xiàn)郑藏。分布式應(yīng)用程序可以基于 ZooKeeper 實(shí)現(xiàn)諸如數(shù)據(jù)發(fā)布/訂閱、命名服務(wù)瘩欺、分布式協(xié)調(diào)/通知必盖、集群管理、配置維護(hù)俱饿、分布式鎖等功能歌粥。
2.3 特點(diǎn)
1、簡(jiǎn)單
分布式應(yīng)用程序可以通過(guò)一個(gè)共享的層級(jí)命名空間(類似標(biāo)準(zhǔn)的文件系統(tǒng))來(lái)進(jìn)行協(xié)調(diào)拍埠,該層級(jí)命名空間由數(shù)據(jù)節(jié)點(diǎn)構(gòu)成——在ZooKeeper中我們稱它為znode失驶,znode類似標(biāo)準(zhǔn)文件系統(tǒng)中的文件或是目錄。不同于標(biāo)準(zhǔn)文件系統(tǒng)枣购,ZooKeeper中的數(shù)據(jù)是存在在內(nèi)存中的嬉探,所以ZooKeeper可以實(shí)現(xiàn)高吞吐量和低延遲。
2棉圈、基于復(fù)制
ZooKeeper集群中的server是互相復(fù)制的涩堤,所以集群中的每個(gè)server數(shù)據(jù)都是一樣的,正因如此分瘾,我們可以通過(guò)任意server來(lái)讀取數(shù)據(jù)胎围。
集群中的server必須能夠互相感知,它們擁有相同的狀態(tài)∪叮客戶端可以連接任意server垮抗,然后與server保持著TCP連接,通過(guò)此連接可以發(fā)送請(qǐng)求碧聪、獲得響應(yīng)冒版,當(dāng)此連接斷掉的時(shí)候,客戶端會(huì)重新連接一個(gè)不同的server逞姿。
集群中每一個(gè)server都可以服務(wù)客戶端辞嗡,讀請(qǐng)求通過(guò)每個(gè)server的本地?cái)?shù)據(jù)副本來(lái)提供,寫(xiě)請(qǐng)求則由ZooKeeper協(xié)議來(lái)處理滞造。作為協(xié)議的一部分续室,所有的寫(xiě)請(qǐng)求都會(huì)被轉(zhuǎn)發(fā)到集群中一個(gè)叫做Leader的節(jié)點(diǎn)來(lái)處理,集群中的其余節(jié)點(diǎn)則稱為Follower谒养,F(xiàn)ollower用來(lái)接收并處理來(lái)自Leader的提案挺狰。Leader宕機(jī)重新選舉與Follower與Leader的同步也都是此協(xié)議的內(nèi)容,感興趣可以搜索ZooKeeper zab協(xié)議進(jìn)一步了解买窟。
3丰泊、有序性
ZooKeeper通過(guò)為每一個(gè)更新操作編號(hào)來(lái)保證事務(wù)有序性。
4始绍、快速
ZooKeeper在讀多寫(xiě)少的場(chǎng)景中瞳购,擁有極快的速度。
2.4 數(shù)據(jù)模型
ZooKeeper的數(shù)據(jù)模型是層次型亏推,類似文件系統(tǒng)学赛。
每個(gè)數(shù)據(jù)節(jié)點(diǎn),在ZooKeeper中叫做znode吞杭,并且其有一個(gè)唯一的路徑標(biāo)識(shí)盏浇,znode既可以包含數(shù)據(jù)也可以包含子節(jié)點(diǎn),好比文件系統(tǒng)中允許文件也作為目錄一樣篇亭。znode中數(shù)據(jù)的讀寫(xiě)都是原子的缠捌。
ZooKeeper中也有臨時(shí)節(jié)點(diǎn)的概念,只要?jiǎng)?chuàng)建臨時(shí)節(jié)點(diǎn)的會(huì)話存在译蒂,該節(jié)點(diǎn)就存在曼月,會(huì)話一結(jié)束,那么該節(jié)點(diǎn)就會(huì)被刪除柔昼。
2.5 ZooKeeper的一些保證
作為構(gòu)建復(fù)雜分布式服務(wù)的基礎(chǔ)哑芹,ZooKeeper提供了一些保證,利用這些保證捕透,我們可以保證應(yīng)用的正確性:
- 順序一致性:來(lái)自同一客戶端的更新將按順序進(jìn)行聪姿。
- 原子性:更新操作要么成功要么失敗碴萧,不存在中間狀態(tài)。
- 單系統(tǒng)映像:不論連接到哪個(gè)服務(wù)器末购,客戶端都會(huì)看到相同的視圖破喻,因?yàn)閆ooKeeper是基于復(fù)制的嘛。
- 可靠性:更新操作成功后盟榴,znode狀態(tài)會(huì)一直持續(xù)到下次更新操作曹质,在此期間,狀態(tài)不變擎场。
- 及時(shí)性:客戶端會(huì)及時(shí)獲取ZooKeeper最新?tīng)顟B(tài)羽德。
3 ZooKeeper的讀寫(xiě)流程分析
在了解了ZooKeeper的基本概念后,我們來(lái)詳細(xì)看下ZooKeeper的讀寫(xiě)流程迅办,以及ZooKeeper在并發(fā)情況下的讀寫(xiě)控制宅静。以求對(duì)ZooKeeper有進(jìn)一步的了解。
3.1 讀流程分析
讀流程如下圖所示:
因?yàn)閆ooKeeper集群中所有的server節(jié)點(diǎn)都擁有相同的數(shù)據(jù)站欺,所以讀的時(shí)候可以在任意一臺(tái)server節(jié)點(diǎn)上姨夹,客戶端連接到集群中某一節(jié)點(diǎn),讀請(qǐng)求镊绪,然后直接返回匀伏。當(dāng)然因?yàn)閆ooKeeper協(xié)議的原因(一半以上的server節(jié)點(diǎn)都成功寫(xiě)入了數(shù)據(jù),這次寫(xiě)請(qǐng)求便算是成功)蝴韭,讀數(shù)據(jù)的時(shí)候可能會(huì)讀到數(shù)據(jù)不是最新的server節(jié)點(diǎn),所以比較推薦使用watch機(jī)制熙侍,在數(shù)據(jù)改變時(shí)榄鉴,及時(shí)感應(yīng)到。
3.2 寫(xiě)流程分析
寫(xiě)流程如下圖所示:
當(dāng)一個(gè)客戶端進(jìn)行寫(xiě)數(shù)據(jù)請(qǐng)求時(shí)蛉抓,會(huì)指定ZooKeeper集群中的一個(gè)server節(jié)點(diǎn)庆尘,如果該節(jié)點(diǎn)為Follower,則該節(jié)點(diǎn)會(huì)把寫(xiě)請(qǐng)求轉(zhuǎn)發(fā)給Leader巷送,Leader通過(guò)內(nèi)部的協(xié)議進(jìn)行原子廣播驶忌,直到一半以上的server節(jié)點(diǎn)都成功寫(xiě)入了數(shù)據(jù),這次寫(xiě)請(qǐng)求便算是成功笑跛,然后Leader便會(huì)通知相應(yīng)Follower節(jié)點(diǎn)寫(xiě)請(qǐng)求成功付魔,該節(jié)點(diǎn)向client返回寫(xiě)入成功響應(yīng)。
3.3 ZooKeeper并發(fā)讀寫(xiě)情況分析
我們已經(jīng)知道ZooKeeper的數(shù)據(jù)模型是層次型飞蹂,類似文件系統(tǒng)几苍,不過(guò)ZooKeeper的設(shè)計(jì)目標(biāo)定位是簡(jiǎn)單、高可靠陈哑、高吞吐妻坝、低延遲的內(nèi)存型存儲(chǔ)系統(tǒng)伸眶,因此它的value不像文件系統(tǒng)那樣適合保存大的值,官方建議保存的value大小要小于1M刽宪,key為路徑厘贼。
每個(gè)數(shù)據(jù)節(jié)點(diǎn)在ZooKeeper中叫做znode,并且其有一個(gè)唯一的路徑標(biāo)識(shí)圣拄,znode節(jié)點(diǎn)可以包含數(shù)據(jù)和子節(jié)點(diǎn)涂臣。
ZooKeeper的層次模型是通過(guò)ConcurrentHashMap實(shí)現(xiàn)的,key為path售担,value為DataNode赁遗,DataNode保存了znode中的value、children族铆、 stat等信息岩四。
ZooKeeper的層次模型是通過(guò)ConcurrentHashMap實(shí)現(xiàn)的,而ConcurrentHashMap是線程安全的Hash Table哥攘,它采用了鎖分段技術(shù)來(lái)減少鎖競(jìng)爭(zhēng)剖煌,提高性能的同時(shí)又保證了并發(fā)安全,其結(jié)構(gòu)如下圖所示:
ConcurrentHashMap由兩部分組成逝淹,Segment和HashEntry耕姊,鎖的粒度是Segment,每個(gè)Segment 對(duì)象包含整個(gè)散列映射表的若干個(gè)桶栅葡,散列沖突時(shí)通過(guò)鏈表來(lái)解決茉兰。
因?yàn)椴迦腈I / 值對(duì)操作只是在 Segment 包含的某個(gè)桶中完成,所以這里的加鎖操作是針對(duì)(鍵的 hash 值對(duì)應(yīng)的)某個(gè)具體的 Segment欣簇,不需要鎖定整個(gè)ConcurrentHashMap规脸,所以對(duì)于ConcurrentHashMap,可以進(jìn)行并發(fā)的寫(xiě)操作熊咽,只要寫(xiě)入的Segment不同莫鸭。而所有的讀線程幾乎不會(huì)因?yàn)閷?xiě)操作的加鎖而阻塞(除非讀線程剛好讀到這個(gè) Segment 中某個(gè) HashEntry 的 value 域的值為 null,此時(shí)需要加鎖后重新讀取該值横殴。這便是鎖分段技術(shù)被因,保證并發(fā)安全的情況下又提高了性能。
對(duì)于ZooKeeper來(lái)講衫仑,ZooKeeper的寫(xiě)請(qǐng)求由Leader處理梨与,Leader能夠保證并發(fā)寫(xiě)入的有序性,即同一時(shí)刻惑畴,只有一個(gè)寫(xiě)操作被批準(zhǔn)蛋欣,然后對(duì)該寫(xiě)操作進(jìn)行全局編號(hào),最后進(jìn)行原子廣播寫(xiě)入如贷,所以ZooKeeper的并發(fā)寫(xiě)請(qǐng)求是順序處理的陷虎,而底層又是用了ConcurrentHashMap到踏,理所當(dāng)然寫(xiě)請(qǐng)求是線程安全的。而對(duì)于并發(fā)讀請(qǐng)求尚猿,同理窝稿,因?yàn)橛昧薈oncurrentHashMap,當(dāng)然也是線程安全的了凿掂“槔疲總結(jié)來(lái)說(shuō),ZooKeeper的并發(fā)讀寫(xiě)是線程安全的庄萎。
但是對(duì)于ZooKeeper的客戶端來(lái)講踪少,如果使用了watch機(jī)制,在進(jìn)行了讀請(qǐng)求但是watch znode前這段時(shí)間中糠涛,如果znode的數(shù)據(jù)變化了援奢,客戶端是無(wú)法感知到的,這段時(shí)間客戶端的數(shù)據(jù)就有一定的滯后性了忍捡,只有當(dāng)下次數(shù)據(jù)變化后集漾,客戶端才能感知到,所以對(duì)于客戶端來(lái)說(shuō)砸脊,數(shù)據(jù)是最終一致性具篇。
4 總結(jié)
通過(guò)上述閱讀,相信大家對(duì)ZooKeeper的基本概念與讀寫(xiě)流程都有了一定的了解凌埂。這篇文章內(nèi)容不算多驱显,但卻花了我不少時(shí)間,主要時(shí)間花在了對(duì)知識(shí)侨舆、概念正確性的考察上面秒紧,盡力避免因?yàn)槲业睦斫忮e(cuò)誤而誤導(dǎo)大家。最后挨下,文章有什么不正確的地方,感謝大家的指出脐湾,如果文章對(duì)你有幫助臭笆,也歡迎點(diǎn)贊。
5 參考資料
[1] ZooKeeper官方文檔資料. http://zookeeper.apache.org/doc/current/zookeeperOver.html.
[2] zookeeper的原理和應(yīng)用場(chǎng)景. http://www.reibang.com/p/b48d50e1fcb1.
[3] 探索 ConcurrentHashMap 高并發(fā)性的實(shí)現(xiàn)機(jī)制. https://www.ibm.com/developerworks/cn/java/java-lo-concurrenthashmap/.
6 寫(xiě)在最后
聊技術(shù)秤掌,不止于技術(shù)愁铺。
歡迎大家關(guān)注我的個(gè)人公眾號(hào):WU雙,在這里我會(huì)與大家分享技術(shù)文章闻鉴、管理知識(shí)以及個(gè)人的一些思想感悟茵乱。