jinfeng_wang

          G-G-S,D-D-U!

          BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
            400 Posts :: 0 Stories :: 296 Comments :: 0 Trackbacks
          https://taozj.org/201701/learn-note-of-distributed-system-%286%29-application.html


           至此,Paxos、Raft、ZAB代表著分布式系統(tǒng)中最常見的一致性協(xié)議都有所了解,但是除了PaxSql之外,對于分布式系統(tǒng)一致性原理的實(shí)際應(yīng)用還處于一臉懵逼的狀態(tài)中。此處于是主要借著《從Paxos到Zookeeper:分布式一致性原理與實(shí)踐》中的案例,依靠ZooKeeper分布式系統(tǒng)組建,對分布式系統(tǒng)的使用情境做一個(gè)簡單的了解。畢竟嘛,我又不是做學(xué)術(shù)的,了解原理后不知道現(xiàn)實(shí)有什么用處又有啥意義…
            ZooKeeper扮演者分布式系統(tǒng)的管理和協(xié)調(diào)框架的作用,通過前面對ZAB和ZooKeeper的了解,ZooKeeper通過ZNode數(shù)據(jù)模型和序列號、持久和臨時(shí)節(jié)點(diǎn)分類,以及Watcher事件通知機(jī)制,可以快速構(gòu)建分布式應(yīng)用的核心功能,看看Apache旗下那么多基于ZooKeeper的分布式項(xiàng)目就可曉而知了。ZooKeeper的集群達(dá)到3臺(tái)就可以正常工作了,但是工業(yè)上通常認(rèn)為至少達(dá)到5臺(tái)才是合適的,一方面機(jī)器增多集群的可靠性增加了,再次集群工作過程中常常會(huì)有機(jī)器下線維護(hù)的情況,這樣在一臺(tái)機(jī)器下線的時(shí)候集群還可以容易一臺(tái)機(jī)器宕機(jī)而不停止服務(wù)。
          zookeeper
            再次說明,個(gè)人沒什么分布式系統(tǒng)的經(jīng)驗(yàn),這些都是查閱資料摘抄得來,如果錯(cuò)誤盡請指正,被我誤導(dǎo)概不負(fù)責(zé)!

          一、數(shù)據(jù)發(fā)布/訂閱(配置中心) - Publish/Subscribe
            發(fā)布/訂閱模式不僅僅會(huì)出現(xiàn)在這里,通常消息隊(duì)列的設(shè)計(jì)中會(huì)更加常用到這種模式。發(fā)布/訂閱模式功能可以分為這幾種模式:
            (1). Push模式是服務(wù)器主動(dòng)將數(shù)據(jù)更新發(fā)送給所有訂閱的客戶端,優(yōu)點(diǎn)是實(shí)時(shí)性好,但是服務(wù)端的工作比較繁重,常常需要記錄各個(gè)客戶端的狀態(tài)信息,甚至要考慮消費(fèi)者的消費(fèi)能力實(shí)現(xiàn)流量控制工作;
            (2). Pull模式則是由客戶端主動(dòng)發(fā)起請求來獲取最新數(shù)據(jù),通常采用定時(shí)機(jī)制輪訓(xùn)拉取的方式進(jìn)行,所以實(shí)時(shí)性較差,但好處是實(shí)現(xiàn)簡單;
            (3). 還有就是結(jié)合兩者進(jìn)行推拉相結(jié)合的方式,客戶端向服務(wù)端注冊自己關(guān)心的主題,一旦主題數(shù)據(jù)有所更新,服務(wù)端會(huì)向?qū)?yīng)訂閱的客戶端發(fā)送事件通知,客戶端接收到事件通知后主動(dòng)向服務(wù)器拉取最新的數(shù)據(jù)。
            在系統(tǒng)開發(fā)中通常會(huì)遇到機(jī)器列表信息、運(yùn)行時(shí)開關(guān)配置、數(shù)據(jù)庫配置等信息,這些數(shù)據(jù)的特點(diǎn)是數(shù)據(jù)規(guī)模比較小、數(shù)據(jù)內(nèi)容在運(yùn)行時(shí)候常常發(fā)生動(dòng)態(tài)變更、相同的數(shù)據(jù)在多個(gè)機(jī)器中共享。在單機(jī)的情況下,可以通過共享內(nèi)存,或者統(tǒng)一配置文件(可以使用文件系統(tǒng)的特性監(jiān)測文件變更iNotify)來滿足這個(gè)需求,但是如果配置需要跨主機(jī),尤其機(jī)器規(guī)模大且成員會(huì)發(fā)生變動(dòng)的情況下共享這些動(dòng)態(tài)信息就較為困難。
            基于ZooKeeper的配置中心方案可以這樣設(shè)計(jì):首先運(yùn)行一個(gè)ZooKeeper服務(wù)器集群,然后在其上面創(chuàng)建周知路徑的ZNode;專用的配置管理程序可以修改ZNode上的配置信息,作為用戶更新配置的操作接口;關(guān)心這些配置的分布式應(yīng)用啟動(dòng)時(shí)候主動(dòng)獲取配置信息一次,然后對ZNode注冊Watcher監(jiān)聽,那么當(dāng)ZNode的數(shù)據(jù)內(nèi)容發(fā)生變化后,ZooKeeper就可以將這個(gè)變更通知發(fā)送給所有的客戶端,客戶端得知這個(gè)變更通知后就可以請求獲取最新數(shù)據(jù)。通過這種手段,就可以實(shí)現(xiàn)配置信息的集中式管理和動(dòng)態(tài)更新部署的功能了。

          二、負(fù)載均衡 - Load Balance
            負(fù)載均衡在前面的Nginx中也介紹過了,Nginx支持3層和7層軟件負(fù)載均衡,對用戶看來這實(shí)際上是實(shí)現(xiàn)的基于服務(wù)端的負(fù)載均衡操作。其實(shí)負(fù)載均衡還可以在客戶端實(shí)現(xiàn),之前介紹的memcached的負(fù)載均衡基本都是在客戶端通過一致性hash原理實(shí)現(xiàn)的。
            通過ZooKeeper實(shí)現(xiàn)的負(fù)載均衡也是通過客戶端來實(shí)現(xiàn)的:ZooKeeper創(chuàng)建一個(gè)周知路徑的ZNode,其數(shù)據(jù)內(nèi)容包含了可以提供服務(wù)的服務(wù)器地址信息,接收服務(wù)的客戶端在該ZNode上注冊Watcher以偵聽它的改變。在工作的時(shí)候客戶端獲取提供服務(wù)的服務(wù)器列表,在接收到修改事前之前可以緩存該列表提高性能,然后服務(wù)調(diào)用者可以采用自己某種特定負(fù)載均衡算法(比如Round Robin、HASH、響應(yīng)時(shí)間、最少連接等算法)選取機(jī)器獲取服務(wù)。
            為了使用方便,服務(wù)機(jī)器列表的配置可以采用全自動(dòng)的方式,這也涉及到機(jī)器健康度檢測問題??梢栽O(shè)計(jì)一個(gè)健康度探測服務(wù)端,并負(fù)責(zé)更新ZNode中的機(jī)器列表:健康度探測服務(wù)端可以同機(jī)器中的列表建立TCP長連接,健康度探測服務(wù)端采用Ping-Pong心跳監(jiān)測的方式進(jìn)行健康度監(jiān)測;也可以機(jī)器每隔一定的時(shí)間向這個(gè)健康度探測服務(wù)端發(fā)送數(shù)據(jù)包,如果健康度探測在某個(gè)超時(shí)時(shí)間后仍未收到某機(jī)器的數(shù)據(jù)包,就認(rèn)定其不可用而將其從機(jī)器列表中進(jìn)行刪除。(呃,后面想想,每個(gè)服務(wù)端機(jī)器把自己作為臨時(shí)ZNode創(chuàng)建在某個(gè)路徑下,這樣的偵測操作不是更加的方便?和集群管理重了)

          三、命名服務(wù) - Name Service
            命名服務(wù)其實(shí)是指明了一種映射關(guān)系,在分布式開發(fā)中有很多的資源需要命名,比如主機(jī)地址,RPC服務(wù)列表等,客戶端根據(jù)名字可以獲取資源的實(shí)體、服務(wù)地址和提供者等信息。
            ZooKeeper提供了方便的API,可以輕松的創(chuàng)建全局唯一的path,這個(gè)path就可以作為名稱使用,所以ZooKeeper的Name Service是開箱即用的。而且ZNode支持SEQUENTIAL屬性,通過創(chuàng)建順序節(jié)點(diǎn)的手法就可以創(chuàng)建具有相同名字但帶順序后綴的這樣很具有規(guī)則性的名字,這樣的命名服務(wù)顯然在保證命名唯一性的同時(shí)更具有解釋意義。

          四、分布式協(xié)調(diào)/通知 - Coordinator
            得益于ZooKeeper特有的Watcher注冊和異步通知的機(jī)制,可以實(shí)現(xiàn)分布式環(huán)境下不同機(jī)器,甚至是不同系統(tǒng)之間的通知和協(xié)調(diào)工作,以應(yīng)對于數(shù)據(jù)變更的實(shí)時(shí)快速處理,這是和觀察者類似的工作模式。而且通過ZooKeepr作為一個(gè)事件的中介者,也起到了業(yè)務(wù)之間解除耦合的效果。

          五、集群管理 - Management
            用于對集群中的機(jī)器進(jìn)行監(jiān)控的情況,主要包括對集群運(yùn)行狀態(tài)的收集,以及對集群和集群成員進(jìn)行操作和控制。
            傳統(tǒng)的運(yùn)維都是基于Agent的分布式集群管理模式,通過在集群成員上部署該類服務(wù)軟件,該軟件負(fù)責(zé)主動(dòng)向集群控制中心匯報(bào)機(jī)器的狀態(tài)信息。這種方式雖然直接,但是具有著固有的缺陷:很難實(shí)現(xiàn)跟業(yè)務(wù)相關(guān)的細(xì)化監(jiān)控,通常都是對CPU、負(fù)載等通用信息進(jìn)行監(jiān)測;如果整個(gè)集群環(huán)境一致還可以,否則就必須面對集群中的異構(gòu)成員進(jìn)行兼容和適配的問題。
            如果運(yùn)行一個(gè)ZooKeeper集群,不僅通過臨時(shí)節(jié)點(diǎn)在會(huì)話結(jié)束后會(huì)自動(dòng)消失的特性,可以快速偵測機(jī)器的上下線,而且可以通過創(chuàng)建特定的ZNode,集群中的機(jī)器就可以向控制中心報(bào)告更多主機(jī)相關(guān)甚至業(yè)務(wù)相關(guān)的信息,而且這一切操作都極為便利,只需要在業(yè)務(wù)端和控制中心進(jìn)行適配就可以了。

          六、Master選舉 - Election
            可以應(yīng)用于那些只需要一個(gè)主節(jié)點(diǎn)做特殊的工作,其他節(jié)點(diǎn)做普通的工作或者候命作為冗余節(jié)點(diǎn)的情況,比如數(shù)據(jù)庫的讀寫分離可以讓Master處理所有的寫任務(wù),而剩余的讀請求由其他機(jī)器負(fù)載均衡完成,借此提供整個(gè)數(shù)據(jù)庫性能;類似的Master可以單獨(dú)處理一些復(fù)雜的邏輯或者計(jì)算,而將計(jì)算結(jié)果同步共享給集群中的其他主機(jī)使用,以此減少重復(fù)勞動(dòng)提高資源利用率。
            傳統(tǒng)情況下的選主可以使用數(shù)據(jù)庫唯一性索引簡單實(shí)現(xiàn),在此約束下所有的機(jī)器創(chuàng)建同一條記錄時(shí)候只能有一個(gè)機(jī)器成功,那么可以讓這個(gè)獨(dú)一無二的機(jī)器作為Master,但是這種方法只是解決了競爭沖突問題,無法解決Master單點(diǎn)故障后整個(gè)系統(tǒng)不可用的問題,即不能實(shí)現(xiàn)高效快速的動(dòng)態(tài)Master選舉功能。
            對此,ZooKeeper的強(qiáng)一致性可以天然解決Master選舉的問題(注意這里的選主是客戶端的Master,和ZAB協(xié)議中的Leader沒有關(guān)系):首先ZooKeeper保證在多個(gè)客戶端請求創(chuàng)建同一路徑描述的ZNode的情況下,只會(huì)有一個(gè)客戶端的請求成功;其次創(chuàng)建ZNode可以是臨時(shí)ZNode,那么一旦創(chuàng)建這個(gè)臨時(shí)ZNode的Master掛掉后會(huì)導(dǎo)致會(huì)話結(jié)束,這個(gè)臨時(shí)ZNode就會(huì)自動(dòng)消失;在之前競爭Master失敗的客戶端,可以注冊該ZNode的Watcher偵聽,一旦接收到節(jié)點(diǎn)的變更事件,就表示Master不可用了,此時(shí)大家就可以即刻再次發(fā)起Master選舉操作了,以實(shí)現(xiàn)了一種高可用的automatic fail-over機(jī)制,滿足了機(jī)器在線率有較高要求的應(yīng)用場景。
            除了上面的方式,各個(gè)主機(jī)還可以通過創(chuàng)建臨時(shí)順序ZNode的方式,每個(gè)主機(jī)會(huì)具有不同的后綴,一旦當(dāng)前的Master宕機(jī)之后自動(dòng)輪訓(xùn)下一個(gè)可用機(jī)器,而下線的機(jī)器也可以隨時(shí)再次上線創(chuàng)建新序列號的臨時(shí)順序節(jié)點(diǎn)。

          七、分布式鎖 - Lock
            主要用來進(jìn)行分布式系統(tǒng)之間的訪問資源的同步手段。在使用中分布式鎖可以支持這些服務(wù):保持獨(dú)占、共享使用和時(shí)序訪問。雖然關(guān)系數(shù)據(jù)庫在更新的時(shí)候,數(shù)據(jù)庫系統(tǒng)會(huì)根據(jù)隔離等級自動(dòng)使用行鎖、表鎖機(jī)制保證數(shù)據(jù)的完整性,但是數(shù)據(jù)庫通常都是大型系統(tǒng)的性能瓶頸之所在,所以如果使用分布式鎖可以起到一定的協(xié)調(diào)作用,那么可以期待增加系統(tǒng)的運(yùn)行效率。
            保持獨(dú)占,就是當(dāng)多個(gè)客戶端試圖獲取這把鎖的時(shí)候,只能有一個(gè)可以成功獲得該鎖,跟上面的Master選舉比較類似,當(dāng)多個(gè)競爭者同時(shí)嘗試創(chuàng)建某個(gè)path(例如”_locknode_/guid-lock-“)的ZNode時(shí)候,ZooKeeper的一致性能夠保證只有一個(gè)客戶端成功,創(chuàng)建成功的客戶端也就擁有了這把互斥鎖,此時(shí)其他客戶端可以在這個(gè)ZNode上面注冊Watcher偵聽,以便得到鎖變更(如持鎖客戶端宕機(jī)、主動(dòng)解鎖)的情況采取接下來的操作。
            共享使用類似于讀寫鎖的功能,多個(gè)讀鎖可以同時(shí)對一個(gè)事務(wù)可見,但是讀鎖和寫鎖以及寫鎖和寫鎖之間是互斥的。鎖的名字按照類似”/share_lock/[Host]-R/W-SN”的形式創(chuàng)建臨時(shí)順序節(jié)點(diǎn),在創(chuàng)建鎖的同時(shí)讀取/share_lock節(jié)點(diǎn)下的所有子節(jié)點(diǎn),并注冊對/share_lock/節(jié)點(diǎn)的Watcher偵聽,然后依據(jù)讀寫所的兼容法則檢查比自己序號小的節(jié)點(diǎn)看是否可以滿足當(dāng)前操作請求,如果不滿足就執(zhí)行等待。當(dāng)持有鎖的節(jié)點(diǎn)崩潰或者釋放鎖之后,所有處于等待狀態(tài)的節(jié)點(diǎn)就都得到了通知,實(shí)際中這會(huì)產(chǎn)生一個(gè)“驚群效應(yīng)”,所以可以在上面注冊/share_lock/的Watcher事件進(jìn)行細(xì)化,只注冊比自己小的那個(gè)子節(jié)點(diǎn)的Watcher偵聽就可以了,以避免不必要的喚醒。
            時(shí)序訪問的方式,則是在這個(gè)時(shí)候每個(gè)請求鎖的客戶端都可以創(chuàng)建臨時(shí)順序ZNode的子節(jié)點(diǎn),他們維系著一個(gè)帶有序列號的后綴,同時(shí)添加對鎖節(jié)點(diǎn)(或者像上面類似優(yōu)化,只注冊序列號比自己小的那個(gè)子節(jié)點(diǎn))的Watcher偵聽,這樣前面的客戶端釋放鎖之后,后面的客戶端會(huì)得到事件通知,然后按照一定順序接下來的一個(gè)客戶端獲得鎖。該模式能夠保證每個(gè)客戶端都具有訪問的機(jī)會(huì),但是其是按照創(chuàng)建臨時(shí)順序子節(jié)點(diǎn)的順序按次序依次訪問的。

          八、分布式隊(duì)列 - Queue
            說到分布式隊(duì)列,目前已有相當(dāng)多的成熟消息中間件了。在ZooKeeper的基礎(chǔ)上,可以方便地創(chuàng)建先進(jìn)先出隊(duì)列,以及對數(shù)據(jù)進(jìn)行聚集之后再統(tǒng)一安排處理的Barrier的工作模式。
            先入先出之FIFO隊(duì)列算是最常見使用的數(shù)據(jù)模型了,類似于一個(gè)生產(chǎn)者-消費(fèi)者的工作模型。生產(chǎn)者會(huì)創(chuàng)建順序ZNode,這些順序ZNode的后綴表明了創(chuàng)建的順序,消費(fèi)者獲得這些順序ZNode后挑出序列號最小的進(jìn)行消費(fèi),就簡單的實(shí)現(xiàn)了FIFO的數(shù)據(jù)類型。
            對于另外一種Barrier(叫做屏障)工作模式,是需要把數(shù)據(jù)集聚之后再做統(tǒng)一處理,通常在大規(guī)模并行計(jì)算的場景上會(huì)使用到。這種隊(duì)列實(shí)現(xiàn)也很簡單,就是在創(chuàng)建順序ZNode的時(shí)候記錄隊(duì)列當(dāng)前已經(jīng)擁有的事務(wù)數(shù)目,如果達(dá)到了Barrier的數(shù)目,就表示條件就緒了于是創(chuàng)建類似“/synchronizing/start”的ZNode,而等待處理的消費(fèi)者之前就偵聽該ZNode是否被創(chuàng)建,如果偵測到一旦創(chuàng)建了就表明事務(wù)的數(shù)目滿足需求了,于是可以啟動(dòng)處理工作。

          小結(jié)
            其實(shí),通過上面的查看,基于ZooKeeper實(shí)現(xiàn)特定需要的分布式應(yīng)用是比較方便的,而且更可貴的是,上面的應(yīng)用都是反反復(fù)復(fù)基于ZooKeeper的那幾條性質(zhì)實(shí)現(xiàn)的!ZooKeeper真是個(gè)好東西!

          本文完!

          參考

          posted on 2017-02-03 16:33 jinfeng_wang 閱讀(310) 評論(0)  編輯  收藏 所屬分類: 2016-zookeeper
          主站蜘蛛池模板: 芦山县| 莒南县| 历史| 清涧县| 九寨沟县| 泉州市| 曲松县| 得荣县| 塔城市| 湖州市| 扶沟县| 黑山县| 馆陶县| 宜宾县| 宁国市| 昌吉市| 夹江县| 花莲市| 福贡县| 新河县| 东兰县| 太仆寺旗| 清新县| 桦南县| 资兴市| 张家口市| 彭泽县| 安康市| 金平| 淮安市| 老河口市| 明星| 突泉县| 北安市| 扬州市| 石柱| 台湾省| 溆浦县| 大田县| 临泉县| 哈尔滨市|