分布式系統(tǒng)解決之道:目錄、消息隊列及其他

分布式系統(tǒng)解決之道:目錄仁烹、消息隊列及其他

本系列的上一篇是:分布式本質輪:微服務、協(xié)程、云

由于這系列文章實在是太長侈询,所以很抱歉發(fā)錯了順序,這應該是第二篇糯耍,不過單獨來看也是可以成文的扔字。

目錄服務(ZooKeeper)

分布式系統(tǒng)是一個由很多進程組成的整體,這個整體中每個成員部分温技,都會具備一些狀態(tài),比如自己的負責模塊舵鳞,自己的負載情況震檩,對某些數(shù)據(jù)的掌握等等抛虏。而這些和其他進程相關的數(shù)據(jù),在故障恢復迂猴、擴容縮容的時候變得非常重要。

簡單的分布式系統(tǒng)沸毁,可以通過靜態(tài)的配置文件,來記錄這些數(shù)據(jù):進程之間的連接對應關系息尺,他們的IP地址和端口,等等搂誉。然而一個自動化程度高的分布式系統(tǒng),必然要求這些狀態(tài)數(shù)據(jù)都是動態(tài)保存的勒葱。這樣才能讓程序自己去做容災和負載均衡的工作。

一些程序員會專門自己編寫一個DIR服務(目錄服務)凛虽,來記錄集群中進程的運行狀態(tài)。集群中進程會和這個DIR服務產(chǎn)生自動關聯(lián)凯旋,這樣在容災、擴容至非、負載均衡的時候钠署,就可以自動根據(jù)這些DIR服務里的數(shù)據(jù),來調整請求的發(fā)送目地荒椭,從而達到繞開故障機器谐鼎、或連接到新的服務器的操作。

然而趣惠,如果我們只是用一個進程來充當這個工作狸棍。那么這個進程就成為了這個集群的“單點”——意思就是,如果這個進程故障了味悄,那么整個集群可能都無法運行的草戈。所以存放集群狀態(tài)的目錄服務,也需要是分布式的侍瑟。幸好我們有ZooKeeper這個優(yōu)秀的開源軟件唐片,它正是一個分布式的目錄服務區(qū)。

ZooKeeper可以簡單啟動奇數(shù)個進程,來形成一個小的目錄服務集群费韭。這個集群會提供給所有其他進程茧球,進行讀寫其巨大的“配置樹”的能力。這些數(shù)據(jù)不僅僅會存放在一個ZooKeeper進程中揽思,而是會根據(jù)一套非常安全的算法袜腥,讓多個進程來承載见擦。這讓ZooKeeper成為一個優(yōu)秀的分布式數(shù)據(jù)保存系統(tǒng)钉汗。

由于ZooKeeper的數(shù)據(jù)存儲結構,是一個類似文件目錄的樹狀系統(tǒng)鲤屡,所以我們常常會利用它的功能损痰,把每個進程都綁定到其中一個“分枝”上,然后通過檢查這些“分支”酒来,來進行服務器請求的轉發(fā)卢未,就能簡單的解決請求路由(由誰去做)的問題。另外還可以在這些“分支”上標記進程的負載的狀態(tài)堰汉,這樣負載均衡也很容易做了辽社。

目錄服務是分布式系統(tǒng)中最關鍵的組件之一。而ZooKeeper是一個很好的開源軟件翘鸭,正好是用來完成這個任務滴铅。

消息隊列服務(ActiveMQ汉匙、ZeroMQ噩翠、Jgroups)

兩個進程間如果要跨機器通訊邦投,我們幾乎都會用TCP/UDP這些協(xié)議。但是直接使用網(wǎng)絡API去編寫跨進程通訊屯援,是一件非常麻煩的事情蠢涝。除了要編寫大量的底層socket代碼外和二,我們還要處理諸如:如何找到要交互數(shù)據(jù)的進程,如何保障數(shù)據(jù)包的完整性不至于丟失惕它,如果通訊的對方進程掛掉了淹魄,或者進程需要重啟應該怎樣等等這一系列問題。這些問題包含了容災擴容兆蕉、負載均衡等一系列的需求缤沦。

為了解決分布式系統(tǒng)進程間通訊的問題缸废,人們總結出了一個有效的模型,就是“消息隊列”模型测萎。消息隊列模型届巩,就是把進程間的交互姆泻,抽象成對一個個消息的處理,而對于這些消息四苇,我們都有一些“隊列”方咆,也就是管道,來對消息進行暫存榆骚。每個進程都可以訪問一個或者多個隊列妓肢,從里面讀取消息(消費)或寫入消息(生產(chǎn))苫纤。由于有一個緩存的管道,我們可以放心的對進程狀態(tài)進行變化喊废。當進程起來的時候,它會自動去消費消息就可以了工闺。而消息本身的路由陆蟆,也是由存放的隊列決定的,這樣就把復雜的路由問題遍搞,變成了如何管理靜態(tài)的隊列的問題器腋。

一般的消息隊列服務纫塌,都是提供簡單的“投遞”和“收取”兩個接口措左,但是消息隊列本身的管理方式卻比較復雜避除,一般來說有兩種。一部分的消息隊列服務凉逛,提倡點對點的隊列管理方式:每對通信節(jié)點之間状飞,都有一個單獨的消息隊列书斜。這種做法的好處是不同來源的消息,可以互不影響焙糟,不會因為某個隊列的消息過多穿撮,擠占了其他隊列的消息緩存空間。而且處理消息的程序也可以自己來定義處理的優(yōu)先級——先收取枪向、多處理某個隊列咧党,而少處理另外一些隊列。

但是這種點對點的消息隊列深员,會隨著集群的增長而增加大量的隊列倦畅,這對于內存占用和運維管理都是一個復雜的事情绣的。因此更高級的消息隊列服務,開始可以讓不同的隊列共享內存空間芭概,而消息隊列的地址信息惩嘉、建立和刪除文黎,都采用自動化的手段∽兀——這些自動化往往需要依賴上文所述的“目錄服務”抓艳,來登記隊列的ID對應的物理IP和端口等信息玷或。比如很多開發(fā)者使用ZooKeeper來充當消息隊列服務的中央節(jié)點;而類似Jgropus這類軟件蔬胯,則自己維護一個集群狀態(tài)來存放各節(jié)點今昔氛濒。

另外一種消息隊列,則類似一個公共的郵箱京景。一個消息隊列服務就是一個進程骗奖,任何使用者都可以投遞或收取這個進程中的消息执桌。這樣對于消息隊列的使用更簡便,運維管理也比較方便伴逸。不過這種用法下错蝴,任何一個消息從發(fā)出到處理香椎,最少進過兩次進程間通信畜伐,其延遲是相對比較高的躺率。并且由于沒有預定的投遞悼吱、收取約束,所以也比較容易出BUG笨枯。

不管使用那種消息隊列服務馅精,在一個分布式服務器端系統(tǒng)中粱檀,進程間通訊都是必須要解決的問題茄蚯,所以作為服務器端程序員睦优,在編寫分布式系統(tǒng)代碼的時候汗盘,使用的最多的就是基于消息隊列驅動的代碼衡未,這也直接導致了EJB3.0把“消息驅動的Bean”加入到規(guī)范之中家凯。

事務系統(tǒng)

在分布式的系統(tǒng)中绊诲,事務是最難解決的技術問題之一。由于一個處理可能分布在不同的處理進程上抗俄,任何一個進程都可能出現(xiàn)故障动雹,而這個故障問題則需要導致一次回滾跟压。這種回滾大部分又涉及多個其他的進程震蒋。這是一個擴散性的多進程通訊問題。要在分布式系統(tǒng)上解決事務問題钾虐,必須具備兩個核心工具:一個是穩(wěn)定的狀態(tài)存儲系統(tǒng)笋庄;另外一個是方便可靠的廣播系統(tǒng)直砂。

事務中任何一步的狀態(tài)哆键,都必須在整個集群中可見,并且還要有容災的能力闪盔。這個需求,一般還是由集群的“目錄服務”來承擔听绳。如果我們的目錄服務足夠健壯椅挣,那么我們可以把每步事務的處理狀態(tài)塔拳,都同步寫到目錄服務上去。ZooKeeper再次在這個地方能發(fā)揮重要的作用量九。

如果事務發(fā)生了中斷荠列,需要回滾载城,那么這個過程會涉及到多個已經(jīng)執(zhí)行過的步驟诉瓦。也許這個回滾只需要在入口處回滾即可(加入那里有保存回滾所需的數(shù)據(jù)),也可能需要在各個處理節(jié)點上回滾呼寸。如果是后者,那么就需要集群中出現(xiàn)異常的節(jié)點河狐,向其他所有相關的節(jié)點廣播一個“回滾馋艺!事務ID是XXXX”這樣的消息。這個廣播的底層一般會由消息隊列服務來承載碱鳞,而類似Jgroups這樣的軟件窿给,直接提供了廣播服務。

雖然現(xiàn)在我們在討論事務系統(tǒng)禁荒,但實際上分布式系統(tǒng)經(jīng)常所需的“分布式鎖”功能角撞,也是這個系統(tǒng)可以同時完成的谒所。所謂的“分布式鎖”,也就是一種能讓各個節(jié)點先檢查后執(zhí)行的限制條件姐军。如果我們有高效而單子操作的目錄服務剖踊,那么這個鎖狀態(tài)實際上就是一種“單步事務”的狀態(tài)記錄德澈,而回滾操作則默認是“暫停操作,稍后再試”缴守。這種“鎖”的方式屡穗,比事務的處理更簡單忽肛,因此可靠性更高,所以現(xiàn)在越來越多的開發(fā)人員础废,愿意使用這種“鎖”服務评腺,而不是去實現(xiàn)一個“事務系統(tǒng)”淑掌。

自動部署工具(Docker)

由于分布式系統(tǒng)最大的需求,是在運行時(有可能需要中斷服務)來進行服務容量的變更:擴容或者縮容媒殉。而在分布式系統(tǒng)中某些節(jié)點故障的時候侥钳,也需要新的節(jié)點來恢復工作。這些如果還是像老式的服務器管理方式苦酱,通過填表疫萤、申報敢伸、進機房池颈、裝服務器、部署軟件……這一套做法每币,那效率肯定是不行琢歇。

在分布式系統(tǒng)的環(huán)境下李茫,我們一般都是采用“池”的方式來管理服務。我們預先會申請一批機器秸侣,然后在某些機器上運行服務軟件塔次,另外一些則作為備份名秀。顯然我們這一批服務器不可能只為某一個業(yè)務服務匕得,而是會提供多個不同的業(yè)務承載汁掠。那些備份的服務器,則會成為多個業(yè)務的通用備份“池”翠忠。隨著業(yè)務需求的變化秽之,一些服務器可能“退出”A服務而“加入”B服務考榨。

這種頻繁的服務變化鹦倚,依賴高度自動的軟件部署工具震叙。我們的運維人員,應該掌握這開發(fā)人員提供的部署工具乐尊,而不是厚厚的手冊匣砖,來進行這類運維操作猴鲫。一些比較有經(jīng)驗的開發(fā)團隊,會統(tǒng)一所有的業(yè)務底層框架牺弄,以期大部分的部署宜狐、配置工具抚恒,都能用一套通用的系統(tǒng)來進行管理。而開源界回溺,也有類似的嘗試,最廣為人知的莫過于RPM安裝包格式萍恕,然而RPM的打包方式還是太復雜车要,不太符合服務器端程序的部署需求翼岁。所以后來又出現(xiàn)了Chef為代表的登澜,可編程的通用部署系統(tǒng)。

在虛擬機技術出現(xiàn)之后购撼,PaaS平臺為自動部署提供了強大的支持:如果我們是按某個PaaS平臺的規(guī)范來編寫的應用迂求,可以完全把程序丟給平臺去部署揩局,其承載量計算凌盯、部署規(guī)劃驰怎,都自動完成了县忌。這方面的佼佼者是Google的AppEngine:我們可以直接用Eclipse開發(fā)一個本地的Web應用继效,然后上傳到AppEngine里面瑞信,所有的部署就完成了!AppEngine會自動的根據(jù)對這個Web應用的訪問量走芋,來進行擴容翁逞、縮容溉仑、故障恢復浊竟。

然而振定,真正有革命性的工具,是Docker的出現(xiàn)梳庆。雖然虛擬機膏执、沙箱技術早就不是什么新技術更米,但是真正使用這些技術來作為部署工具的時間卻不長征峦。Linux高效的輕量級容器技術栏笆,提供了部署上巨大的便利性——我們可以在各種庫竖伯、各種協(xié)作軟件的環(huán)境下打包我們的應用程序因宇,然后隨意的部署在任何一個Linux系統(tǒng)上察滑。

為了管理大量的分布式服務器端進程户盯,我們確實需要花很多功夫,其優(yōu)化其部署管理的工作吗伤。統(tǒng)一服務器端進程的運行規(guī)范足淆,是實現(xiàn)自動化部署管理的基本條件。我們可以根據(jù)“操作系統(tǒng)”作為規(guī)范礁阁,采用Docker技術巧号;也可以根據(jù)“Web應用”作為規(guī)范,采用某些PaaS平臺技術姥闭;或者自己定義一些更具體的規(guī)范丹鸿,自己開發(fā)完整的分布式計算平臺。

日志服務(log4j)

服務器端的日志棚品,一直是一個既重要又容易被忽視的問題靠欢。很多團隊在剛開始的時候,僅僅把日志視為開發(fā)調試南片、排除BUG的輔助工具掺涛。但是很快會發(fā)現(xiàn)疼进,在服務運營起來之后,日志幾乎是服務器端系統(tǒng)减拭,在運行時可以用來了解程序情況的唯一有效手段。

盡管我們有各種profile工具可霎,但是這些工具大部分都不適合在正式運營的服務上開啟,因為會嚴重降低其運行性能绢记。所以我們更多的時候需要根據(jù)日志來分析。盡管日志從本質上护赊,就是一行行的文本信息抽高,但是由于其具有很大的靈活性,所以會很受開發(fā)和運維人員的重視。

日志本身從概念上莹桅,是一個很模糊的東西。你可以隨便打開一個文件,然后寫入一些信息。但是現(xiàn)代的服務器系統(tǒng)杭抠,一般都會對日志做一些標準化的需求規(guī)范:日志必須是一行一行的,這樣比較方便日后的統(tǒng)計分析忿墅;每行日志文本,都應該有一些統(tǒng)一的頭部棍弄,比如日期時間就是基本的需求颁虐;日志的輸出應該是分等級的儒陨,比如fatal/error/warning/info/debug/trace等等车海,程序可以在運行時調整輸出的等級喘沿,以便可以節(jié)省日志打印的消耗留量;日志的頭部一般還需要一些類似用戶ID或者IP地址之類的頭信息忆绰,用于快速查找定位過濾某一批日志記錄,或者有一些其他的用于過濾縮小日志查看范圍的字段,這叫做染色功能;日志文件還需要有“回滾”功能侈沪,也就是保持固定大小的多個文件歼秽,避免長期運行后呻惕,把硬盤寫滿。

由于有上述的各種需求柑营,所以開源界提供了很多游戲的日志組件庫,比如大名鼎鼎的log4j,以及成員眾多的log4X家族庫,這些都是應用廣泛而飽受好評的工具摆尝。

不過對比日志的打印功能,日志的搜集和統(tǒng)計功能卻往往比較容易被忽視视哑。作為分布式系統(tǒng)的程序員跪呈,肯定是希望能從一個集中節(jié)點误阻,能搜集統(tǒng)計到整個集群日志情況寻定。而有一些日志的統(tǒng)計結果唐含,甚至希望能在很短時間內反復獲取,用來監(jiān)控整個集群的健康情況桐腌。要做到這一點,就必須有一個分布式的文件系統(tǒng)遭殉,用來存放源源不斷到達的日志(這些日志往往通過UDP協(xié)議發(fā)送過來)蛔糯。而在這個文件系統(tǒng)上,則需要有一個類似Map Reduce架構的統(tǒng)計系統(tǒng),這樣才能對海量的日志信息翅溺,進行快速的統(tǒng)計以及報警。有一些開發(fā)者會直接使用Hadoop系統(tǒng),有一些則用Kafka來作為日志存儲系統(tǒng),上面再搭建自己的統(tǒng)計程序。

日志服務是分布式運維的儀表盤色洞、潛望鏡奈搜。如果沒有一個可靠的日志服務,整個系統(tǒng)的運行狀況可能會是失控的鞋真。所以無論你的分布式系統(tǒng)節(jié)點是多還是少,必須花費重要的精力和專門的開發(fā)時間闸昨,去建立一個對日志進行自動化統(tǒng)計分析的系統(tǒng)嵌牺。

本系列1:分布式本質論:高吞吐蹋绽、高可用蚣抗、可擴展

本系列2:分布式本質論:維服務震缭、協(xié)程手趣、云

往期精彩內容回看:

理解面向對象編碼

經(jīng)典游戲服務器架構

深入理解數(shù)字技術理論

高性能服務器架構方案

提高程序員工作效率十法

如何當一名合格的技術總監(jiān)

架構師必讀:經(jīng)典軟件架構模式

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市氛悬,隨后出現(xiàn)的幾起案子伪朽,更是在濱河造成了極大的恐慌西土,老刑警劉巖肋乍,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異禽拔,居然都是意外死亡睹栖,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事父晶。” “怎么了甲喝?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵尝苇,是天一觀的道長。 經(jīng)常有香客問我埠胖,道長糠溜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任直撤,我火速辦了婚禮非竿,結果婚禮上,老公的妹妹穿的比我還像新娘谋竖。我一直安慰自己红柱,他們只是感情好,可當我...
    茶點故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布蓖乘。 她就那樣靜靜地躺著锤悄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嘉抒。 梳的紋絲不亂的頭發(fā)上零聚,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天,我揣著相機與錄音众眨,去河邊找鬼握牧。 笑死,一個胖子當著我的面吹牛娩梨,可吹牛的內容都是我干的沿腰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼狈定,長吁一口氣:“原來是場噩夢啊……” “哼颂龙!你這毒婦竟也來了?” 一聲冷哼從身側響起纽什,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤措嵌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后芦缰,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體企巢,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年让蕾,在試婚紗的時候發(fā)現(xiàn)自己被綠了浪规。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片或听。...
    茶點故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖笋婿,靈堂內的尸體忽然破棺而出誉裆,到底是詐尸還是另有隱情,我是刑警寧澤缸濒,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布足丢,位于F島的核電站,受9級特大地震影響庇配,放射性物質發(fā)生泄漏斩跌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一讨永、第九天 我趴在偏房一處隱蔽的房頂上張望滔驶。 院中可真熱鬧,春花似錦卿闹、人聲如沸揭糕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽著角。三九已至,卻和暖如春旋恼,著一層夾襖步出監(jiān)牢的瞬間吏口,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工冰更, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留产徊,地道東北人。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓蜀细,卻偏偏與公主長得像舟铜,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子奠衔,可洞房花燭夜當晚...
    茶點故事閱讀 44,654評論 2 354

推薦閱讀更多精彩內容

  • 本文轉載自http://geek.csdn.net/news/detail/112672 WeTest導讀 我們常...
    shineegirl閱讀 1,547評論 0 26
  • 承載量是分布式系統(tǒng)存在的原因 當一個互聯(lián)網(wǎng)業(yè)務獲得大眾歡迎的時候谆刨,最顯著碰到的技術問題,就是服務器非常繁忙归斤。當每天...
    XYLY閱讀 1,460評論 1 48
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理痊夭,服務發(fā)現(xiàn),斷路器脏里,智...
    卡卡羅2017閱讀 134,652評論 18 139
  • 分布式系統(tǒng)面臨的第一個問題就是數(shù)據(jù)分布她我,即將數(shù)據(jù)均勻地分布到多個存儲節(jié)點。另外,為了保證可靠性和可用性番舆,需要將數(shù)據(jù)...
    olostin閱讀 4,576評論 2 26
  • 以下內容都是騰訊WeTest《淺析分布式系統(tǒng)》博文的摘抄根吁,說是摘抄其實跟原文照搬差不了多少,原文地址騰訊WeTes...
    天之藍色閱讀 1,053評論 0 6