<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ZooKeeper系列文章:ZooKeeper 源碼和實(shí)踐揭秘(一)

          共 10641字,需瀏覽 22分鐘

           ·

          2021-11-18 22:24


          導(dǎo)語(yǔ)


          ZooKeeper 是個(gè)針對(duì)大型分布式系統(tǒng)的高可用、高性能且具有一致性的開(kāi)源協(xié)調(diào)服務(wù),被廣泛的使用。對(duì)于開(kāi)發(fā)人員,ZooKeeper 是一個(gè)學(xué)習(xí)和實(shí)踐分布式組件的不錯(cuò)的選擇。本文對(duì) ZooKeeper 的源碼進(jìn)行簡(jiǎn)析,也會(huì)介紹 ZooKeeper 實(shí)踐經(jīng)驗(yàn),希望能幫助到 ZooKeeper 初學(xué)者?。文章部分內(nèi)容參考了一些網(wǎng)絡(luò)文章,已標(biāo)注在末尾參考文獻(xiàn)中。


          1. 寫(xiě)文初衷


          在業(yè)務(wù)中使用了 ZooKeeper 作為消息系統(tǒng),在開(kāi)發(fā)和運(yùn)維過(guò)程中,也遇到一些問(wèn)題,萌發(fā)了閱讀源碼窺視實(shí)現(xiàn)細(xì)節(jié)的想法。同時(shí)我們運(yùn)維的 ZooKeeper 集群規(guī)模和數(shù)據(jù)規(guī)模非常大,也想把運(yùn)維的經(jīng)驗(yàn)分享出來(lái)供參考去規(guī)避風(fēng)險(xiǎn)點(diǎn)和性能調(diào)優(yōu)。


          2.目標(biāo)讀者


          本文是介紹 ZooKeeper 基礎(chǔ)知識(shí)和源碼分析的入門(mén)級(jí)材料,適合用于初步進(jìn)入分布式系統(tǒng)的開(kāi)發(fā)人員,以及使用 ZooKeeper 進(jìn)行生產(chǎn)經(jīng)營(yíng)的應(yīng)用程序運(yùn)維人員。


          Zookeeper系列文章介紹


          第 1 篇:主要介紹 ZooKeeper 使命、地位、基礎(chǔ)的概念和基本組成模塊,以及 ZooKeeper 內(nèi)部運(yùn)行原理,此部分主要從書(shū)籍《ZooKeeper 分布式過(guò)程協(xié)同技術(shù)詳解》摘錄,對(duì)于有 ZooKeeper 基礎(chǔ)的可以略過(guò)。堅(jiān)持主要目的,不先陷入解析源碼的繁瑣的實(shí)現(xiàn)上,而是從系統(tǒng)和底層看 ZooKeeper 如何運(yùn)行,通過(guò)從高層次介紹其所使用的協(xié)議,以及 ZooKeeper 所采用的在提高性能的同時(shí)還具備容錯(cuò)能力的機(jī)制。


          第 2 章節(jié):簡(jiǎn)析 ZooKeeper 的源碼實(shí)現(xiàn),主要目的去介紹 ZooKeeper 集群的工作流程,給出看源碼的簡(jiǎn)要指引,能更快上手去深入閱讀源碼


          第 3 章節(jié):主要介紹業(yè)務(wù)用 zookeeper 做消息系統(tǒng)的實(shí)踐,在實(shí)踐中的優(yōu)化點(diǎn)和踩坑的地方,由于業(yè)務(wù)場(chǎng)景和規(guī)模的差別,關(guān)注點(diǎn)和優(yōu)化點(diǎn)也差別很大,也歡迎在評(píng)論區(qū)更新使用 ZooKeeper 共性問(wèn)題。



          ZooKeeper簡(jiǎn)介



          在大數(shù)據(jù)和云計(jì)算盛行的今天,應(yīng)用服務(wù)由很多個(gè)獨(dú)立的程序組成,這些獨(dú)立的程序則運(yùn)行在形形色色,千變?nèi)f化的一組計(jì)算機(jī)上,而如何讓一個(gè)應(yīng)用中的多個(gè)獨(dú)立的程序協(xié)同工作是一件非常困難的事情。而 ZooKeeper 就是一個(gè)分布式的,開(kāi)放源碼的分布式應(yīng)用程序協(xié)調(diào)服務(wù)。它使得應(yīng)用開(kāi)發(fā)人員可以更多的關(guān)注應(yīng)用本身的邏輯,而不是協(xié)同工作上。從系統(tǒng)設(shè)計(jì)看,ZooKeeper 從文件系統(tǒng) API 得到啟發(fā),提供一組簡(jiǎn)單的 API,使得開(kāi)發(fā)人員可以實(shí)現(xiàn)通用的協(xié)作任務(wù),例如選舉主節(jié)點(diǎn),管理組內(nèi)成員的關(guān)系,管理元數(shù)據(jù)等,同時(shí) ZooKeeper 的服務(wù)組件運(yùn)行在一組專用的服務(wù)器之上,也保證了高容錯(cuò)性和可擴(kuò)展性。


          本章節(jié)主要從 ZooKeeper 的使命、ZooKeeper 基礎(chǔ)、工業(yè)級(jí)案例,來(lái)簡(jiǎn)要介紹 ZooKeeper。


          ZooKeeper 的使命


          Apache ZooKeeper 的官方介紹,ZooKeeper is a distributed, open-source coordination service for distributed applications. It exposes a simple set of primitives that distributed applications can build upon to implement higher level services for synchronization, configuration maintenance, and groups and naming. It is designed to be easy to program,and uses a data model styled after the familiar directory tree structure of file systems. It runs in Java and has bindings for both Java and C.



          從上面的官方介紹看,ZooKeeper 主要的系統(tǒng)功能是在分布式系統(tǒng)中協(xié)作多個(gè)任務(wù)。例如,典型的主-從工作模式中,我們需要主節(jié)點(diǎn)和從節(jié)點(diǎn)進(jìn)行協(xié)作,在從節(jié)點(diǎn)處于空閑狀態(tài)時(shí)會(huì)通知主節(jié)點(diǎn)可以接受工作,于是主節(jié)點(diǎn)就會(huì)分配任務(wù)給從節(jié)點(diǎn),同時(shí)我們只想有一個(gè)主節(jié)點(diǎn),而很多進(jìn)程可能都想成為主節(jié)點(diǎn),這些操作都是要在多個(gè)任務(wù)中進(jìn)行協(xié)作。另外,協(xié)同并不總是采取像主節(jié)點(diǎn)選舉或者加鎖等同步原語(yǔ)的形式,配置元數(shù)據(jù)也是一個(gè)進(jìn)程通知其他進(jìn)程需要做什么的一種常用數(shù)據(jù),例如,在一個(gè)主-從系統(tǒng)中,從節(jié)點(diǎn)需要知道任務(wù)已經(jīng)分配給他們,即便在主節(jié)點(diǎn)發(fā)生崩潰的情況下,這些信息也需要有效。


          在 ZooKeeper 之前,一些系統(tǒng)也可以采用分布式鎖管理器或者分布式數(shù)據(jù)庫(kù)來(lái)實(shí)現(xiàn)協(xié)作,例如,用數(shù)據(jù)庫(kù),redis 實(shí)現(xiàn)分布式鎖。


          那么 ZooKeeper 改變了什么呢?ZooKeeper 的設(shè)計(jì)更專注于任務(wù)協(xié)作,它不提供任何鎖的接口或者通用的存儲(chǔ)數(shù)據(jù)的接口,也沒(méi)有強(qiáng)加任何特殊的同步原語(yǔ),而是提供一個(gè)更加敏捷健壯的分布協(xié)作方案,例如在主-從模型中,ZooKeeper 沒(méi)有為應(yīng)用實(shí)現(xiàn)主節(jié)點(diǎn)選舉,或者進(jìn)程存活與否的跟蹤功能,但是,ZooKeeper 提供了實(shí)現(xiàn)這些任務(wù)的工具,對(duì)于實(shí)現(xiàn)什么樣的協(xié)同任務(wù),有開(kāi)發(fā)人員自己決定。


          分布式系統(tǒng)中關(guān)鍵在于進(jìn)程通信,其有兩種選擇:直接通過(guò)網(wǎng)絡(luò)進(jìn)行信息交換,或者讀寫(xiě)某些共享存儲(chǔ)。對(duì)于 ZooKeeper 實(shí)現(xiàn)協(xié)作和同步原語(yǔ)本質(zhì)上是使用共享存儲(chǔ)模型,即開(kāi)發(fā)的應(yīng)用是連接到 ZooKeeper 服務(wù)器端的客戶端,他們連接到 ZooKeeper 服務(wù)器端進(jìn)行相關(guān)的操作,以來(lái)影響服務(wù)器端存儲(chǔ)的共享數(shù)據(jù),最終應(yīng)用間實(shí)現(xiàn)協(xié)作。


          ZooKeeper 不適合的場(chǎng)景


          整個(gè) ZooKeeper 的服務(wù)器集群管理著應(yīng)用協(xié)作的關(guān)鍵數(shù)據(jù),ZooKeeper 不適合用作海量的數(shù)據(jù)存儲(chǔ),對(duì)于需要海量的應(yīng)用數(shù)據(jù)的情況,可以使用數(shù)據(jù)庫(kù)和分布式文件系統(tǒng),所以在設(shè)計(jì)應(yīng)用時(shí),最佳實(shí)踐是把應(yīng)用數(shù)據(jù)和協(xié)同數(shù)據(jù)獨(dú)立分開(kāi)。


          ZooKeeper基礎(chǔ)簡(jiǎn)介



          本小節(jié)簡(jiǎn)要介紹 ZooKeeper 數(shù)據(jù)結(jié)構(gòu)、監(jiān)控與通知、服務(wù)架構(gòu),詳細(xì)的介紹請(qǐng)查看 ZooKeeper 技術(shù)文檔和書(shū)籍。


          1. ZooKeeper 數(shù)據(jù)結(jié)構(gòu)


          ZooKeeper 采用類似于文件系統(tǒng)的層級(jí)樹(shù)狀結(jié)構(gòu)進(jìn)行管理 Znode,并且暴露操作 API 接口。


          ZooKeeper數(shù)據(jù)樹(shù)結(jié)構(gòu)


          Znode 的節(jié)點(diǎn)類型:在新建 znode 節(jié)點(diǎn),需要指定該節(jié)點(diǎn)的類型,不同的類型決定了 znode 節(jié)點(diǎn)的行為方式,znode 的類型分為持久節(jié)點(diǎn)、時(shí)節(jié)點(diǎn)、有序節(jié)點(diǎn),組合 4 中類型,持久的,臨時(shí)的,持久有序的,臨時(shí)有序的。對(duì)于持久節(jié)點(diǎn),只能主動(dòng)調(diào)用 delete 來(lái)刪除,而臨時(shí)的 znode,在當(dāng)創(chuàng)建該節(jié)點(diǎn)的客戶端崩潰或者關(guān)閉了與 ZooKeeper 的連接時(shí),這個(gè)節(jié)點(diǎn)就會(huì)被刪除。一般持久類型的 znode 為應(yīng)用保存數(shù)據(jù),即使 znode 的創(chuàng)建者不再屬于應(yīng)用系統(tǒng)時(shí),數(shù)據(jù)會(huì)保存下來(lái)而不丟失。臨時(shí) Znode 僅當(dāng)創(chuàng)建者的會(huì)話有效時(shí)這些信息必須有效保存,會(huì)話超時(shí)或者主動(dòng)關(guān)閉時(shí),臨時(shí) znode 會(huì)自動(dòng)消失。有序 Znode 節(jié)點(diǎn)是被分配唯一一個(gè)單調(diào)遞增的整數(shù)。


          2. API 接口


          create /path data 創(chuàng)建一個(gè)名為/path的znode節(jié)點(diǎn),并包含數(shù)據(jù)data。delete /path 刪除名為/path的znode。exists /path 檢查是否存在名為/path的節(jié)點(diǎn)。setData /path datagetData /pathgetChildren /path


          需要注意的是,ZooKeeper 并不允許局部寫(xiě)入或讀取 znode 節(jié)點(diǎn)的數(shù)據(jù)。當(dāng)設(shè)置一個(gè) znode 節(jié)點(diǎn)的數(shù)據(jù)或讀取時(shí),znode 節(jié)點(diǎn)的內(nèi)容會(huì)被整個(gè)替換或者全部讀取進(jìn)來(lái),特別是 getChildren,如果是數(shù)據(jù)量比較大,會(huì)獲取大量的數(shù)據(jù)。


          3. ZooKeeper 監(jiān)視與通知


          ZooKeeper 客戶端獲得服務(wù)器的數(shù)據(jù)或者變化,不是通過(guò)輪詢的模式,而是基于通知的機(jī)制,客戶端向 ZooKeeper 服務(wù)器端注冊(cè)需要接收通知的 znode,通過(guò)對(duì) znode 設(shè)置監(jiān)視點(diǎn)來(lái)接收通知,需要強(qiáng)調(diào)的是監(jiān)視點(diǎn)是一個(gè)單次觸發(fā)的操作。


          4.?ZooKeeper 架構(gòu)

          ZooKeeper服務(wù)器和客戶端工作流程


          ZooKeeper 服務(wù)器端運(yùn)行于兩種模式下:獨(dú)立模式和仲裁模式。獨(dú)立服務(wù)器只有一個(gè)單獨(dú)的服務(wù)器,ZooKeeper 狀態(tài)無(wú)法復(fù)制。而在仲裁模式下,具有一組 ZooKeeper 服務(wù)器,稱為 ZooKeeper 集合,它們之間可以進(jìn)行狀態(tài)的復(fù)制,并同時(shí)服務(wù)客戶端的請(qǐng)求。不過(guò)服務(wù)器集合并不會(huì)讓客戶端等待每個(gè)服務(wù)器完成數(shù)據(jù)保存后再繼續(xù),而是在滿足仲裁數(shù)目的服務(wù)器保存或者同步了狀態(tài)就會(huì)返回給客戶端。在解決這一分布式數(shù)據(jù)一致性,ZooKeeper 采用 ZAB(ZooKeeper Atomic Broadcast)的一致性協(xié)議,關(guān)于 ZAB 協(xié)議后面會(huì)詳細(xì)的介紹。


          ZooKeeper 客戶端在服務(wù)器集群中執(zhí)行任何請(qǐng)求前必須先與服務(wù)器建立會(huì)話(session),客戶端提交給 ZooKeeper 的所有操作均關(guān)聯(lián)在一個(gè)會(huì)話上。客戶端初始化連接到集合中某個(gè)服務(wù)器或一個(gè)獨(dú)立的服務(wù)器,客戶端提供TCP 協(xié)議與服務(wù)器進(jìn)行連接并通信,但當(dāng)會(huì)話無(wú)法與當(dāng)前連接的服務(wù)器繼續(xù)通信時(shí),會(huì)話就可能轉(zhuǎn)移到另外一個(gè)服務(wù)器,ZooKeeper 客戶端透明地轉(zhuǎn)移一個(gè)會(huì)話到不同的服務(wù)器。需要指明的,會(huì)話提供了順序保障,同一個(gè)會(huì)話中的請(qǐng)求會(huì)以 FIFO(先進(jìn)先出)順序執(zhí)行。


          ZooKeeper 應(yīng)用案例


          Apache HBase

          HBase 是一個(gè)通常與 Hadoop 一起使用的數(shù)據(jù)存儲(chǔ)倉(cāng)庫(kù)。在 HBase 中,ZooKeeper 用于選舉一個(gè)集群內(nèi)的主節(jié)點(diǎn),以便跟蹤可用的服務(wù)器,并保持集群的元數(shù)據(jù)。


          Apache Kafka

          Kafka 是一個(gè)基于發(fā)布-訂閱模型的消息系統(tǒng)。其中 ZooKeeper 用于檢測(cè)崩潰,實(shí)現(xiàn)主題的發(fā)現(xiàn),并保持主題的生產(chǎn)和消費(fèi)狀態(tài)。


          Apache Solr

          Solr 是一個(gè)企業(yè)級(jí)的搜索平臺(tái),它使用 ZooKeeper 來(lái)存儲(chǔ)集群的元數(shù)據(jù),并協(xié)作更新這些元數(shù)據(jù)。

          ZooKeeper 應(yīng)該是 “The King Of Coordination for Big Data”!



          ZooKeeper 內(nèi)部實(shí)現(xiàn)原理


          本章節(jié)是介紹 ZooKeeper 內(nèi)部是如何運(yùn)行的,通過(guò)從高層次介紹其所使用的協(xié)議,以及 ZooKeeper 所采用的在提供高性能的同時(shí)還具有容錯(cuò)能力的機(jī)制。總體來(lái)說(shuō) ZooKeeper 運(yùn)行于一個(gè)集群環(huán)境中,選舉出某個(gè)服務(wù)器作為群首(Leader),其他服務(wù)器追隨群首(Follower)。群首作為中心處理所有對(duì) ZooKeeper 系統(tǒng)變更的請(qǐng)求,它就像一個(gè)定序器,建立了所有對(duì) ZooKeeper 狀態(tài)的更新的順序,追隨者接收群首所發(fā)出更新操作請(qǐng)求,并對(duì)這些請(qǐng)求進(jìn)行處理,以此來(lái)保障狀態(tài)更新操作不會(huì)發(fā)生碰撞。


          1. 請(qǐng)求、事務(wù)、標(biāo)識(shí)符


          ZooKeeper 服務(wù)器會(huì)在本地處理只讀請(qǐng)求(exists、getData、getChildren),例如一個(gè)服務(wù)器接收客戶端的 getData 請(qǐng)求,服務(wù)器讀取該狀態(tài)信息,并把這些信息返回給客戶端。


          那些會(huì)改變 ZooKeeper 狀態(tài)的客戶端請(qǐng)求(create,delete 和 setData)將會(huì)轉(zhuǎn)發(fā)到群首,群首執(zhí)行對(duì)應(yīng)的請(qǐng)求,并形成狀態(tài)的更新,稱為事務(wù)(transaction),其中事務(wù)要以原子方式執(zhí)行。同時(shí),一個(gè)事務(wù)還要具有冪等性,事務(wù)的冪等性在我們進(jìn)行恢復(fù)處理時(shí)更加簡(jiǎn)單,后面我們可以看到如何利用冪等性進(jìn)行數(shù)據(jù)恢復(fù)或者災(zāi)備。


          在群首產(chǎn)生了一個(gè)事務(wù),就會(huì)為該事務(wù)分配一個(gè)標(biāo)識(shí)符,稱為會(huì)話 id(zxid),通過(guò) Zxid 對(duì)事務(wù)進(jìn)行標(biāo)識(shí),就可以按照群首所指定的順序在各個(gè)服務(wù)器中按序執(zhí)行。服務(wù)器之間在進(jìn)行新的群首選舉時(shí)也會(huì)交換 zxid 信息,這樣就可以知道哪個(gè)無(wú)故障服務(wù)器接收了更多的事務(wù),并可以同步他們之間的狀態(tài)信息。


          Zxid 為一個(gè) long 型(64 位)整數(shù),分為兩部分:時(shí)間戳(epoch)部分和計(jì)數(shù)器(counter)部分。每一部分為 32 位,在我們討論 zab 協(xié)議時(shí),我們就會(huì)發(fā)現(xiàn)時(shí)間戳(epoch)和計(jì)數(shù)器(counter)的具體作用,我們通過(guò) zab 協(xié)議來(lái)廣播各個(gè)服務(wù)器的狀態(tài)變更信息。


          2. 群首選舉


          群首為集群中的服務(wù)器選擇出來(lái)的一個(gè)服務(wù)器,并會(huì)一直被集群所認(rèn)可。設(shè)置群首的目的是為了對(duì)客戶端所發(fā)起的 ZooKeeper 狀態(tài)更新請(qǐng)求進(jìn)行排序,包括 create,setData 和 delete 操作。群首將每一個(gè)請(qǐng)求轉(zhuǎn)換為一個(gè)事務(wù),將這些事務(wù)發(fā)送給追隨者,確保集群按照群首確定的順序接受并處理這些事務(wù)。


          每個(gè)服務(wù)器啟動(dòng)后進(jìn)入 LOOKING 狀態(tài),開(kāi)始選舉一個(gè)新的群首或者查找已經(jīng)存在的群首。如果群首已經(jīng)存在,其他服務(wù)器就會(huì)通知這個(gè)新啟動(dòng)的服務(wù)器,告知哪個(gè)服務(wù)器是群首,于此同時(shí),新服務(wù)器會(huì)與群首建立連接,以確保自己的狀態(tài)與群首一致。如果群首中的所有的服務(wù)器均處于 LOOKING 狀態(tài),這些服務(wù)器之間就會(huì)進(jìn)行通信來(lái)選舉一個(gè)群首,通過(guò)信息交換對(duì)群首選舉達(dá)成共識(shí)的選擇。在本次選舉過(guò)程中勝出的服務(wù)器將進(jìn)入 LEADING 狀態(tài),而集群中其他服務(wù)器將會(huì)進(jìn)入 FOLLOWING 狀態(tài)。


          具體看,一個(gè)服務(wù)器進(jìn)入 LOOKING 狀態(tài),就會(huì)發(fā)送向集群中每個(gè)服務(wù)器發(fā)送一個(gè)通知信息,該消息中包括該服務(wù)器的投票(vote)信息,投票中包含服務(wù)器標(biāo)識(shí)符(sid)和最近執(zhí)行事務(wù)的 zxid 信息。


          當(dāng)一個(gè)服務(wù)器收到一個(gè)投票信息,該服務(wù)器將會(huì)根據(jù)以下規(guī)則修改自己的投票信息:


          將接收的 voteId 和 voteZxid 作為一個(gè)標(biāo)識(shí)符,并獲取接收方當(dāng)前的投票中的 zxid,用 myZxid 和 mySid 表示接收方服務(wù)器自己的值。


          如果(voteZxid > myZxid)或者(voteZxid == myZxid 且 voteId >mySid),保留當(dāng)前的投票信息。


          否則,修改自己的投票信息,將 voteZxid 賦值給 myZxid,將 voteId 賦值給 mySid。


          從上面的投票過(guò)程可以看出,只有最新的服務(wù)器將贏得選舉,因?yàn)槠鋼碛凶罱淮蔚?zxid。如果多個(gè)服務(wù)器擁有的最新的 zxid 值,其中的 sid 值最大的將會(huì)贏得選舉。


          當(dāng)一個(gè)服務(wù)器連接到仲裁數(shù)量的服務(wù)器發(fā)來(lái)的投票都一樣時(shí),就表示群首選舉成功,如果被選舉的群首為某個(gè)服務(wù)器自己,該服務(wù)器將會(huì)開(kāi)始行使群首角色,否則就會(huì)成為一個(gè)追隨者并嘗試連接被選舉的群首服務(wù)器。一旦連接成功,追隨者和群首之間將會(huì)進(jìn)行狀態(tài)同步,在同步完成后,追隨者才可以進(jìn)行新的請(qǐng)求。


          3. Zab:狀態(tài)更新的廣播協(xié)議


          在接收到一個(gè)寫(xiě)請(qǐng)求操作后,追隨者會(huì)將請(qǐng)求轉(zhuǎn)發(fā)給群首,群首將會(huì)探索性的執(zhí)行該請(qǐng)求,并將執(zhí)行結(jié)果以事務(wù)的方式對(duì)狀態(tài)更新進(jìn)行廣播。如何確認(rèn)一個(gè)事務(wù)是否已經(jīng)提交,ZooKeeper 由此引入了 zab 協(xié)議,即原子廣播協(xié)議(ZooKeeper Atomic Broadeast protocol)。該協(xié)議提交一個(gè)事務(wù)非常簡(jiǎn)單,類型于一個(gè)兩階段提交。


          1. 群首向所有追隨者發(fā)送一個(gè) PROPOSAL 消息 p。
          2. 當(dāng)一個(gè)追隨者接收到消息 p 后,會(huì)響應(yīng)群首一個(gè) ACK 消息,通知群首其已接受該提案(proposal)。
          3. 當(dāng)收到仲裁數(shù)量的服務(wù)器發(fā)送的確認(rèn)消息后(該仲裁數(shù)包括群首自己),群首就會(huì)發(fā)送消息通知追隨者進(jìn)行提交(COMMIT)操作。


          Zab 保障了以下幾個(gè)重要的屬性:
          • 如果群首按順序廣播了事務(wù) T 和事務(wù) T,那么每個(gè)服務(wù)器在提交 T 事務(wù)前保證事務(wù) T 已經(jīng)完成提交。
          • 如果某個(gè)服務(wù)器按照事務(wù) T 和事務(wù) T 的順序提交了事務(wù),所有其他服務(wù)器也必然會(huì)在提交事務(wù) T 前提交事務(wù) T。
          • 第一個(gè)屬性保證事務(wù)在服務(wù)器之間傳送順序的一致,而第二個(gè)豎向保證服務(wù)器不會(huì)跳過(guò)任何事務(wù)。


          4. 觀察者


          觀察者與追隨者有一些共同的特點(diǎn),他們提交來(lái)自群首的提議,不同于追隨者的是,觀察者不參與選舉過(guò)程,他們僅僅學(xué)習(xí)經(jīng)由 INFORM 消息提交的提議。


          引入觀察者的一個(gè)主要原因是提高讀請(qǐng)求的可擴(kuò)展性。通過(guò)加入多個(gè)觀察者,我們可以在不犧牲寫(xiě)操作的吞吐率的前提下服務(wù)更多的讀操作。但是引入觀察者也不是完全沒(méi)有開(kāi)銷,每一個(gè)新加入的觀察者將對(duì)應(yīng)于每一個(gè)已提交事務(wù)點(diǎn)引入的一條額外消息。


          采用觀察者的另外一個(gè)原因是進(jìn)行跨多個(gè)數(shù)據(jù)中心部署。由于數(shù)據(jù)中心之間的網(wǎng)絡(luò)鏈接延時(shí),將服務(wù)器分散于多個(gè)數(shù)據(jù)中心將明顯地降低系統(tǒng)的速度。引入觀察者后,更新請(qǐng)求能夠先以高吞吐量和低延遲的方式在一個(gè)數(shù)據(jù)中心內(nèi)執(zhí)行,接下來(lái)再傳播到異地的其他數(shù)據(jù)中心得到執(zhí)行。


          5. 服務(wù)器的構(gòu)成


          群首,追隨者,觀察者根本上都是服務(wù)器。在實(shí)現(xiàn)服務(wù)器主要抽象概念是請(qǐng)求處理器。請(qǐng)求處理器是對(duì)處理流水線上不同階段的抽象,每個(gè)服務(wù)器實(shí)現(xiàn)一個(gè)請(qǐng)求處理器的序列。


          獨(dú)立服務(wù)器

          PrepRequestProcessor 接受客戶端的請(qǐng)求并執(zhí)行這個(gè)請(qǐng)求,處理結(jié)果則是生成一個(gè)事務(wù)。不過(guò)只有改變 ZooKeeper 狀態(tài)的操作才會(huì)產(chǎn)生事務(wù),對(duì)于讀操作并不會(huì)產(chǎn)生任何事務(wù)。


          SyncRequestProcessor 負(fù)責(zé)將事務(wù)持久化到磁盤(pán)上。實(shí)際上就是將事務(wù)數(shù)據(jù)按照順序追加到事務(wù)日志中,并形成快照數(shù)據(jù)。


          最后一個(gè)處理器為 FinalRequestProcessor,如果 Request 對(duì)象包含事務(wù)數(shù)據(jù),該處理器就會(huì)接受對(duì) ZooKeeper 數(shù)據(jù)樹(shù)的修改,否則,該處理器會(huì)從數(shù)據(jù)樹(shù)中讀取數(shù)據(jù)并返回客戶端。


          群首服務(wù)器

          在切換到仲裁模式時(shí),服務(wù)器的流水線則有一些變化。


          群首服務(wù)器流水線


          第一個(gè)處理器同樣是 PrepRequestProcessor,而之后的處理器則為 ProposalRequestProcessor,該處理器會(huì)準(zhǔn)備一個(gè)提議,并將該提議發(fā)送給跟隨者,并且會(huì)把所有請(qǐng)求轉(zhuǎn)發(fā)給 CommitRequestProcessor,對(duì)于寫(xiě)操作請(qǐng)求,還會(huì)把請(qǐng)求轉(zhuǎn)發(fā)給 SyncRequestProcessor 處理器。


          SyncRequestProcessor 和獨(dú)立服務(wù)器的功能一樣,是持久化事務(wù)到磁盤(pán)上,執(zhí)行完后會(huì)觸發(fā) AckRequestProcessor 處理器,它僅僅生成確認(rèn)消息并返回給自己。


          CommitRequestProcessor 會(huì)將收到足夠多的確認(rèn)消息的提議進(jìn)行提交。


          追隨者和觀察者服務(wù)器

          Follower 服務(wù)器是先從 FollowerRequestProcessors 處理器開(kāi)始,該處理器接收并處理客戶端請(qǐng)求,F(xiàn)ollowerRequestProcessors 處理器之后轉(zhuǎn)發(fā)請(qǐng)求給 CommitRequestProcessor,同時(shí)也會(huì)轉(zhuǎn)發(fā)寫(xiě)請(qǐng)求到群首服務(wù)器。CommitRequestProcessor 會(huì)直接轉(zhuǎn)發(fā)讀取請(qǐng)求到 FinalRequestProcessor 處理器,而且對(duì)于寫(xiě)請(qǐng)求,在轉(zhuǎn)發(fā)前會(huì)等待提交事務(wù)。而群首接收到一個(gè)新的寫(xiě)請(qǐng)求時(shí)會(huì)生成一個(gè)提議,之后轉(zhuǎn)發(fā)到追隨者服務(wù)器,在收到一個(gè)提議,追隨服務(wù)器會(huì)發(fā)送這個(gè)提議到 SyncRequestProcessor,SendRequestProcessor 會(huì)向群首發(fā)送確認(rèn)消息。


          當(dāng)群首服務(wù)器接收到足夠多確認(rèn)消息來(lái)提交這個(gè)提議是,群首就會(huì)發(fā)送提交事務(wù)消息給追隨者,當(dāng)收到提交的事務(wù)消息時(shí),追隨者就通過(guò) CommitRequestProcessor 處理器進(jìn)行處理。為了保證執(zhí)行的順序,CommitRequestProcessor 處理器會(huì)在收到一個(gè)寫(xiě)請(qǐng)求處理器時(shí)暫停后續(xù)的請(qǐng)求處理。


          對(duì)于觀察者服務(wù)器不需要確認(rèn)提議消息,因此觀察者服務(wù)器并不需要發(fā)送確認(rèn)消息給群首服務(wù)器,一般情況下,也不用持久化事務(wù)到磁盤(pán)。對(duì)于觀察者服務(wù)器是否持久化事務(wù)到磁盤(pán),以便加速觀察者服務(wù)器的恢復(fù)速度,可以根據(jù)具體情況決定。


          6. 本地存儲(chǔ)


          SyncRequestProcessor 處理器是用于處理提議寫(xiě)入的日志和快照。


          • 日志和磁盤(pán)的使用

          服務(wù)器通過(guò)事務(wù)日志來(lái)持久化事務(wù)。在接受一個(gè)提議時(shí),一個(gè)服務(wù)器就會(huì)將提議的事務(wù)持久化到事務(wù)日志中,該事務(wù)日志保存在服務(wù)器本地磁盤(pán)中,而事務(wù)將會(huì)按照順序追加其后。寫(xiě)事務(wù)日志是寫(xiě)請(qǐng)求操作的關(guān)鍵路徑,因此 ZooKeeper 必須有效處理寫(xiě)日志問(wèn)題。在持久化事務(wù)到磁盤(pán)時(shí),還有一個(gè)重要說(shuō)明:現(xiàn)代操作系統(tǒng)通常會(huì)緩存臟頁(yè)(Dirty Page),并將他們異步寫(xiě)入磁盤(pán)介質(zhì)。然而,我們需要在繼續(xù)之前,要確保事務(wù)已經(jīng)被持久化。因此我們需要沖刷(Flush)事務(wù)到磁盤(pán)介質(zhì)。


          沖刷在這里就是指我們告訴操作系已經(jīng)把臟頁(yè)寫(xiě)入到磁盤(pán),并在操作完成后返回。同時(shí)為了提高 ZooKeeper 系統(tǒng)的運(yùn)行速度,也會(huì)使用組提交和補(bǔ)白的。其中組提交是指一次磁盤(pán)寫(xiě)入時(shí)追加多個(gè)事務(wù),可以減少磁盤(pán)尋址的開(kāi)銷。補(bǔ)白是指在文件中預(yù)分配磁盤(pán)存儲(chǔ)塊。


          • 快照

          快照是 ZooKeeper 數(shù)據(jù)樹(shù)的拷貝副本,每一個(gè)服務(wù)器會(huì)經(jīng)常以序列化整個(gè)數(shù)據(jù)樹(shù)的方式來(lái)提取快照,并將這個(gè)提取的快照保存到文件。服務(wù)器在進(jìn)行快照時(shí)不需要進(jìn)行協(xié)作,也不需要暫停處理請(qǐng)求。因此服務(wù)器在進(jìn)行快照時(shí)還會(huì)繼續(xù)處理請(qǐng)求,所以當(dāng)快照完成時(shí),數(shù)據(jù)樹(shù)可能又發(fā)生了變化,稱為快照是模糊的,因?yàn)樗鼈儾荒芊从吵鲈谌我饨o定的時(shí)間點(diǎn)數(shù)據(jù)樹(shù)的準(zhǔn)確的狀態(tài)。


          7. 服務(wù)器與會(huì)話


          會(huì)話(session)是 ZooKeeper 的一個(gè)重要的抽象。保證請(qǐng)求有序,臨時(shí) znode 節(jié)點(diǎn),監(jiān)控點(diǎn)都與會(huì)話密切相關(guān)。因此會(huì)話的跟蹤機(jī)制對(duì) ZooKeeper 來(lái)說(shuō)也是非常重要的。


          在獨(dú)立模式下,單個(gè)服務(wù)器會(huì)跟蹤所有的會(huì)話,而在仲裁模式下則由群首服務(wù)器來(lái)跟蹤和維護(hù)。而追隨者服務(wù)器僅僅是簡(jiǎn)單地把客戶端連接的會(huì)話信息轉(zhuǎn)發(fā)到群首服務(wù)器。


          為了保證會(huì)話的存活,服務(wù)器需要接收會(huì)話的心跳信息。心跳的形式可以是一個(gè)新的請(qǐng)求或者顯式的 ping 信息。兩種情況下,服務(wù)器通過(guò)更新會(huì)話的過(guò)期時(shí)間來(lái)觸發(fā)會(huì)話活躍,在仲裁模式下,群首服務(wù)器發(fā)送一個(gè) PING 信息給它的追隨者們,追隨者們返回自從最新一次 PING 消息之后的一個(gè) session 列表。群首服務(wù)器每半個(gè) tick 就會(huì)發(fā)送一個(gè) ping 信息給追隨者們。


          8. 服務(wù)器與監(jiān)視點(diǎn)


          監(jiān)視點(diǎn)是由讀取操作所設(shè)置的一次性觸發(fā)器,每個(gè)監(jiān)視點(diǎn)有一個(gè)特定操作來(lái)觸發(fā),即通過(guò)監(jiān)視點(diǎn),客戶端可以對(duì)指定的 znode 節(jié)點(diǎn)注冊(cè)一個(gè)通知請(qǐng)求,在發(fā)生時(shí)就會(huì)收到一個(gè)單次的通知。監(jiān)視點(diǎn)只會(huì)存在內(nèi)存,而不會(huì)持久化到硬盤(pán),當(dāng)客戶端與服務(wù)端的連接斷開(kāi)時(shí),它的所有的監(jiān)視點(diǎn)會(huì)從內(nèi)存中清除。因?yàn)榭蛻舳艘矔?huì)維護(hù)一份監(jiān)視點(diǎn)的數(shù)據(jù),在重連之后,監(jiān)視點(diǎn)數(shù)據(jù)會(huì)再次同步到服務(wù)端。


          9. 客戶端


          在客戶端庫(kù)中有 2 個(gè)主要的類:ZooKeeper 和 ClientCnxn,寫(xiě)客戶端應(yīng)用程序時(shí)通過(guò)實(shí)例化 ZooKeeper 類來(lái)建立一個(gè)會(huì)話。一旦建立起一個(gè)會(huì)話,ZooKeeper 就會(huì)使用一個(gè)會(huì)話標(biāo)識(shí)符來(lái)關(guān)聯(lián)這個(gè)會(huì)話。這個(gè)會(huì)話標(biāo)識(shí)符實(shí)際上是有服務(wù)端所生產(chǎn)的。


          ClientCnxn 類管理連接到 server 的 socket 連接。該類維護(hù)一個(gè)可連接的 ZooKeeper 的服務(wù)列表,并當(dāng)連接斷掉的時(shí)候無(wú)縫地切換到其他服務(wù)器,當(dāng)重連到一個(gè)其他的服務(wù)器時(shí)會(huì)使用同一個(gè)會(huì)話,客戶端也會(huì)重置所有的監(jiān)視點(diǎn)到剛連接的服務(wù)器上。


          10. 序列化


          對(duì)于網(wǎng)絡(luò)傳輸和磁盤(pán)保存的序列化消息和事務(wù),ZooKeeper 使用了 Hadoop 中的 Jute 來(lái)做序列化。


          One more thing


          目前,騰訊云微服務(wù)引擎(Tencent Cloud Service Engine,簡(jiǎn)稱TSE)已上線,并發(fā)布子產(chǎn)品服務(wù)注冊(cè)、配置中心(ZooKeeper/Nacos/Eureka/Apollo)、治理中心(PolarisMesh)。支持一鍵創(chuàng)建、免運(yùn)維、高可用、開(kāi)源增強(qiáng)的組件托管服務(wù),歡迎點(diǎn)擊文末的「閱讀原文」了解詳情并使用!


          TSE官網(wǎng)地址:

          https://cloud.tencent.com/product/tse



          參考文獻(xiàn)

          • ZooKeeper-選舉實(shí)現(xiàn)分析:
            https://juejin.im/post/5cc2af405188252da4250047
          • Apache ZooKeeper 官網(wǎng):
            https://zookeeper.apache.org/
          • ZooKeeper github:
            https://github.com/apache/zookeeper
          • 《zookeeper-分布式過(guò)程協(xié)同技術(shù)詳解》【美】里德,【美】Flavio Junqueira 著
          • ZooKeeper 源碼分析:
            https://blog.reactor.top/tags/Zookeeper/
          • ZooKeeper-選舉實(shí)現(xiàn)分析:
            https://juejin.im/post/5cc2af405188252da4250047
          • ZooKeeper 源碼分析:
            https://www.cnblogs.com/sunshine-2015/tag/zookeeper/


          往期

          推薦


          《深入理解Rabbit MQ與AMQP協(xié)議》

          《應(yīng)用多環(huán)境部署的最佳實(shí)踐》

          《單元化架構(gòu)在金融行業(yè)的最佳實(shí)踐》

          《服務(wù)器又崩了?深度解析高可用架構(gòu)的挑戰(zhàn)和實(shí)踐》

          《Kratos技術(shù)系列|從Kratos設(shè)計(jì)看Go微服務(wù)工程實(shí)踐》

          《Pulsar技術(shù)系列 - 深度解讀Pulsar Schema》

          《Apache Pulsar事務(wù)機(jī)制原理解析|Apache Pulsar 技術(shù)系列》





          掃描下方二維碼關(guān)注本公眾號(hào),

          了解更多微服務(wù)、消息隊(duì)列的相關(guān)信息!

          解鎖超多鵝廠周邊!


          戳原文,查看更多微服務(wù)引擎TSE信息!


          點(diǎn)個(gè)在看你最好看


          瀏覽 66
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费成人黄片 | 俺去也婷婷 | 天天肏屄天天射 | 深爱激情在线视频 | 另类专区视频 |