掃二維碼與項(xiàng)目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
作者:佚名 2017-04-14 09:48:25
存儲
存儲軟件
分布式 分布式存儲系統(tǒng)首先要面對的問題就是數(shù)據(jù)分片,即將數(shù)據(jù)均勻地分布到多個存儲節(jié)點(diǎn)。另外,為了保證可靠性和可用性,需要將數(shù)據(jù)復(fù)制多個副本,這就帶來了多個副本的數(shù)據(jù)一致性問題。

十余年的八宿網(wǎng)站建設(shè)經(jīng)驗(yàn),針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。網(wǎng)絡(luò)營銷推廣的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整八宿建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)公司從事“八宿網(wǎng)站設(shè)計”,“八宿網(wǎng)站推廣”以來,每個客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。
最近讀了楊傳輝的《大規(guī)模分布式存儲系統(tǒng):原理解析與架構(gòu)實(shí)踐》,這本書寫的很好,涉及的知識點(diǎn)枚不勝舉。本篇對于其中的分布式存儲系統(tǒng)基礎(chǔ)知識做些整理,以饗諸君。
分布式存儲系統(tǒng)首先要面對的問題就是數(shù)據(jù)分片,即將數(shù)據(jù)均勻地分布到多個存儲節(jié)點(diǎn)。另外,為了保證可靠性和可用性,需要將數(shù)據(jù)復(fù)制多個副本,這就帶來了多個副本的數(shù)據(jù)一致性問題。
大規(guī)模系統(tǒng)的重要目標(biāo)是節(jié)省成本,因而只能采用性價比較高的PC服務(wù)器。這些服務(wù)器性能很好,但是故障率很高,要求系統(tǒng)能夠在軟件層面實(shí)現(xiàn)自動容錯。當(dāng)存儲節(jié)點(diǎn)出現(xiàn)故障時,系統(tǒng)能夠檢測出來,并將原有的數(shù)據(jù)和服務(wù)遷移到集群中其他正常工作的節(jié)點(diǎn)。
基本概念
異常
在分布式存儲系統(tǒng)中,往往將一臺服務(wù)器或者服務(wù)器上運(yùn)行的一個進(jìn)程稱為一個節(jié)點(diǎn),節(jié)點(diǎn)與節(jié)點(diǎn)之間通過網(wǎng)絡(luò)互聯(lián)。然而,服務(wù)節(jié)點(diǎn)是不可靠的,網(wǎng)絡(luò)也是不可靠的,它們之間通信可能會出現(xiàn)各種異常。
服務(wù)器宕機(jī)
引發(fā)服務(wù)器宕機(jī)的原因有很多,例如內(nèi)存錯誤、服務(wù)器停電等等。服務(wù)器宕機(jī)可能隨時發(fā)生,當(dāng)發(fā)生宕機(jī)時,節(jié)點(diǎn)無法正常工作。服務(wù)器重啟后,節(jié)點(diǎn)將失去所有的內(nèi)存信息。
因此,設(shè)計存儲系統(tǒng)時需要考慮如何通過讀取持久化介質(zhì)(如機(jī)械硬盤、固態(tài)硬盤)中的數(shù)據(jù)來恢復(fù)內(nèi)存信息,從而恢復(fù)到宕機(jī)前的某個一致的狀態(tài)。
網(wǎng)絡(luò)異常
引發(fā)網(wǎng)絡(luò)異常的原因可能是消息丟失、消息亂序或者網(wǎng)絡(luò)包數(shù)據(jù)錯誤。有一種特殊的網(wǎng)絡(luò)異常稱為“網(wǎng)絡(luò)分區(qū)”,即集群的所有節(jié)點(diǎn)被劃分為多個區(qū)域,每個區(qū)域內(nèi)部可以正常通信,但是區(qū)域之間無法通信。例如,某分布式系統(tǒng)部署在兩個數(shù)據(jù)中心,由于網(wǎng)絡(luò)調(diào)整,導(dǎo)致數(shù)據(jù)中心之間無法通信,但是,數(shù)據(jù)中心內(nèi)部可以正常通信。
磁盤故障
磁盤故障可以分為兩種情況:磁盤損壞和磁盤數(shù)據(jù)錯誤。磁盤損壞時,將會丟失存儲在上面的數(shù)據(jù),因而,分布式存儲系統(tǒng)需要考慮將數(shù)據(jù)存儲到多臺服務(wù)器,即使其中一臺服務(wù)器磁盤出現(xiàn)故障,也能從其他服務(wù)器上恢復(fù)數(shù)據(jù)。對于磁盤數(shù)據(jù)錯誤,往往可以采用校驗(yàn)和機(jī)制來解決,這樣的機(jī)制既可以在操作系統(tǒng)層面實(shí)現(xiàn),又可以在上層的分布式存儲系統(tǒng)層面實(shí)現(xiàn)。
超時
由于網(wǎng)絡(luò)異常的存在,分布式系統(tǒng)中請求結(jié)果存在“三態(tài)”的概念,即“成功”、“失敗”、“超時”(未知狀態(tài))?!俺晒Α焙汀笆 敝缚蛻舳苏埱竺鞔_收到服務(wù)器的返回值;而“超時”指客戶端發(fā)出了一個請求但是沒有收到回復(fù),但客戶端不能簡單地認(rèn)為服務(wù)端處理失敗,因?yàn)橛锌赡芊?wù)端已經(jīng)處理成功了,但在返回結(jié)果時出現(xiàn)了網(wǎng)絡(luò)異?;蝈礄C(jī)。
對于超時(未知)狀態(tài),有兩種處理思路:1)不斷讀取之前操作的狀態(tài)來驗(yàn)證rpc操作是否成功;2)將操作設(shè)計為“冪等”的,也就是說,操作執(zhí)行一次與執(zhí)行多次的結(jié)果相同。
一致性
由于異常的存在,分布式存儲系統(tǒng)設(shè)計時往往將數(shù)據(jù)冗余存儲多份,每一份稱為一個副本(replica)。這樣,當(dāng)一個節(jié)點(diǎn)出現(xiàn)故障時,可以從其他副本上讀取數(shù)據(jù)??梢哉J(rèn)為,副本是分布式存儲系統(tǒng)容錯技術(shù)的唯一手段。
由于多個副本的存在,如何保證副本之間的一致性是整個分布式系統(tǒng)的理論核心。
可以從兩個角度理解一致性:第一個角度是客戶端,即客戶端讀寫操作是否符合某種特性;第二個角度是存儲系統(tǒng),即存儲系統(tǒng)的多個副本是否一致,更新的順序是否相同等等。
首先定義如下場景,這個場景包含三個組成部分:
最終一致性的描述比較粗略,其他常見的變體如下:
衡量指標(biāo)
評價分布式存儲系統(tǒng)有一些常用的指標(biāo),下面分別介紹。
性能
常見的性能指標(biāo)有:系統(tǒng)的吞吐能力(throughput)以及系統(tǒng)的響應(yīng)時間(latency)。其中,系統(tǒng)的吞吐能力指系統(tǒng)在某一段時間可以處理的請求總數(shù),通常用每秒處理的讀操作數(shù)(QPS,Query Per Second)或者寫操作數(shù)(TPS,Transaction Per Second)來衡量。系統(tǒng)的響應(yīng)時間,指從某個請求發(fā)出到接收到返回結(jié)果消耗的時間,通常用平均延時或者99.9%以上請求的最大延時來衡量。
這兩個指標(biāo)往往是矛盾的,追求高吞吐的系統(tǒng),往往很難做到低延遲;追求低延遲的系統(tǒng),吞吐量也會受到限制。因此,設(shè)計系統(tǒng)時需要權(quán)衡這兩個指標(biāo)。
可用性
系統(tǒng)的可能性(availability)是指系統(tǒng)在面對各種異常時可以提供正常服務(wù)的能力。系統(tǒng)的可用性可以用系統(tǒng)停服務(wù)的時間與正常服務(wù)的時間的比例來衡量,例如某系統(tǒng)的可用性為4個9(99.99%),相當(dāng)于系統(tǒng)一年停服務(wù)時間不能超過365 * 24 * 60 / 10000 = 52.56分鐘。系統(tǒng)可用性往往體現(xiàn)了系統(tǒng)的整體代碼質(zhì)量以及容錯能力。
一致性
前面已經(jīng)說明了系統(tǒng)的一致性。一般來說,越是強(qiáng)的一致性模型,用戶使用起來越簡單。
可擴(kuò)展性
系統(tǒng)的可擴(kuò)展性(scalability)指分布式存儲系統(tǒng)通過擴(kuò)展集群服務(wù)器規(guī)模來提高系統(tǒng)存儲容量、計算量和性能的能力。隨著業(yè)務(wù)的發(fā)展,對底層存儲系統(tǒng)的性能需求不斷增加,比較好的方式就是通過自動增加服務(wù)器提高系統(tǒng)的能力。理想的分布式存儲系統(tǒng)實(shí)現(xiàn)“線性可擴(kuò)展”,也就是說,隨著集群規(guī)模的增加,系統(tǒng)整體性能與服務(wù)器數(shù)量呈線性關(guān)系。
數(shù)據(jù)分布
分布式系統(tǒng)區(qū)別于傳統(tǒng)單機(jī)系統(tǒng)在于能夠?qū)?shù)據(jù)分布到多個節(jié)點(diǎn),并在多個節(jié)點(diǎn)之間實(shí)現(xiàn)負(fù)載均衡。數(shù)據(jù)分布的方式主要有兩種,一種是哈希分布,如一致性哈希,代表系統(tǒng)為Amazon的Dynamo系統(tǒng);另一種方法是順序分布,即數(shù)據(jù)按照主鍵整體有序,代表系統(tǒng)為Google的Bigtable系統(tǒng)。Bigtable將一張大表根據(jù)主鍵切分為有序的范圍,每個有序的范圍是一個子表。
哈希分布
哈希取模的方法很常見,其方法是根據(jù)數(shù)據(jù)的某一種特征計算哈希值,并將哈希值與集群中的服務(wù)器建立映射關(guān)系,從而將不同哈希值得數(shù)據(jù)分布到不同的服務(wù)器上。
如果哈希函數(shù)的散列特性很好,哈希方式可以將數(shù)據(jù)比較均勻地分布到集群中去。然而,找出一個散列特性很好的哈希函數(shù)是很難的。舉個例子,如果按照主鍵散列,那么同一個用戶id下的數(shù)據(jù)可能被分散到多臺服務(wù)器,這會使得一次操作同一個用戶id下的多條記錄變得困難;如果按照用戶id散列,容易出現(xiàn)“數(shù)據(jù)傾斜”問題,即某些大用戶的數(shù)據(jù)量很大,無論集群的規(guī)模有多大,這些用戶始終由一臺服務(wù)器處理。
處理大用戶問題一般有兩種方式,一種方式是手動拆分,即線下標(biāo)記系統(tǒng)中的大用戶,并根據(jù)這些大用戶的數(shù)據(jù)量將其拆分到多臺服務(wù)器上。這相當(dāng)于在哈希分布的基礎(chǔ)上針對這些大用戶特殊處理;另一種方式是自動拆分,即數(shù)據(jù)分布算法能夠動態(tài)調(diào)整,自動將大用戶的數(shù)據(jù)拆分到多臺服務(wù)器上。
傳統(tǒng)的哈希分布算法還有一個問題:當(dāng)服務(wù)器上線或者下線時,N值發(fā)生變化,數(shù)據(jù)映射完全被打亂,幾乎所有的數(shù)據(jù)都需要重新分布,這將帶來大量的數(shù)據(jù)遷移。
一種思路是不再簡單地將哈希值和服務(wù)器個數(shù)之間做除法取模映射,而是將哈希值與服務(wù)器的對應(yīng)關(guān)系作為元數(shù)據(jù),交給專門的元數(shù)據(jù)服務(wù)器來管理。訪問數(shù)據(jù)時,首先計算哈希值,再查詢元數(shù)據(jù)服務(wù)器,獲得該哈希值對應(yīng)的服務(wù)器。這樣,集群擴(kuò)容時,可以將部分哈希值分配給新加入的機(jī)器并遷移對應(yīng)的數(shù)據(jù)。
另一種思路就是采用一致性哈希算法。算法思想如下:給系統(tǒng)中每個節(jié)點(diǎn)分配一個隨機(jī)token,這些token構(gòu)成一個哈希環(huán)。執(zhí)行數(shù)據(jù)存放操作時,先計算Key(主鍵)的哈希值,然后存放到順時針方向第一個大于或者等于該哈希值得token所在的節(jié)點(diǎn)。一致性哈希的優(yōu)點(diǎn)在于節(jié)點(diǎn)加入/刪除時只影響到在哈希環(huán)中相鄰的節(jié)點(diǎn),而對其他節(jié)點(diǎn)沒影響。
順序分布
哈希散列破壞了數(shù)據(jù)的有序性,只支持隨機(jī)讀操作,不能夠支持順序掃描。順序分布在分布式表格系統(tǒng)中比較常見,一般的做法是將大表順序劃分為連續(xù)的范圍,每個范圍稱為一個子表,總控服務(wù)器負(fù)責(zé)將這些子表按照一定的策略分配到存儲節(jié)點(diǎn)上。
例如,用戶表(User表)的主鍵范圍為為1~7000,在分布式存儲系統(tǒng)中劃分為多個子表,分別對應(yīng)數(shù)據(jù)范圍1~1000,1001~2000,…,6001~7000。某些系統(tǒng)只有根表(Root表)一級索引,在Root表中維護(hù)用戶表的位置信息,即每個用戶子表存放在哪個存儲節(jié)點(diǎn)上。為了支持更大的集群規(guī)模,Bigtable這樣的系統(tǒng)將索引分為兩級:根表以及元數(shù)據(jù)表(Meta表),由Meta表維護(hù)User表的位置信息,而Root表維護(hù)Meta表的位置信息。
順序分布與B+樹數(shù)據(jù)結(jié)構(gòu)比較類似,每個子表相當(dāng)于葉子節(jié)點(diǎn),隨著數(shù)據(jù)的插入和刪除,某些子表可能變得很大,某些變得很小,數(shù)據(jù)分布不均勻,系統(tǒng)設(shè)計時需要考慮子表的分裂與合并。
負(fù)載均衡
分布式存儲系統(tǒng)的每個集群中一般都有一個總控節(jié)點(diǎn),其他節(jié)點(diǎn)為工作節(jié)點(diǎn),由總控節(jié)點(diǎn)根據(jù)全局負(fù)載信息進(jìn)行整體調(diào)度。系統(tǒng)運(yùn)行過程中需要不斷地執(zhí)行遷移任務(wù),將數(shù)據(jù)從負(fù)載較高的工作節(jié)點(diǎn)遷移到負(fù)載較低的工作節(jié)點(diǎn)。
工作節(jié)點(diǎn)通過心跳包(Heartbeat,定時發(fā)送)將節(jié)點(diǎn)負(fù)載相關(guān)的信息,如CPU,內(nèi)存,磁盤,網(wǎng)絡(luò)等資源使用率,讀寫次數(shù)及讀寫數(shù)據(jù)量發(fā)送給總控節(jié)點(diǎn)。總控節(jié)點(diǎn)計算出工作節(jié)點(diǎn)的負(fù)載以及需要遷移的數(shù)據(jù),生成遷移任務(wù)放入遷移隊(duì)列中等待執(zhí)行。
分布式存儲系統(tǒng)中往往會存儲數(shù)據(jù)的多個副本,其中一個副本為主副本,其他副本為備副本,由主副本對外提供服務(wù)。遷移備副本不會對服務(wù)造成影響,遷移主副本也可以首先將數(shù)據(jù)的讀寫服務(wù)切換到其他備副本。整個遷移過程可以做到無縫,對用戶完全透明。
復(fù)制
復(fù)制的概述
為了保證分布式存儲系統(tǒng)的高可靠和高可用,數(shù)據(jù)在系統(tǒng)中一般存儲多個副本。當(dāng)某個副本所在的存儲節(jié)點(diǎn)出現(xiàn)故障時,分布式存儲系統(tǒng)能夠?qū)⒎?wù)切換到其他副本,從而實(shí)現(xiàn)自動容錯。分布式存儲系統(tǒng)通過將復(fù)制協(xié)議將數(shù)據(jù)同步到多個存儲節(jié)點(diǎn),并保證多個副本的數(shù)據(jù)一致性。
同一份數(shù)據(jù)的多個副本往往有一個副本為主副本(Primary),其他副本為備副本(Backup),由主副本將數(shù)據(jù)復(fù)制到備副本。復(fù)制協(xié)議分為兩種,強(qiáng)同步復(fù)制以及異步復(fù)制。二者的區(qū)別在于用戶的寫請求是否需要同步到備副本才可以返回成功。假如備副本不止一個,復(fù)制協(xié)議還會要求寫請求至少需要同步到幾個備副本。
主副本將寫請求復(fù)制到其他備副本常見的做法是同步操作日志(Commit Log),主副本首先將操作日志同步到備副本,備副本回放操作日志,完成后通知主副本。等這些操作完成后再通知客戶端寫成功。這種協(xié)議稱為強(qiáng)同步協(xié)議。強(qiáng)同步協(xié)議提供了強(qiáng)一致性,但是,如果備副本出現(xiàn)問題將阻塞寫操作,系統(tǒng)可用性較差。
操作日志的原理很簡單:為了利用磁盤的順序讀寫特性,將客戶端的寫操作先順序?qū)懭氪疟P中,然后應(yīng)用到內(nèi)存中。當(dāng)服務(wù)器宕機(jī)重啟時,只需要回放操作日志就可以恢復(fù)內(nèi)存狀態(tài)。為了提高系統(tǒng)的并發(fā)能力,系統(tǒng)會積攢一定的操作日志再批量寫入到磁盤中,這種技術(shù)稱為成組提交。
如果每次服務(wù)器出現(xiàn)故障都需要回放所有的操作日志,效率是無法忍受的,檢查點(diǎn)(checkpoint)正是為了解決這個問題。系統(tǒng)定期將內(nèi)存狀態(tài)以檢查點(diǎn)文件的形式dump到磁盤中,并記錄檢查點(diǎn)時刻對應(yīng)的操作日志回放點(diǎn)。檢查點(diǎn)文件創(chuàng)建成功后,回放點(diǎn)之前的日志可以被垃圾回收,以后如果服務(wù)器出現(xiàn)故障,只需要回放檢查點(diǎn)之后的操作日志。
強(qiáng)同步復(fù)制和異步復(fù)制都是基于主副本的復(fù)制協(xié)議(Primary-based protocol)。這種方法要求在任何時刻只能有一個副本為主副本,由它來確定寫操作之間的順序。如果主副本出現(xiàn)故障,需要選舉一個備副本稱為新的主副本,這步操作稱為選舉,經(jīng)典的選舉協(xié)議為Paxos協(xié)議。
一致性和可用性是矛盾的,強(qiáng)同步復(fù)制協(xié)議可以保證主備副本之間的一致性,但是備副本出現(xiàn)故障時,也可能阻塞存儲系統(tǒng)的正常寫服務(wù),系統(tǒng)的整體可用性受到影響;異步復(fù)制的可用性相對較好,但是一致性得不到保障,主副本出現(xiàn)故障還有數(shù)據(jù)丟失的可能。
除了基于主副本的復(fù)制協(xié)議,分布式存儲系統(tǒng)還可能使用基于寫多個存儲節(jié)點(diǎn)的復(fù)制協(xié)議(Replicated-write protocol)。比如Dynamo系統(tǒng)中的NWR復(fù)制協(xié)議,其中N為副本數(shù)量,W為寫操作的副本數(shù),R為讀操作的副本數(shù)。NWR協(xié)議中不再區(qū)分主和備,客戶端根據(jù)一定的策略往其中的W個副本寫入數(shù)據(jù),讀其中的R個副本。只要W+R>N,可以保證讀到的副本中至少有一個包含了最新的更新。
一致性與可用性
來自Berkerly的Eric Brewer教授提出了一個著名的CAP理論:一致性(Consistency),可用性(Availability)以及分區(qū)可容忍性(Toleration of network Partition)三者不能同時滿足。
一致性:讀操作總能讀取到之前完成的寫操作結(jié)果。
可用性:讀寫操作始終能夠成功。
分區(qū)可容忍性:系統(tǒng)能夠容忍由于機(jī)器故障、網(wǎng)絡(luò)故障、機(jī)房停電等異常情況所造成的網(wǎng)絡(luò)分區(qū)。
在分布式系統(tǒng)中,分區(qū)可容忍性總是要滿足的,因此一致性和可用性不能同時滿足。存儲系統(tǒng)設(shè)計時需要在一致性和可用性之間權(quán)衡,在某些場景下,不允許丟失數(shù)據(jù),在另外一些場景下,極小的概率丟失部分?jǐn)?shù)據(jù)是允許的,可用性更加重要。例如,Oracle數(shù)據(jù)庫的DataGuard復(fù)制組件包含三種模式:
容錯
隨著集群規(guī)模越來越大,故障發(fā)生的概率也越來越大,大規(guī)模集群每天都有故障發(fā)生。容錯是分布式存儲系統(tǒng)涉及的重要目標(biāo),只有實(shí)現(xiàn)了自動化容錯,才能減少人工運(yùn)維成本,實(shí)現(xiàn)分布式存儲的規(guī)模效應(yīng)。
首先,分布式存儲系統(tǒng)需要能夠檢測到機(jī)器故障,例如通過租約(Lease)協(xié)議實(shí)現(xiàn)。接著,需要能夠?qū)⒎?wù)復(fù)制或者遷移到集群中的其他正常服務(wù)的存儲節(jié)點(diǎn)。
故障檢測
容錯處理的第一步是故障檢測,心跳是一種很自然地想法。假設(shè)總控機(jī)A需要確認(rèn)工作機(jī)B是否發(fā)生故障,那么總控機(jī)A每隔一段時間,比如1秒,向工作機(jī)B發(fā)送一個心跳包。如果一切正常,機(jī)器B將響應(yīng)機(jī)器A的心跳包;否則,機(jī)器A重試了一定次數(shù)后認(rèn)為機(jī)器B發(fā)生了故障。但是,機(jī)器A收不到機(jī)器B的心跳并不能確保機(jī)器B發(fā)生故障并停止了服務(wù),比如可能是A和B之間出現(xiàn)網(wǎng)絡(luò)問題導(dǎo)致A收不到回復(fù)。由于在機(jī)器A“認(rèn)為”機(jī)器B發(fā)生故障后,往往需要將它上面的服務(wù)遷移到集群中的其他服務(wù)器,為了保證強(qiáng)一致性,需要確保機(jī)器B不再提供服務(wù)。
這里的問題是機(jī)器A和機(jī)器B之間需要對“機(jī)器B是否應(yīng)該被認(rèn)為發(fā)生故障且停止服務(wù)”達(dá)成一致。我們可以通過租約(Lease)機(jī)制進(jìn)行故障檢測,機(jī)器A可以通過機(jī)器B發(fā)放租約,機(jī)器B持有的租約在有效期內(nèi)才允許提供服務(wù),否則主動停止服務(wù)。機(jī)器B的租約快要到期的時候向機(jī)器A重新申請租約。正常情況下,機(jī)器B通過不斷申請租約來延長有效期,當(dāng)機(jī)器B出現(xiàn)故障或者與機(jī)器A之間的網(wǎng)絡(luò)發(fā)生故障時,機(jī)器B的租約將過期,從而機(jī)器A能夠確保機(jī)器B不再提供服務(wù),機(jī)器B的服務(wù)可以被安全地遷移到其他服務(wù)器。
故障恢復(fù)
當(dāng)總控機(jī)檢測到工作機(jī)發(fā)生故障時,需要將服務(wù)遷移到其他工作節(jié)點(diǎn)。常見的分布式存儲系統(tǒng)分為兩種結(jié)構(gòu):單層結(jié)構(gòu)和雙層結(jié)構(gòu)。大部分系統(tǒng)為單層結(jié)構(gòu),在系統(tǒng)中對每個數(shù)據(jù)分票維護(hù)多個副本;只有類Bigtable系統(tǒng)為雙層結(jié)構(gòu),將存儲和服務(wù)分為兩層,存儲層對每個數(shù)據(jù)分片維護(hù)多個副本,服務(wù)層只有一個副本提供服務(wù)。單層結(jié)構(gòu)和雙層結(jié)構(gòu)的故障恢復(fù)機(jī)制有所不同。
單層結(jié)構(gòu)和雙層結(jié)構(gòu)如下圖所示:
單層結(jié)構(gòu)的分布式存儲系統(tǒng)維護(hù)了多個副本,例如副本個數(shù)為3,主備副本之間通過操作日志同步。如上圖所示,某單層結(jié)構(gòu)的分布式存儲系統(tǒng)有3個數(shù)據(jù)分片A、B、C,每個數(shù)據(jù)分片存儲了三個副本。其中,A1,B1,C1為主副本,分別存儲在節(jié)點(diǎn)1,節(jié)點(diǎn)2以及節(jié)點(diǎn)3.假設(shè)節(jié)點(diǎn)1發(fā)生故障,總控節(jié)點(diǎn)選擇一個最新的副本(比如A2或者A3)來替換A1成為新的主副本并提供寫服務(wù)。
兩層結(jié)構(gòu)的分布式存儲系統(tǒng)會將所有的數(shù)據(jù)持久化寫入底層的分布式文件系統(tǒng),每個數(shù)據(jù)分片同一時刻只有一個提供服務(wù)的節(jié)點(diǎn)。如上圖所示,某雙層結(jié)構(gòu)的分布式存儲系統(tǒng)有3個數(shù)據(jù)分片,A、B和C。它們分別被節(jié)點(diǎn)1,節(jié)點(diǎn)2和節(jié)點(diǎn)3所服務(wù)。當(dāng)節(jié)點(diǎn)1發(fā)生故障時,總控節(jié)點(diǎn)將選擇一個工作節(jié)點(diǎn),比如節(jié)點(diǎn)2,加載A的服務(wù)。由于A的所有數(shù)據(jù)都存儲在共享的分布式文件系統(tǒng)中,節(jié)點(diǎn)2只需要從底層的分布式文件系統(tǒng)讀取A的數(shù)據(jù)并加載到內(nèi)存中。
可擴(kuò)展性
同構(gòu)系統(tǒng)
同構(gòu)系統(tǒng)將存儲節(jié)點(diǎn)分為若干組,組內(nèi)的節(jié)點(diǎn)服務(wù)完全相同的數(shù)據(jù),其中有一個節(jié)點(diǎn)為主節(jié)點(diǎn),其他節(jié)點(diǎn)為備節(jié)點(diǎn)。由于同一個組內(nèi)的節(jié)點(diǎn)服務(wù)相同的數(shù)據(jù),這樣的系統(tǒng)稱為同構(gòu)系統(tǒng)。如下圖所示。
同構(gòu)系統(tǒng)的問題在于增加副本需要遷移的數(shù)據(jù)量太大,假設(shè)每個存儲節(jié)點(diǎn)服務(wù)的數(shù)據(jù)量為1TB,內(nèi)部傳輸帶寬限制為20MB/s,那么增加副本拷貝數(shù)據(jù)需要的時間為1TB/20MB=50000s,大約十幾個小時,由于拷貝數(shù)據(jù)的過程中存儲節(jié)點(diǎn)再次發(fā)生故障的概率很高,所以這樣的架構(gòu)很難做到自動化,不適合大規(guī)模分布式存儲系統(tǒng)。
異構(gòu)系統(tǒng)
大規(guī)模分布式存儲系統(tǒng)要求具有線性可擴(kuò)展性,即隨時加入或者刪除一個或者多個存儲節(jié)點(diǎn),系統(tǒng)的處理能力與存儲節(jié)點(diǎn)的個數(shù)成線性關(guān)系。為了實(shí)現(xiàn)線性可擴(kuò)展性,存儲系統(tǒng)的存儲節(jié)點(diǎn)之間是異構(gòu)的。
異構(gòu)系統(tǒng)將數(shù)據(jù)分為很多大小相近的分片,每個分片的多個副本可以分布到集群的任何一個存儲節(jié)點(diǎn)。如果某個節(jié)點(diǎn)發(fā)生故障,原有的服務(wù)將由整個集群而不是某幾個固定的存儲節(jié)點(diǎn)來恢復(fù)。
如下圖所示,系統(tǒng)中有五個分片(A,B,C,D,E),每個分片包含三個副本,如分片A的三個副本分別為A1,A2以及A3。假如節(jié)點(diǎn)1發(fā)生永久性故障,那么可以從剩余的節(jié)點(diǎn)中任意挑選健康的節(jié)點(diǎn)來增加A,B以及E的副本。由于整個集群都參與到節(jié)點(diǎn)1的故障恢復(fù)過程,故障恢復(fù)時間很短,而且集群規(guī)模越大,優(yōu)勢越明顯。
分布式協(xié)議
分布式系統(tǒng)涉及的協(xié)議很多,例如租約,復(fù)制協(xié)議,一致性協(xié)議,其中以兩階段提交協(xié)議和Paxos協(xié)議最具有代表性。兩階段提交協(xié)議用于保證跨多個節(jié)點(diǎn)操作的原子性,也就是說,跨多個節(jié)點(diǎn)的操作要么在所有節(jié)點(diǎn)上全部執(zhí)行成功,要么全部失敗。Paxos協(xié)議用于確保多個節(jié)點(diǎn)對某個投票(例如哪個節(jié)點(diǎn)成為主節(jié)點(diǎn))達(dá)成一致。
兩階段提交協(xié)議
兩階段提交協(xié)議(Two-phase Commit,2PC)經(jīng)常用來實(shí)現(xiàn)分布式事務(wù),在兩階段提交協(xié)議中,系統(tǒng)一般包含兩類節(jié)點(diǎn):一類為協(xié)調(diào)者(coordinator),通常一個系統(tǒng)中只有一個;另一類為事務(wù)參與者(participants),一般包含多個。顧名思義,兩階段提交協(xié)議由兩個階段組成,如下所述:
兩階段提交協(xié)議可能面臨兩種故障:
Paxos協(xié)議
Paxos協(xié)議用于解決多個節(jié)點(diǎn)之間的一致性問題。多個節(jié)點(diǎn)之間通過操作日志同步數(shù)據(jù),如果只有一個節(jié)點(diǎn)為主節(jié)點(diǎn),那么,很容易確保多個節(jié)點(diǎn)之間操作日志的一致性??紤]到主節(jié)點(diǎn)可能出現(xiàn)故障,系統(tǒng)需要選舉出新的主節(jié)點(diǎn)。Paxos協(xié)議正是用來實(shí)現(xiàn)這個需求。只要保證多個節(jié)點(diǎn)之間操作日志的一致性,就能夠在這些節(jié)點(diǎn)上構(gòu)建高可用的全局服務(wù),例如分布式鎖服務(wù),全局命名和配置服務(wù)等。
為了實(shí)現(xiàn)高可用,主節(jié)點(diǎn)往往將數(shù)據(jù)以操作日志的形式同步到備節(jié)點(diǎn)。如果主節(jié)點(diǎn)發(fā)生故障,備節(jié)點(diǎn)會提議自己成為主節(jié)點(diǎn)。這里存在的問題是網(wǎng)絡(luò)分區(qū)的時候,可能會存在多個備節(jié)點(diǎn)提議(Proposer,提議者)自己成為主節(jié)點(diǎn)。Paxos協(xié)議保證,即使同時存在多個proposer,也能夠保證所有節(jié)點(diǎn)最終達(dá)成一致,即選舉出唯一的主節(jié)點(diǎn)。
大多數(shù)情況下,系統(tǒng)只有一個proposer,他的提議也總是會很快被大多數(shù)節(jié)點(diǎn)接受。步驟如下:
1)批準(zhǔn)(accept):Proposer發(fā)送accept消息要求所有其他節(jié)點(diǎn)(acceptor,接受者)接受某個提議值,acceptor可以接受或者拒絕。
2)確認(rèn)(acknowledge):如果超過一半的acceptor接受,意味著提議值已經(jīng)生效,Proposer發(fā)送acknowledge消息通知所有的acceptor提議生效。
當(dāng)出現(xiàn)網(wǎng)絡(luò)或者其他異常時,系統(tǒng)中可能存在多個Proposer,他們各自發(fā)起不同的提議。這里的提議可以是一個修改操作,也可以是提議自己成為主節(jié)點(diǎn)。如果proposer第一次發(fā)起的accept請求沒有被acceptor中的多數(shù)派批準(zhǔn)(例如與其他proposer的提議沖突),那么,需要完整地執(zhí)行一輪Paxos協(xié)議。過程如下:
1)準(zhǔn)備(prepare):Proposer首先選擇一個提議序號n給其他的acceptor節(jié)點(diǎn)發(fā)送prepare消息。Acceptor收到prepare消息后,如果提議的序號大于他已經(jīng)回復(fù)的所有prepare消息,則acceptor將自己上次接受的提議回復(fù)給proposer,并承諾不再回復(fù)小于n的提議。
2)批準(zhǔn)(accept):Proposer收到了acceptor中的多數(shù)派對于prepare的回復(fù)后,就進(jìn)入批準(zhǔn)階段。如果在之前的prepare階段acceptor回復(fù)了上次接受的提議,那么,proposer選擇其中序號最大的提議值發(fā)給acceptor批準(zhǔn);否則,proposer生成一個新的提議值發(fā)給acceptor批準(zhǔn)。Acceptor在不違背他之前在prepare階段的承諾的前提下,接受這個請求。
3)確認(rèn)(acknowledge):如果超過一半的acceptor接受,提議值生效。Proposer發(fā)送acknowledge消息通知所有的acceptor提議生效。
Paxos協(xié)議需要考慮兩個問題:正確性,即只有一個提議值生效;可終止性,即最后總會有一個提議值生效。Paxos協(xié)議中要求每個生效的提議被acceptor中的多數(shù)派接受,并且每個acceptor不會接受兩個不同的提議,因此可以保證正確性。Paxos協(xié)議并不能嚴(yán)格保證可終止性,但是從Paxos協(xié)議的執(zhí)行過程可以看出來,只要超過一個acceptor接受了提議,proposer很快就會發(fā)現(xiàn),并重新提議其中序號最大的提議值。因此,隨著協(xié)議不斷進(jìn)行,它會往“某個提議值被多數(shù)派接受并生效”這一最終目標(biāo)靠攏。
Paxos與2PC
Paxos協(xié)議和2PC協(xié)議在分布式系統(tǒng)中所起的作用并不相同。Paxos協(xié)議用于保證同一個數(shù)據(jù)分片的多個副本之間的數(shù)據(jù)一致性。當(dāng)這些副本分布到不同的數(shù)據(jù)中心時,這個需求尤其強(qiáng)烈。2PC協(xié)議用于保證多個數(shù)據(jù)分片上的操作的原子性。這些數(shù)據(jù)分片可能分布在不同的服務(wù)器上,2PC協(xié)議保證多臺服務(wù)器上的操作要么全部成功,要么全部失敗。
常見的做法是,將2PC和Paxos協(xié)議結(jié)合起來,通過2PC保證多個數(shù)據(jù)分片上的操作的原子性,通過Paxos協(xié)議實(shí)現(xiàn)同一個數(shù)據(jù)分片的多個副本之間的一致性。另外,通過Paxos協(xié)議解決2PC協(xié)議中協(xié)調(diào)者宕機(jī)問題。當(dāng)2PC協(xié)議中的協(xié)調(diào)者出現(xiàn)故障,通過Paxos協(xié)議選舉出新的協(xié)調(diào)者繼續(xù)提供服務(wù)。
跨機(jī)房部署
在分布式系統(tǒng)中,跨機(jī)房問題一直都是老大難問題。機(jī)房之間的網(wǎng)絡(luò)延遲較大,且不穩(wěn)定??鐧C(jī)房問題主要包含兩個方面:數(shù)據(jù)同步以及服務(wù)切換??鐧C(jī)房部署方案有三個:集群整體切換、單個集群跨機(jī)房、Paxos選主副本。下面分別介紹。
1.集群整體切換
集群整體切換是最為常見的方案。如下圖所示,假設(shè)某系統(tǒng)部署在兩個機(jī)房:機(jī)房1和機(jī)房2。兩個機(jī)房保持獨(dú)立,每個機(jī)房部署單獨(dú)的總控節(jié)點(diǎn),且每個總控節(jié)點(diǎn)各有一個備份節(jié)點(diǎn)。當(dāng)總控節(jié)點(diǎn)出現(xiàn)故障時,能夠自動將機(jī)房內(nèi)的備份節(jié)點(diǎn)切換為總控節(jié)點(diǎn)繼續(xù)提供服務(wù)。另外,兩個機(jī)房部署了相同的副本數(shù),例如數(shù)據(jù)分片A在機(jī)房1存儲的副本為A11和A12,在機(jī)房2部署的副本為A21和A22.在某個時刻,機(jī)房1為主機(jī)房,機(jī)房2為備機(jī)房。
機(jī)房之間的數(shù)據(jù)同步方式可能為強(qiáng)同步或者異步。
如果采用異步模式,那么備用機(jī)房的數(shù)據(jù)總是落后于主機(jī)房。當(dāng)主機(jī)房整體出現(xiàn)故障時,有兩種選擇:要么將服務(wù)切換到備機(jī)房,忍受數(shù)據(jù)丟失的風(fēng)險;要么停止服務(wù),直到主機(jī)房恢復(fù)為止。因此,主備切換往往是手工的,因?yàn)樾枰鶕?jù)業(yè)務(wù)特點(diǎn)選擇“丟失數(shù)據(jù)”或者“停止服務(wù)”。
如果采用強(qiáng)同步模式,那么備機(jī)房的數(shù)據(jù)和主機(jī)房保持一致。當(dāng)主機(jī)房出現(xiàn)故障時,可以通過分布式鎖服務(wù)發(fā)現(xiàn),并自動將備用機(jī)房切換為主機(jī)房。
2.單個集群跨機(jī)房
上一種方案的所有主副本只能同時存在于一個機(jī)房內(nèi),另一種方案是將單個集群部署到多個機(jī)房,允許不同數(shù)據(jù)分片的主副本位于不同的機(jī)房。如下圖所示,每個數(shù)據(jù)分片在機(jī)房1和機(jī)房2,總共包含4個副本,其中A1、B1、C1是主副本,A1和B1在機(jī)房1,C1在機(jī)房2。整個集群只有一個總控節(jié)點(diǎn),它需要同機(jī)房1和機(jī)房2的所有工作節(jié)點(diǎn)保持通信。當(dāng)總控節(jié)點(diǎn)出現(xiàn)故障時,分布式鎖服務(wù)將檢測到,并將機(jī)房2的備份節(jié)點(diǎn)切換為總控節(jié)點(diǎn)。
如果采用這種部署方式,總控節(jié)點(diǎn)在執(zhí)行數(shù)據(jù)分布時,需要考慮機(jī)房信息,也就是說,盡量將同一個數(shù)據(jù)分片的多個副本分布到多個機(jī)房,從而防止單個機(jī)房出現(xiàn)故障而影響正常服務(wù)。
3.Paxos選主副本
在前兩種方案中,總控節(jié)點(diǎn)需要和工作節(jié)點(diǎn)之間保持租約(lease),當(dāng)工作節(jié)點(diǎn)出現(xiàn)故障時,自動將它上面服務(wù)的主副本切換到其他工作節(jié)點(diǎn)。
如果采用Paxos選主副本,那么,每個數(shù)據(jù)分片的多個副本構(gòu)成一個Paxos復(fù)制組。如下圖所示,B1、B2、B3、B4構(gòu)成一個復(fù)制組,某一時刻B1為復(fù)制組的主副本,當(dāng)B1出現(xiàn)故障時,其他副本將嘗試切換為主副本,Paxos協(xié)議保證只有一個副本會成功。這樣,總控節(jié)點(diǎn)和工作節(jié)點(diǎn)之間不再需要保持租約,總控節(jié)點(diǎn)出現(xiàn)故障也不會對工作節(jié)點(diǎn)產(chǎn)生影響。
Google后續(xù)開發(fā)的系統(tǒng),包括Google Megastore以及Spanner,都采用了這種方式。它的優(yōu)點(diǎn)在于能夠降低對總控節(jié)點(diǎn)的依賴,缺點(diǎn)在于工程復(fù)雜度太高,難以在線下模擬所有的異常情況。

我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流