雖然之前數(shù)個(gè)章節(jié)介紹了分布式系統(tǒng)各種可能的錯(cuò)誤檀轨,但是之前的估計(jì)仍然過于樂觀线欲,原因在于碎连,分布式系統(tǒng)的故障和單節(jié)點(diǎn)的故障有著顯著區(qū)別搞动。本章對(duì)于分布式系統(tǒng)可能出現(xiàn)的故障做出了全面躏精、悲觀的總結(jié)。
故障與部分失效
對(duì)于單個(gè)節(jié)點(diǎn)上運(yùn)行的程序鹦肿,一個(gè)質(zhì)量合格的軟件要么是功能正常矗烛,要么是完全失效,而不會(huì)介于兩者之間箩溃。
對(duì)于多個(gè)節(jié)點(diǎn)上運(yùn)行的分布式軟件瞭吃,情況將要復(fù)雜和混亂很多,系統(tǒng)中可能只有一部分工作正常涣旨,或者節(jié)點(diǎn)正常但是網(wǎng)絡(luò)出現(xiàn)故障歪架。
云計(jì)算與超算
構(gòu)建大規(guī)模計(jì)算系統(tǒng)具有兩種不同的思路:
- 高性能計(jì)算:包含成千上萬個(gè)CPU的超級(jí)計(jì)算機(jī)構(gòu)成一個(gè)龐大的集群
- 云計(jì)算:具有多個(gè)數(shù)據(jù)中心,彈性/按需分配資源
相比之下霹陡,高性能計(jì)算更類似于單節(jié)點(diǎn)系統(tǒng)而不是分布式系統(tǒng)和蚪,書中重點(diǎn)為基于互聯(lián)網(wǎng)的服務(wù)系統(tǒng),相比于高性能計(jì)算具有以下不同:
- 云計(jì)算通常用于提供在線服務(wù)穆律,需要隨時(shí)提供低延遲的服務(wù)惠呼,高性能計(jì)算通常承擔(dān)批處理任務(wù)
- 云計(jì)算服務(wù)通常采用通用機(jī)器構(gòu)建,而高性能計(jì)算常采用專用硬件構(gòu)建
- 云計(jì)算各個(gè)節(jié)點(diǎn)間通常采用IP與以太網(wǎng)通信峦耘,高性能計(jì)算則通常采用特定的網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)
不可靠的網(wǎng)絡(luò)
互聯(lián)網(wǎng)與大多數(shù)網(wǎng)絡(luò)中心的內(nèi)部網(wǎng)絡(luò)都是異步網(wǎng)絡(luò)剔蹋,一個(gè)節(jié)點(diǎn)可以向另一個(gè)節(jié)點(diǎn)發(fā)送消息當(dāng)時(shí)不保證是否能到達(dá),不保證何時(shí)到達(dá)辅髓,在發(fā)送后等待的過程中泣崩,可能發(fā)生請(qǐng)求丟失,請(qǐng)求在隊(duì)列中排隊(duì)洛口,遠(yuǎn)程接受節(jié)點(diǎn)崩潰矫付,遠(yuǎn)程接受節(jié)點(diǎn)暫時(shí)無法相應(yīng),應(yīng)答丟失第焰,應(yīng)答被延遲處理等各種情況买优。
發(fā)送者不清楚數(shù)據(jù)包是否成功發(fā)送,只能通過接收者的應(yīng)答來確定,但是應(yīng)答也可能出現(xiàn)丟失活延遲杀赢,因此通常采用超時(shí)機(jī)制處理烘跺。
現(xiàn)實(shí)中的網(wǎng)絡(luò)故障
網(wǎng)絡(luò)分區(qū):網(wǎng)絡(luò)被分隔為斷開的幾個(gè)部分
檢測故障
系統(tǒng)需要能夠自動(dòng)檢測節(jié)點(diǎn)失效,通常具有以下功能:
- 下線:避免已經(jīng)失效的節(jié)點(diǎn)繼續(xù)分發(fā)請(qǐng)求
- 選舉:對(duì)于主從復(fù)制數(shù)據(jù)區(qū)脂崔,如果主節(jié)點(diǎn)失敗滤淳,需要將某個(gè)從節(jié)點(diǎn)提升為主節(jié)點(diǎn)
但是檢測節(jié)點(diǎn)的失效是困難的,或許可以從應(yīng)用級(jí)別獲取錯(cuò)誤報(bào)告砌左,但是還是應(yīng)假設(shè)無法接收到任何錯(cuò)誤報(bào)告脖咐。重試是另一種解決方案,在等待超時(shí)后汇歹,如果沒有收到響應(yīng)則最終聲明節(jié)點(diǎn)失效屁擅。
超時(shí)與無限期的延遲
如果超時(shí)是檢測失效唯一的可行方案,那么超時(shí)時(shí)間長度的設(shè)定同樣是個(gè)問題秤朗。設(shè)置較長的失效時(shí)間閾值會(huì)導(dǎo)致需要較長的時(shí)間煤蹭,設(shè)置較短的失效時(shí)間閾值會(huì)導(dǎo)致系統(tǒng)對(duì)于網(wǎng)絡(luò)或性能的波動(dòng)過于敏感,如果一個(gè)節(jié)點(diǎn)被宣布失效取视,則會(huì)發(fā)生節(jié)點(diǎn)切換硝皂,為網(wǎng)絡(luò)帶來更多負(fù)擔(dān),從而加劇網(wǎng)絡(luò)問題作谭。
網(wǎng)絡(luò)擁塞與排隊(duì)
網(wǎng)絡(luò)上數(shù)據(jù)包的排隊(duì)是延遲的重要誘因稽物,網(wǎng)絡(luò)交換機(jī)擁擠,CPU繁忙折欠,容器切換贝或,TCP擁塞控制都可能引起排隊(duì),以上因素都導(dǎo)致網(wǎng)絡(luò)的延遲非常不確定锐秦,超時(shí)設(shè)置并不是一個(gè)不變的常量咪奖,而是持續(xù)測量響應(yīng)時(shí)間及其變化。
同步與異步網(wǎng)絡(luò)
對(duì)于傳統(tǒng)的電話酱床,系統(tǒng)會(huì)為每個(gè)電話連接建立一條電路羊赵,這種網(wǎng)絡(luò)本質(zhì)上是同步的。
網(wǎng)絡(luò)延遲是否可以預(yù)測
傳統(tǒng)的電話能夠使用的帶寬是固定的扇谣,而TCP連接的數(shù)據(jù)包嘗試使用所有的網(wǎng)絡(luò)帶寬昧捷,以太網(wǎng)和IP都是基于分組交換的。TCP帶寬動(dòng)態(tài)調(diào)整與面向分組的特性使得帶寬可以更高效的利用罐寨,節(jié)約了成本靡挥。
不可靠的時(shí)鐘
不同節(jié)點(diǎn)的設(shè)備都具有自己的物理時(shí)鐘,但是各個(gè)設(shè)備的時(shí)鐘或快或慢鸯绿,雖然NTP可以從一定程度上同步時(shí)鐘跋破,但是并不足夠精確簸淀,時(shí)鐘的不同步導(dǎo)致了難以確定事件發(fā)生的先后順序。
單調(diào)時(shí)鐘與墻上時(shí)鐘
墻上時(shí)鐘
子1970年1月1日0點(diǎn)至今的秒數(shù)與毫秒數(shù)毒返,不包含閏秒啃擦,墻上時(shí)鐘可以與NTP同步,但是精度較為粗糙饿悬。
單調(diào)時(shí)鐘
單調(diào)時(shí)鐘保證總總是向前的,不會(huì)出現(xiàn)墻上時(shí)鐘由于閏秒產(chǎn)生的回?fù)墁F(xiàn)象聚霜,單調(diào)時(shí)鐘的絕對(duì)值沒有意義狡恬,比較不同節(jié)點(diǎn)上的單調(diào)時(shí)鐘同樣沒有意義,因?yàn)閱握{(diào)時(shí)鐘沒有固定的基準(zhǔn)蝎宇。單調(diào)時(shí)鐘可以用于測量一項(xiàng)任務(wù)的持續(xù)時(shí)間弟劲,但是不假設(shè)有任何的時(shí)鐘同步。
時(shí)鐘同步與準(zhǔn)確性
時(shí)鐘可能出現(xiàn)的問題:晶振漂移姥芥,NTP連接失敗兔乞,NTP拒絕授時(shí),NTP網(wǎng)絡(luò)延遲凉唐,NTP服務(wù)器故障庸追,閏秒,虛擬機(jī)導(dǎo)致的虛擬化時(shí)鐘台囱,設(shè)備時(shí)鐘不可控等淡溯。
依賴同步的時(shí)鐘
時(shí)鐘看起來簡單,但是存在閏秒等問題簿训,對(duì)于高精度依賴于時(shí)鐘的軟件咱娶,時(shí)鐘的偏差是可能產(chǎn)生致命后果的。
時(shí)間戳與事件順序
對(duì)于最后寫入獲勝(LWW)策略强品,但是LWW策略存在一定的問題:
- 由于時(shí)鐘速度差異膘侮,先寫入的數(shù)據(jù)可能反而被保留
- LWW無法區(qū)分連續(xù)寫操作(客戶端A寫入后客戶端B才發(fā)生增量操作)與并發(fā)寫入(每個(gè)寫操作都不依賴其他寫)
- 由于時(shí)鐘精度問題,兩個(gè)節(jié)點(diǎn)可能產(chǎn)生完全相同的時(shí)間戳
即使采用NTP進(jìn)行時(shí)鐘同步的榛,時(shí)鐘仍然存在不精確的問題琼了,如果需要進(jìn)行排序,可以基于邏輯時(shí)鐘困曙,也就是遞增計(jì)數(shù)器表伦。
時(shí)鐘的置信區(qū)間
由于NTP的誤差,不應(yīng)當(dāng)將時(shí)鐘的讀數(shù)視為一個(gè)精確的時(shí)間點(diǎn)慷丽,而應(yīng)該視為一個(gè)具有置信區(qū)間的范圍蹦哼,Google Spanner中的TrueTime API會(huì)告知本地時(shí)間的置信范圍,查詢會(huì)得到兩個(gè)值[不早于要糊,不晚于]纲熏。
全局快照的同步時(shí)鐘
通常實(shí)現(xiàn)快照隔離需要單調(diào)遞增的事務(wù)ID,但是對(duì)于分布式事務(wù)則需要全局單調(diào)遞增的事務(wù)ID。那么是否可以利用同步后的墻上時(shí)鐘作為事務(wù)ID局劲?利用時(shí)鐘的置信區(qū)間勺拣,在提交事務(wù)時(shí)等待置信區(qū)間的長度可以避免事務(wù)的重疊。
進(jìn)程暫停
對(duì)于主從復(fù)制的系統(tǒng)鱼填,主節(jié)點(diǎn)需要維持自己主節(jié)點(diǎn)的身份药有,一種思路為主節(jié)點(diǎn)定時(shí)向其他節(jié)點(diǎn)獲取一個(gè)租約,但是采用這種方式可能會(huì)因?yàn)檫M(jìn)程的暫停導(dǎo)致問題出現(xiàn)苹丸,導(dǎo)致進(jìn)程暫停的可能有很多:垃圾回收愤惰,虛擬機(jī)切換,進(jìn)程上下文切換赘理,磁盤或網(wǎng)絡(luò)I/O宦言,缺頁中斷,OS命令商模。分布式系統(tǒng)必須假定執(zhí)行過程中的進(jìn)程可能隨時(shí)暫停相當(dāng)長的時(shí)間奠旺。
響應(yīng)時(shí)間保證
對(duì)于應(yīng)用于航天等場合的嵌入式設(shè)備,可以通過RTOS保證實(shí)時(shí)性施流,但是對(duì)于服務(wù)器來說保證實(shí)時(shí)性并不合適响疚。
調(diào)整垃圾回收的影響
調(diào)整垃圾回收的策略,從而減少垃圾回收對(duì)于進(jìn)程暫停的影響嫂沉。
知識(shí)稽寒,真相與謊言
本部分用于介紹在構(gòu)建分布式系統(tǒng)時(shí)進(jìn)行的假設(shè)。
真相又多數(shù)決定
首先趟章,節(jié)點(diǎn)自身是無法判斷自身的狀態(tài)的杏糙,分布式系統(tǒng)中的決策需要依靠法定票數(shù),最常見的法定票數(shù)是取節(jié)點(diǎn)半數(shù)以上蚓土。
主節(jié)點(diǎn)與鎖
在很多情況下宏侍,分布式系統(tǒng)只允許在系統(tǒng)內(nèi)具有一個(gè)實(shí)例,例如主從復(fù)制模式中只有一個(gè)主節(jié)點(diǎn)蜀漆,只允許一個(gè)事務(wù)或客戶端持有特定資源的鎖谅河,尤其需要注意的是,某個(gè)節(jié)點(diǎn)自認(rèn)為自己是唯一的一個(gè)确丢,但并不一定獲得了系統(tǒng)內(nèi)法定票數(shù)的同意绷耍。例如持有租約的主節(jié)點(diǎn)可能因?yàn)檫M(jìn)程暫停失去主節(jié)點(diǎn)身份,但是仍然自認(rèn)為是主節(jié)點(diǎn)從而向其他節(jié)點(diǎn)發(fā)送指令或修改存儲(chǔ)鲜侥,從而引發(fā)破壞褂始。
Fencing令牌
可以通過fencing機(jī)制保證節(jié)點(diǎn)可以意識(shí)到租約過期,原理為在授予鎖或租約時(shí)描函,返回一個(gè)fensing令牌崎苗,令牌每授予一次就會(huì)遞增狐粱,擁有鎖的節(jié)點(diǎn)在對(duì)于存儲(chǔ)進(jìn)行修改時(shí)需附帶令牌編號(hào),存儲(chǔ)服務(wù)會(huì)記錄各個(gè)修改請(qǐng)求中的令牌編號(hào)胆数,如果某個(gè)請(qǐng)求中令牌編號(hào)小于記錄中的最大值肌蜻,則拒絕此次服務(wù)。這種方式要求資源必須檢查鎖編號(hào)必尼,并能主動(dòng)拒絕蒋搜。
拜占庭故障
fensing令牌可以排除無意的誤操作,但是如果節(jié)點(diǎn)故意破壞系統(tǒng)判莉,只需要偽造令牌即可齿诞。本書總是假設(shè)節(jié)點(diǎn)不一定可靠,但總是誠實(shí)骂租,而在互不信任的環(huán)境中達(dá)到的共識(shí)則稱為拜占庭將軍問題。
系統(tǒng)中的某些節(jié)點(diǎn)由于故障導(dǎo)致不遵守協(xié)議或惡意攻擊斑司,但仍可以繼續(xù)運(yùn)行渗饮,那么稱為拜占庭式容錯(cuò)系統(tǒng),例如航天領(lǐng)域可能由于輻射導(dǎo)致寄存器數(shù)據(jù)發(fā)生改變宿刮,比特幣系統(tǒng)用于讓互不信任的當(dāng)事方對(duì)于交易達(dá)成一致互站。不過本書中通常不需要考慮部署拜占庭式容錯(cuò)系統(tǒng)。
弱的謊言形式
通常節(jié)點(diǎn)是誠實(shí)的僵缺,但是需要一些方式避免一些弱的胡桃、無意的謊言,這種謊言可能是由于硬件故障磕潮,配置錯(cuò)誤等原因引起的翠胰,可采用的方法有:
- 添加數(shù)據(jù)校驗(yàn)和
- 對(duì)于開放輸入內(nèi)容則檢測用戶輸入,防止SQL注入等操作
- 對(duì)于NTP等服務(wù)自脯,可以采用多個(gè)授時(shí)服務(wù)器
理論系統(tǒng)模型與現(xiàn)實(shí)
分布式系統(tǒng)的構(gòu)建需要定義一些系統(tǒng)模型來形式化描述算法的前提條件之景。
計(jì)時(shí)模型:
- 同步模型:由上界的網(wǎng)絡(luò)延遲、進(jìn)程暫停和時(shí)鐘誤差
- 部分同步模型:大部分情況下如同同步系統(tǒng)一樣運(yùn)行膏潮,但有時(shí)延遲锻狗、進(jìn)程暫停、時(shí)鐘誤差會(huì)超出上限
- 異步模型:不對(duì)時(shí)間做出任何假設(shè)
節(jié)點(diǎn)失效模型:
崩潰-中止模型:節(jié)點(diǎn)只會(huì)在發(fā)生故障后永久消失
崩潰-恢復(fù)模型:節(jié)點(diǎn)在故障后焕参,可能在一段未知長度的時(shí)間后恢復(fù)并再次響應(yīng)
-
拜占庭失效模型:節(jié)點(diǎn)可能發(fā)生任何故障轻纪,包括試圖作弊或欺騙
對(duì)于真實(shí)系統(tǒng)的建模,通常在兩方面都折中叠纷,即采用部分同步模型和崩潰-恢復(fù)模型刻帚。
算法的正確性
為了描述分布式算法的正確性,可以通過描述目標(biāo)分布式系統(tǒng)的相關(guān)屬性來定義其正確性讲岁,如果某種算法在各種情況下都能滿足屬性要求我擂,那么這個(gè)算法就是正確的衬以。
安全與活性
安全性可理解為“沒有發(fā)生意外”,活性可以理解為“預(yù)期的事情最終一定會(huì)發(fā)生“校摩,如果違反了安全性看峻,可以明確指向發(fā)生的特定時(shí)間點(diǎn),如果違反了活性衙吩,可能無法明確指向具體的時(shí)間點(diǎn)互妓。
對(duì)于分布式系統(tǒng),要求在所有可能的情況下都符合安全性坤塞,也就是即便任何故障發(fā)生都不會(huì)返回錯(cuò)誤結(jié)果冯勉,而對(duì)于活性則可以放寬,只在一定條件滿足時(shí)達(dá)成活性摹芙,例如必須多數(shù)節(jié)點(diǎn)沒有崩潰灼狰,且網(wǎng)絡(luò)最終可以恢復(fù)時(shí)滿足活性。
將系統(tǒng)模型映射到現(xiàn)實(shí)世界
理論上的模型和現(xiàn)實(shí)世界還有差距浮禾。
小結(jié)
本章討論遵循以下邏輯進(jìn)行:
- 分布式系統(tǒng)的特點(diǎn)
- 不可靠的網(wǎng)絡(luò)
- 不可靠的時(shí)鐘
- 進(jìn)程暫停
- 謊言