DDIA 7. 分布式系統(tǒng)的麻煩

目錄

  1. 局部故障(部分失效是不確定性的)
  2. 不可靠的網(wǎng)絡(luò)(超時(shí)的3種情況,trade off 超時(shí)間隔太長或太短的問題)
  3. 不可靠的時(shí)鐘 (單調(diào)鐘vs時(shí)鐘,事件的時(shí)間戳排序的問題)
  4. 不可靠的租約(柵欄令牌)
  5. 不可靠的節(jié)點(diǎn)(拜占庭問題)

故障

當(dāng)我們在使用單機(jī)系統(tǒng)時(shí),它通常以一種相當(dāng)可預(yù)測的方式工作:要么它正常工作,要么不工作。

而當(dāng)我們在使用分布式系統(tǒng)時(shí),情況就不同了。在分布式系統(tǒng)中,系統(tǒng)的某些部分可能以某種不可預(yù)知的方式被破壞,即使系統(tǒng)的其他部分工作正常。這種故障通常是不確定的:如果你想做涉及多個(gè)節(jié)點(diǎn)和網(wǎng)絡(luò)的東西,可能甚至不知道某個(gè)消息是否成功,因?yàn)橄⒋┰骄W(wǎng)絡(luò)所需的時(shí)間也是不確定的。

這種故障的不確定性,使得分布式系統(tǒng)的變得復(fù)雜而脆弱。一個(gè)系統(tǒng)越大,它的組件就越有可能出現(xiàn)故障。在一個(gè)有成千上萬個(gè)節(jié)點(diǎn)的系統(tǒng)中,某些東西總是會出現(xiàn)故障。而錯(cuò)誤處理策略僅僅是簡單的放棄的話,一個(gè)大系統(tǒng)可能會花費(fèi)大量時(shí)間從故障中恢復(fù),而不是做有用的工作。所以我們需要分布式系統(tǒng)能夠容忍失敗的節(jié)點(diǎn),并且仍然保持整體工作,將容錯(cuò)機(jī)制建立到軟件中。換句話說,分布式系統(tǒng)需要從不可靠的組件中建立一個(gè)可靠的系統(tǒng)。

不可靠的網(wǎng)絡(luò)

分布式系統(tǒng)是一組由網(wǎng)絡(luò)連接的機(jī)器組成的。網(wǎng)絡(luò)是這些機(jī)器通信的唯一方式,每臺機(jī)器都有自己的內(nèi)存和磁盤,一臺機(jī)器不能訪問另一臺機(jī)器的內(nèi)存或磁盤。在網(wǎng)絡(luò)中,一個(gè)節(jié)點(diǎn)可以向另一個(gè)節(jié)點(diǎn)發(fā)送消息,但是網(wǎng)絡(luò)不能保證它何時(shí)到達(dá)或是否到達(dá),所以網(wǎng)絡(luò)是不可靠的。

不可靠的網(wǎng)絡(luò)系統(tǒng)

如上圖所示,如果發(fā)送的請求并沒有得到響應(yīng),則無法區(qū)分
(a)請求丟失
(b)遠(yuǎn)程節(jié)點(diǎn)失效
(c)響應(yīng)丟失。
處理這個(gè)問題的通常方法是超時(shí):一段時(shí)間后,發(fā)送方放棄等待,并假定響應(yīng)不會到達(dá)。但是,當(dāng)超時(shí)發(fā)生時(shí),遠(yuǎn)程節(jié)點(diǎn)可能已經(jīng)得到請求并進(jìn)行了處理。

故障檢測

由于網(wǎng)絡(luò)的不確定性使得很難判斷一個(gè)節(jié)點(diǎn)是否工作。分布式系統(tǒng)當(dāng)中常用的便是超時(shí)檢測的機(jī)制。如果超時(shí)檢測是檢測故障的方法,那么超時(shí)應(yīng)該是多長時(shí)間呢?不幸的是,沒有簡單的答案。

長的超時(shí)時(shí)間意味著需要等待一個(gè)節(jié)點(diǎn)被宣告死亡。短的超時(shí)時(shí)間會更快地檢測到故障,但是事實(shí)上節(jié)點(diǎn)并沒有停止工作(例如由于節(jié)點(diǎn)或網(wǎng)絡(luò)過載)時(shí),會錯(cuò)誤地檢測一個(gè)節(jié)點(diǎn)失效。如果節(jié)點(diǎn)實(shí)際上是活著的,在執(zhí)行某些操作的時(shí),工作另一個(gè)節(jié)點(diǎn)接管,則該操作可能最終執(zhí)行兩次。而且當(dāng)一個(gè)節(jié)點(diǎn)失效時(shí),它的責(zé)任需要轉(zhuǎn)移到其他節(jié)點(diǎn),這將額外的負(fù)載放到其他節(jié)點(diǎn)和網(wǎng)絡(luò)上。如果系統(tǒng)已經(jīng)處于高負(fù)載之下,過早檢測節(jié)點(diǎn)失效會使問題變得更糟。特別是,它可能發(fā)生的是節(jié)點(diǎn)實(shí)際上沒有時(shí)效,但由于過載而響應(yīng)緩慢,將其負(fù)載轉(zhuǎn)移到其他節(jié)點(diǎn)會導(dǎo)致級聯(lián)故障。

目前學(xué)界和業(yè)界的趨勢是:不使用常數(shù)配置的超時(shí),而是系統(tǒng)可以連續(xù)測量的響應(yīng)時(shí)間和響應(yīng)時(shí)間的抖動(dòng),并自動(dòng)調(diào)整超時(shí)時(shí)間根據(jù)所觀察到的響應(yīng)時(shí)間動(dòng)態(tài)分布。如Akka的超時(shí)器,Cassandra的動(dòng)態(tài)檢測,TCP的超時(shí)重傳。

不可靠的時(shí)間

在分布式系統(tǒng)中,時(shí)間是一件棘手的事情,因?yàn)橥ㄐ挪皇撬矔r(shí)的:消息穿越網(wǎng)絡(luò)從一臺機(jī)器轉(zhuǎn)到另一臺機(jī)器需要時(shí)間。消息接收的時(shí)間總是比發(fā)送的時(shí)間晚,但由于網(wǎng)絡(luò)中的可變延遲,我們不知道以后會有多少延遲。很難確定多臺機(jī)器處理的邏輯與順序。

每臺機(jī)器都有自己的時(shí)鐘,通常是一個(gè)石英晶體振蕩器。這些設(shè)備并不完全準(zhǔn)確,所以每臺機(jī)器都有自己的時(shí)間,它可能比其他機(jī)器稍快或慢一些。存在同步時(shí)鐘的網(wǎng)絡(luò)協(xié)議:最常用的機(jī)制是網(wǎng)絡(luò)時(shí)間協(xié)議(NTP),它允許計(jì)算機(jī)時(shí)鐘根據(jù)一組服務(wù)器報(bào)告的時(shí)間進(jìn)行調(diào)整。服務(wù)器可以從更精確的時(shí)間源獲取時(shí)間。

時(shí)鐘:

UTC時(shí)間以1970年1月1日為開始,根據(jù)公歷,忽略閏秒,來計(jì)算當(dāng)前時(shí)間。計(jì)算機(jī)時(shí)鐘通常與NTP同步,這意味著一臺機(jī)器的時(shí)間戳(理想情況下)意味著與另一臺機(jī)器上的時(shí)間戳相同。

單調(diào)的時(shí)間:

您可以在一個(gè)時(shí)間點(diǎn)檢查時(shí)鐘的值,然后再一次檢查時(shí)鐘。兩個(gè)值之間的差異告訴你這兩個(gè)檢查之間要花多少時(shí)間。在分布式系統(tǒng)中,通過一個(gè)單調(diào)的時(shí)鐘測量時(shí)間(如超時(shí))通常是好的,因?yàn)樗怀袚?dān)不同的節(jié)點(diǎn)的時(shí)鐘之間的同步的細(xì)微誤差。

事件的時(shí)間戳排序

跨多個(gè)節(jié)點(diǎn)的事件排序是一個(gè)令人頭疼的問題。例如,如果兩個(gè)客戶機(jī)向分布式數(shù)據(jù)庫寫入,誰首先到達(dá)?哪個(gè)是最近寫的? 如下圖所示:

image.png

寫x = 1的時(shí)間戳是42.004秒,但寫x = 2的時(shí)間戳42.003秒。當(dāng)Node 2接收到這兩個(gè)事件時(shí),它會錯(cuò)誤地得出結(jié)論:x = 1是最新的值,忽略x=2的寫入。Client B的增量操作將會丟失。這種沖突解決策略被稱為最后寫者勝(LWW),會導(dǎo)致一個(gè)具有滯后時(shí)鐘的節(jié)點(diǎn)無法覆蓋以前用一個(gè)快速時(shí)鐘寫入的節(jié)點(diǎn)的值,直到節(jié)點(diǎn)之間的時(shí)鐘偏差消失。

所以對于有嚴(yán)格時(shí)序要求的系統(tǒng),需要使用邏輯時(shí)鐘(比如:Lamport Clock,Lanport老爺子真的是分布式領(lǐng)域的上古神牛啊~~~),這是基于遞增計(jì)數(shù)器是一個(gè)來判斷事件的更迭順序。邏輯時(shí)鐘不測量每天的時(shí)間或經(jīng)過的秒數(shù),只有事件的相對順序,也就是判斷一個(gè)事件是否發(fā)生在另一個(gè)事件之前或之后。

4.不可靠的租約

在分布式系統(tǒng)之中,有時(shí)需要確保在存儲服務(wù)文件只能同時(shí)被一個(gè)客戶端訪問,因?yàn)槿绻鄠€(gè)客戶端試圖寫它,文件會被損壞。您需要通過在訪問文件之前從鎖服務(wù)獲得租約來實(shí)現(xiàn)分布式鎖。但是有時(shí)這個(gè)鎖并非有我們想象的可靠,如下圖所示:

不正確的執(zhí)行分布式租約

如果持有租約的客戶端 1 因?yàn)镚C等原因暫停太久,而它的租約到期了。另一個(gè)客戶端 2 可以獲取租約,并開始向文件寫入數(shù)據(jù)。當(dāng)暫停的客戶端1返回時(shí),它仍然認(rèn)為自己擁有一個(gè)有效的租約,并且繼續(xù)寫入數(shù)據(jù)。于是造成了寫入沖突。

柵欄令牌

我們可以使用柵欄令牌的方式,讓不可靠的租約變的更加可靠,如下圖所示:

通過柵欄令牌來確保寫入安全

鎖服務(wù)器可以在每次授予租約時(shí),返回一個(gè)令牌,它是一個(gè)在每次授予鎖時(shí)增加的數(shù)字ID。每次客戶端發(fā)出一個(gè)寫請求時(shí),必須包含當(dāng)前的租約令牌。而存儲服務(wù)會記錄寫入的租約令牌,成為一個(gè)柵欄,舊的令牌寫入將被存儲服務(wù)拒絕。

拜占庭問題

第12章 拜占庭容錯(cuò)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容