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

發(fā)表評(píng)論
請(qǐng)輸入評(píng)論內(nèi)容...
請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字
最新活動(dòng)更多
-
6月20日立即下載>> 【白皮書】精準(zhǔn)測(cè)量 安全高效——福祿克光伏行業(yè)解決方案
-
7月3日立即報(bào)名>> 【在線會(huì)議】英飛凌新一代智能照明方案賦能綠色建筑與工業(yè)互聯(lián)
-
7月22-29日立即報(bào)名>> 【線下論壇】第三屆安富利汽車生態(tài)圈峰會(huì)
-
7.30-8.1火熱報(bào)名中>> 全數(shù)會(huì)2025(第六屆)機(jī)器人及智能工廠展
-
7月31日免費(fèi)預(yù)約>> OFweek 2025具身機(jī)器人動(dòng)力電池技術(shù)應(yīng)用大會(huì)
-
免費(fèi)參會(huì)立即報(bào)名>> 7月30日- 8月1日 2025全數(shù)會(huì)工業(yè)芯片與傳感儀表展
推薦專題
- 1 AI 眼鏡讓百萬(wàn) APP「集體失業(yè)」?
- 2 大廠紛紛入局,百度、阿里、字節(jié)搶奪Agent話語(yǔ)權(quán)
- 3 深度報(bào)告|中國(guó)AI產(chǎn)業(yè)正在崛起成全球力量,市場(chǎng)潛力和關(guān)鍵挑戰(zhàn)有哪些?
- 4 上海跑出80億超級(jí)獨(dú)角獸:獲上市公司戰(zhàn)投,干人形機(jī)器人
- 5 一文看懂視覺(jué)語(yǔ)言動(dòng)作模型(VLA)及其應(yīng)用
- 6 國(guó)家數(shù)據(jù)局局長(zhǎng)劉烈宏調(diào)研格創(chuàng)東智
- 7 下一代入口之戰(zhàn):大廠為何紛紛押注智能體?
- 8 百億AI芯片訂單,瘋狂傾銷中東?
- 9 Robotaxi新消息密集釋放,量產(chǎn)元年誰(shuí)在領(lǐng)跑?
- 10 格斗大賽出圈!人形機(jī)器人致命短板曝光:頭腦過(guò)于簡(jiǎn)單