分布式系統(tǒng):問題及其可復用的解決方案
作者: Unmesh Joshi
譯者: java達人
在過去的幾個月中,我一直在ThoughtWorks上進行有關(guān)分布式系統(tǒng)的研討會。舉辦研討會時面臨的主要挑戰(zhàn)之一是如何將分布式系統(tǒng)的理論映射到諸如Kafka或Cassandra之類的開源代碼庫,同時保持研討的通用性足以涵蓋廣泛的解決方案。模式的概念提供了一個不錯的方式。
模式結(jié)構(gòu)本質(zhì)上使我們能夠?qū)W⒂谔囟▎栴},從而很清楚地說明了為什么需要特定解決方案。然后,解決方案描述中給出一個代碼結(jié)構(gòu),該結(jié)構(gòu)足夠具體以顯示實際的解決方案,但又足夠通用以涵蓋各種變體。模式技術(shù)還允許我們將各種模式鏈接在一起以構(gòu)建一個完整的系統(tǒng)。這為討論分布式系統(tǒng)實現(xiàn)提供了很好的術(shù)語。
接下來是在主流開源分布式系統(tǒng)中觀察到的第一組模式。我希望這些模式集對所有開發(fā)人員都有用。
分布式系統(tǒng) - 實現(xiàn)的角度來看
當今的企業(yè)體系結(jié)構(gòu)充滿了自然分布的平臺和框架。如果我們看到今天在典型的企業(yè)體系結(jié)構(gòu)中使用的框架和平臺的示例列表,它將類似于以下內(nèi)容:
所有這些本質(zhì)上都是“分布式的”。分布式系統(tǒng)意味著什么?有兩個方面:
?它們在多臺服務器上運行。集群中的服務器數(shù)量可以從三臺到幾千臺不等。
? 它們管理數(shù)據(jù)。因此,這些天生就是“有狀態(tài)”的系統(tǒng)。
當多個服務器參與數(shù)據(jù)存儲時,有幾種途徑可能會導致問題。上述所有系統(tǒng)都需要解決這些問題。這些系統(tǒng)的實現(xiàn)對這些問題有一些可復用的解決方案。理解這些解決方案的一般形式,有助于理解這些系統(tǒng)的廣泛實現(xiàn),并且在需要構(gòu)建新系統(tǒng)時也可以作為很好的指導。下面進入模式章節(jié)。
問題及其可復用的解決方案
當數(shù)據(jù)存儲在多個服務器上時,可能會出現(xiàn)幾個問題。
進程崩潰
進程隨時會由于硬件故障或軟件故障崩潰。進程崩潰的方式有很多種。
?系統(tǒng)管理員可以將其下線進行日常維護。?由于磁盤已滿并且該異常無法正確被處理,因此在執(zhí)行某些文件IO時被殺死。?在云環(huán)境中,這可能會更加棘手,因為一些不相關(guān)的事件可能會使服務器宕機。
最重要的是,如果進程負責存儲數(shù)據(jù),則必須對存儲在服務器上的數(shù)據(jù)提供持久性保證。即使進程突然崩潰,它也應保留所有已通知用戶已成功存儲的數(shù)據(jù)。根據(jù)訪問模式,不同的存儲引擎具有不同的存儲結(jié)構(gòu),從簡單的哈希映射到復雜的圖存儲。由于將數(shù)據(jù)刷新到磁盤是最耗時的操作之一,因此無法將每次對存儲的插入或更新都刷新到磁盤。因此,大多數(shù)數(shù)據(jù)庫都具有內(nèi)存存儲結(jié)構(gòu),這些存儲結(jié)構(gòu)僅定期刷新到磁盤。如果進程突然崩潰,則可能會丟失所有數(shù)據(jù)。
一種稱為Write-Ahead Log的技術(shù)用于解決這種情況。服務器將每個狀態(tài)更改作為命令存儲在硬盤上的append-only文件中。append文件通常是非?焖俚牟僮,因此可以在不影響性能的情況下進行。通過順序附加單個日志的方式存儲每一次更新。在服務器啟動時,可以重放日志以再次建立內(nèi)存狀態(tài)。
這提供了持久性保證。即使服務器突然崩潰,然后重新啟動,數(shù)據(jù)也不會丟失。但是,在恢復服務器之前,客戶端將無法獲取或存儲任何數(shù)據(jù)。因此,如果服務器發(fā)生故障,缺乏可用性。
一種顯而易見的解決方案是將數(shù)據(jù)存儲在多個服務器上。因此,我們可以在多個服務器上復制預寫日志。
當涉及多個服務器時,還有更多的故障情況需要考慮。
網(wǎng)絡延遲
在TCP / IP協(xié)議棧中,在跨網(wǎng)絡傳輸消息時所引起的延遲沒有上限。它可以根據(jù)網(wǎng)絡上的負載而變化。例如,一條1 Gbps的網(wǎng)絡連接可能會被觸發(fā)的大數(shù)據(jù)作業(yè)吞沒,從而填滿網(wǎng)絡緩沖區(qū),并可能導致某些消息到達服務器的超長延遲。
在典型的數(shù)據(jù)中心中,服務器一起放在機架中,并且有多個機架通過機架交換機連接?赡軙幸粋交換機樹將數(shù)據(jù)中心的一部分連接到另一部分。在某些情況下,一組服務器可以相互通信,但與另一組服務器斷開連接。這種情況稱為網(wǎng)絡分區(qū)。服務器通過網(wǎng)絡進行通信的基本問題之一是何時知道特定服務器發(fā)生故障。
這里有兩個問題要解決。
?某臺的服務器不能無限期地等待其他服務器是否崩潰。?不應有兩組服務器,每組服務器都認為另一組服務器發(fā)生了故障,因此繼續(xù)為不同組的客戶端提供服務。這稱為腦裂。
為了解決第一個問題,每臺服務器都會定期向其他服務器發(fā)送HeartBeat消息。如果心跳丟失,則將發(fā)送心跳的服務器視為已崩潰。心跳間隔足夠小,以確保不需要花費很多時間來檢測服務器故障。如我們將下面看到的,在最壞的情況下,服務器可能已啟動并正在運行,但是考慮到服務器出現(xiàn)故障,集群作為一個整體可以繼續(xù)運行。這樣可以確保提供給客戶端的服務不會中斷。
第二個問題是腦裂。腦裂,如果兩組服務器獨立接受更新請求,則不同的客戶端可以獲取和設置不同的數(shù)據(jù),一旦腦裂得到解決,就不可能自動解決數(shù)據(jù)沖突。
為了解決腦裂問題,我們必須確保彼此斷開連接的兩組服務器不能獨立運展。為確保這一點,該服務器執(zhí)行的每個動作只有獲得大多數(shù)服務器的確認才被認為是成功的。如果服務器無法獲得多數(shù)確認,則它們將無法提供所需的服務,并且某些客戶端組可能無法接收該服務的響應,但是集群中的服務器將始終處于一致狀態(tài)。占多數(shù)的服務器數(shù)量稱為Quorum。如何確定Quorum?這是根據(jù)群集可以容忍的故障數(shù)決定的。因此,如果我們有五個節(jié)點的集群,則需要三個仲裁。通常,如果我們要容忍f個故障,則需要2f + 1的集群大小。
Quorum確保我們有足夠的數(shù)據(jù)副本以承受某些服務器故障。但是,僅向客戶提供強大的一致性保證是不夠的。假設客戶端在quorum上開始了寫操作,但是該寫操作僅在一臺服務器上成功。quorum的其他服務器仍是舊值。當客戶端從quorum 取值時,如果具有最新值的服務器可用,則它可能會獲得最新值。但是,當客戶端開始讀取值時,具有最新值的服務器不可用,它就會獲取舊值。為了避免這種情況,需有設備跟蹤quorum是否同意特定的操作,并且僅將值發(fā)送給保證在所有服務器上都可用的客戶端。在這種情況下使用 Leader and Followers模式。其中一臺服務器當選領(lǐng)導者,其他服務器充當追隨者。領(lǐng)導者控制并協(xié)調(diào)對跟隨者的復制。領(lǐng)導者現(xiàn)在需要確定哪些更改應該對客戶可見。High-Water Mark用于跟蹤已知已成功復制到追隨者Quorum的預寫日志中的條目。客戶端可以看到所有High-Water之前的條目。領(lǐng)導者還將High-Water Mark傳播給跟隨者。因此,如果領(lǐng)導者失敗并且其中一個跟隨者成為新領(lǐng)導者,那么客戶看到的內(nèi)容就不會出現(xiàn)不一致之處。
進程暫停
但這還不是全部,即使有了Quorums和Leader and Followers,仍然需要解決一個棘手的問題。領(lǐng)導者進程暫停。進程暫停的原因有很多。具有較長垃圾收集暫停時間的領(lǐng)導者會與追隨者者斷開連接,并在恢復后繼續(xù)向追隨者發(fā)送消息。同時,由于追隨者沒有收到領(lǐng)導者的任何心跳,因此他們可能選擇了新的領(lǐng)導者并接受了客戶的更新。如果舊領(lǐng)導者的請求按原邏輯處理,它們可能會覆蓋某些更新。因此,我們需要一種機制來檢測過時領(lǐng)導者的請求。Generation Clock 用于標記和檢測來自過期領(lǐng)導者的請求。Generation是單調(diào)增加的數(shù)字。
不同步的時鐘和事件順序
從較新的消息中檢測較舊的領(lǐng)導者消息的問題是保持消息順序的問題。我們似乎可以使用系統(tǒng)時間戳來排序一組消息,但事實上不能。我們不能使用系統(tǒng)時鐘的主要原因是不能保證跨服務器的系統(tǒng)時鐘是同步的。計算機中的一天中的時鐘由石英晶體管理,并根據(jù)晶體的振蕩來測量時間。
這種機制易于出錯,因為晶體可以更快或更慢地振蕩,因此不同的服務器可能具有截然不同的時間。一組服務器上的時鐘由稱為NTP的服務進行同步。該服務會定期檢查一組全局時間服務器,并相應地調(diào)整計算機時鐘。
因為這是通過網(wǎng)絡上的通信發(fā)生的,并且網(wǎng)絡延遲可能會如上一節(jié)中所述發(fā)生變化,所以時鐘同步可能會由于網(wǎng)絡問題而延遲。這可能會導致服務器時鐘彼此偏移,并且在NTP同步發(fā)生后甚至會向后移。由于計算機時鐘存在這些問題,因此通常不將一天中的時間用于排序事件。取而代之的是使用一種稱為Lamport時間戳的簡單技術(shù)。Generation Clock就是一個例子。
這些問題可能會發(fā)生在最復雜的設置中?紤]Amazon、谷歌和Github的例子。
一次Github宕機實質(zhì)上導致了東海岸和西海岸數(shù)據(jù)中心之間的連接中斷。這會導致數(shù)據(jù)無法跨數(shù)據(jù)中心復制,使兩臺mysql服務器的數(shù)據(jù)不一致。
https://github.blog/2018-10-30-oct21-post-incident-analysis/
一次AWS宕機是由人為錯誤造成的,其中自動化腳本錯誤地傳遞了一個參數(shù),關(guān)閉了大量服務器。https://aws.a(chǎn)mazon.com/message/41926/
一次谷歌中斷是由一些錯誤配置引起的,對網(wǎng)絡容量造成了重大影響,從而導致網(wǎng)絡擁塞和服務中斷。
https://status.cloud.google.com/incident/cloud-networking/19009
匯總-分布式系統(tǒng)示例
我們可以發(fā)現(xiàn)理解這些模式如何幫助我們從頭開始建立一個完整的系統(tǒng)。我們將以共識實現(xiàn)為例。分布式共識是分布式系統(tǒng)實現(xiàn)的特例,它提供了最強的一致性保證。在流行的企業(yè)系統(tǒng)中常見的示例有Zookeeper,etcd和Consul。他們實現(xiàn)了zab和Raft等共識算法,以提供復制和強一致性。還有其他流行的算法可以實現(xiàn)共識,Paxos用于Google的Chubby鎖服務,查stamp replication和virtual-synchrony。用非常簡單的術(shù)語來說,“共識”是指一組服務器,它們在存儲的數(shù)據(jù),存儲的順序以及何時使該數(shù)據(jù)對客戶端可見方面達成一致。
實現(xiàn)共識的模式序列
共識實現(xiàn)使用狀態(tài)機復制來實現(xiàn)容錯。在狀態(tài)機復制中,存儲服務(如鍵值存儲)在所有服務器上復制,并且用戶的輸入在每個服務器上以相同順序執(zhí)行。實現(xiàn)此目的的關(guān)鍵技術(shù)是在所有服務器上復制預寫日志以獲得“ Replicated Wal”。
我們可以將這些模式放在一起以實現(xiàn)Replicated Wal,如下所示。
為了提供持久性保證,請使用Write-Ahead Log。使用Segmented Log將Write-Ahead Log分為多個段。這有助于Low-Water Mark 處理日志清理。通過在多個服務器上復制預寫日志來提供容錯能力。服務器之間的復制是通過使用“領(lǐng)導者”和“追隨者”來管理的。Quorum法定數(shù)用于更新High-Water Mark,以確定客戶端可以看到哪些值。通過使用Singular Update Queue,所有請求均按嚴格順序處理。使用Single Socket Channel將領(lǐng)導者的請求發(fā)送給追隨者時,順序?qū)⒌玫骄S護。為了優(yōu)化單個套接字通道上的吞吐量和延遲性,使用Request Pipeline。追隨者通過從領(lǐng)導者處獲得HeartBeat獲知其可用性。如果領(lǐng)導者由于網(wǎng)絡分區(qū)而暫時從集群斷開連接,則可以使用Generation Clock進行檢測。
通過這種方式,理解問題及其一般形式的可復用解決方案,有助于理解完整系統(tǒng)的構(gòu)建模塊
下一步
分布式系統(tǒng)是一個廣泛的話題。這里討論的模式集只是一小部分,它涵蓋了不同類別,以展示模式方法如何幫助理解和設計分布式系統(tǒng)。我將繼續(xù)在這個集合中添加內(nèi)容,任何分布式系統(tǒng)中都廣泛地包含了以下問題類別。
?集群成員和故障檢測?分區(qū)?復制和一致性?存儲?處理

請輸入評論內(nèi)容...
請輸入評論/評論長度6~500個字
最新活動更多
推薦專題
- 1 UALink規(guī)范發(fā)布:挑戰(zhàn)英偉達AI統(tǒng)治的開始
- 2 北電數(shù)智主辦酒仙橋論壇,探索AI產(chǎn)業(yè)發(fā)展新路徑
- 3 降薪、加班、裁員三重暴擊,“AI四小龍”已折戟兩家
- 4 “AI寒武紀”爆發(fā)至今,五類新物種登上歷史舞臺
- 5 國產(chǎn)智駕迎戰(zhàn)特斯拉FSD,AI含量差幾何?
- 6 光計算迎來商業(yè)化突破,但落地仍需時間
- 7 東陽光:2024年扭虧、一季度凈利大增,液冷疊加具身智能打開成長空間
- 8 地平線自動駕駛方案解讀
- 9 封殺AI“照騙”,“淘寶們”終于不忍了?
- 10 優(yōu)必選:營收大增主靠小件,虧損繼續(xù)又逢關(guān)稅,能否乘機器人東風翻身?