分布式系統(tǒng)與單節(jié)點系統(tǒng)的本質(zhì)區(qū)別是什么_第1頁
分布式系統(tǒng)與單節(jié)點系統(tǒng)的本質(zhì)區(qū)別是什么_第2頁
分布式系統(tǒng)與單節(jié)點系統(tǒng)的本質(zhì)區(qū)別是什么_第3頁
分布式系統(tǒng)與單節(jié)點系統(tǒng)的本質(zhì)區(qū)別是什么_第4頁
分布式系統(tǒng)與單節(jié)點系統(tǒng)的本質(zhì)區(qū)別是什么_第5頁
已閱讀5頁,還剩7頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

1、 分布式系統(tǒng)與單節(jié)點系統(tǒng)的本質(zhì)區(qū)別是什么? 分布式系統(tǒng)與單節(jié)點系統(tǒng)的本質(zhì)區(qū)別是什么?我們通過一個簡單的例子來說明。在單線程程序中,我們定義變量和執(zhí)行過程(即一組步驟)。例如,我們可以定義一個變量,并對它執(zhí)行簡單的算術運算:int x = 1;x += 2;x *= 2;這里我們只會得到唯一的執(zhí)行歷史:聲明一個變量,把它加上2,再乘以2,然后得到結果6。假設這些運算不是由單個線程執(zhí)行的,而是有兩個線程讀寫變量x,我們就需要考慮并發(fā)執(zhí)行的問題。1 并發(fā)執(zhí)行一旦兩個執(zhí)行線程都能訪問變量,除非我們在線程間同步這些步驟,否則這些并發(fā)步驟的執(zhí)行結果是無法預知的。如圖8-1所示,我們得到了4個可能的結果。注

2、1a) x = 2,如果兩個線程都讀到初始值,加法寫入結果,但被乘法的結果覆蓋了。b) x = 3,如果兩個線程都讀到初始值,乘法寫入結果,但被加法的結果覆蓋了。c) x = 4,如果乘法讀到初始值,且乘法在加法之前執(zhí)行。d) x = 6,如果加法讀到初始值,且加法在乘法之前執(zhí)行。即便僅在單個節(jié)點上,我們就已經(jīng)遇到了分布式系統(tǒng)中的第一個問題:并發(fā)。每個并發(fā)程序都具有分布式系統(tǒng)的某些特性。線程訪問共享狀態(tài),在本地執(zhí)行一些運算,再將結果傳回共享變量。圖1:并發(fā)執(zhí)行中可能的交錯情形為了精確定義執(zhí)行歷史并減少可能的結果數(shù)量,我們需要一致性模型。一致性模型描述并發(fā)執(zhí)行的過程,并且確定了運算執(zhí)行以及對其他

3、參與者可見的順序。使用不同的一致性模型,我們可以約束或放松系統(tǒng)可能的狀態(tài)數(shù)量。分布式系統(tǒng)和并發(fā)計算在術語和學術研究上有許多重疊之處,但也存在一些差異。并發(fā)系統(tǒng)中存在共享內(nèi)存,進程可以用它來交換信息。在分布式系統(tǒng)中,各個進程擁有自己的本地狀態(tài),參與者之間通過傳遞消息進行通信。并發(fā)和并行我們經(jīng)?;Q使用并發(fā)和并行計算這兩個術語,但是這兩個概念在語義上有細微的差異。當兩個步驟序列并發(fā)執(zhí)行時,二者都在進行中,但任意時刻都只有其中一個在執(zhí)行。當兩個步驟序列并行執(zhí)行時,它們的步驟可以(在某一時刻)同時執(zhí)行。并發(fā)的操作時間上存在重疊,而并行的操作由多個處理器執(zhí)行WEIKUM01。Erlang編程語言的創(chuàng)建者

4、Joe Armstrong舉過一個例子:并發(fā)執(zhí)行就像一臺咖啡機前排了兩隊,而并行執(zhí)行就像兩臺咖啡機前排了兩隊。即便如此,絕大部分資料都用術語“并發(fā)”來描述擁有多個并行執(zhí)行線程的系統(tǒng),而“并行”這個詞則很少見。分布式系統(tǒng)中的共享狀態(tài)我們可以嘗試在分布式系統(tǒng)中引入共享內(nèi)存的概念,例如,單一信息源(比如數(shù)據(jù)庫)。即使我們解決了并發(fā)訪問的問題,我們依然無法保證所有進程都是同步的。為了訪問數(shù)據(jù)庫,進程需要通過通信介質(zhì)發(fā)送和接受消息,以查詢或修改狀態(tài)。但是,如果一個進程很久都沒有從數(shù)據(jù)庫得到響應會如何?為了回答這個問題,我們首先要定義什么是很久。為此,必須從同步性的角度來描述系統(tǒng):通信是否是全異步的?是否

5、存在某些時序假設?如果存在的話,這些時序假設將允許我們引入操作超時和重試機制。我們無從知曉數(shù)據(jù)庫沒有響應是因為過載、不可用、響應太慢還是網(wǎng)絡問題。這描述了崩潰的本質(zhì)進程可能以各種方式崩潰:可能因某種原因無法繼續(xù)執(zhí)行后面的算法步驟;可能遇到了臨時性的故障;也可能是消息丟失。我們需要定義一個故障模型并描述故障可能發(fā)生的方式,然后再決定如何處理它們。如果系統(tǒng)在故障發(fā)生時仍然能繼續(xù)正常運行,我們將這樣的特性稱為容錯性。故障是不可避免的,所以我們需要構建出具有可靠組件的系統(tǒng)。消除單點故障,比如前文提到的單節(jié)點數(shù)據(jù)庫,可能是我們朝此方向邁出的第一步。我們可以引入一些冗余,增設備份數(shù)據(jù)庫。然而這就引出了另一

6、個問題:如何使共享狀態(tài)的多個副本保持同步?到目前為止,在我們這個簡單系統(tǒng)中引入共享狀態(tài)所帶來的問題比答案還多?,F(xiàn)在我們知道,共享狀態(tài)不像引入數(shù)據(jù)庫那樣簡單,還必須采取更細化的方法,即基于消息傳遞來描述各個獨立進程之間的交互。2 分布式計算的誤區(qū)理想情況下,當兩臺計算機在網(wǎng)絡上通信時,一切都能正常工作:進程開啟一個連接、發(fā)送數(shù)據(jù)、收到響應,每個人都很開心。但是假設所有操作總會成功并且沒有任何錯誤是很危險的,因為當某些東西出問題時,我們的假設也就不成立了,那時系統(tǒng)的行為將變得難以預測。大多數(shù)時候,假設網(wǎng)絡可靠是合理的。網(wǎng)絡至少在一定程度上可靠才能有用。我們都曾經(jīng)歷過這樣的情況,當我們嘗試連接到遠程

7、服務器時,卻收到了一個“網(wǎng)絡不可達”的錯誤。即使能建立連接,一個成功的初始連接也無法保證這條鏈路是穩(wěn)定的,連接隨時可能中斷。消息可能送達了對端,但對端的響應卻可能丟失了,也有可能在對端的響應發(fā)送之前連接就中斷了。網(wǎng)絡交換機會有故障,電纜可能斷開,網(wǎng)絡配置也隨時可能發(fā)生變化。我們構建系統(tǒng)時需要適當?shù)靥幚硭羞@些情況。連接可以是穩(wěn)定的,但我們不能期望遠程調(diào)用能像本地調(diào)用一樣快。我們應盡可能少地對延遲做出假設,并且永遠不要假設延遲為零。一條消息要想到達遠程服務器,需要穿過若干個軟件層和一個物理媒介(比如光纖或電纜),所有這些操作都不是瞬間完成的。Michael Lewis在他所著的書Flash Bo

8、ys(Simon and Schuster公司出版)中講述了這樣一個故事,公司花費數(shù)百萬美元把延遲降低幾毫秒,從而能比競爭對手更快地訪問交易所。這是一個把延遲作為競爭優(yōu)勢的絕佳例子,然而值得一提的是,根據(jù)其他一些研究,比如文獻BARTLETT16,過時報價套利(通過比競爭對手更快地得知價格并執(zhí)行交易來獲取利潤)并不能使快速交易者從市場中獲利。從上述教訓當中學習,我們增加了重試和重連機制,并去掉了關于瞬間執(zhí)行的假設,但是事實證明這還不夠:當我們增加消息的數(shù)量、發(fā)送速率和大小,并向現(xiàn)有網(wǎng)絡中添加新的進程時,我們不應該假設帶寬是無限的。1994年,Peter Deutsch發(fā)布過一個如今很有名的斷言

9、列表,標題為“分布式計算的誤區(qū)”,描述了分布式計算中易被忽視的一些方面。除了網(wǎng)絡可靠性、延遲和帶寬假設,它還提到了其他問題,比如,網(wǎng)絡的安全性、可能存在的攻擊者、有意或無意的拓撲變化都可能打破我們的一些假設,這些假設包括:某一資源存在性和所在位置,網(wǎng)絡傳輸所消耗的時間和資源,以及最后存在一個擁有整個網(wǎng)絡的知識和控制權的權威個體。Deutsch的列表可以說非常詳盡,但它側重于通過鏈路傳遞消息時可能出錯的地方。這些擔憂是合理的,而且描述了最通用、最底層的復雜性,但不幸的是,在設計和實現(xiàn)分布式系統(tǒng)時,我們還做出了很多其他假設,這些假設也可能在運行中導致問題。2.1 處理在遠程進程響應剛剛收到的消息之

10、前,它還需要在本地執(zhí)行一些工作,因此我們不能假定處理是瞬時完成的。只考慮網(wǎng)絡延遲還不夠,因為遠程進程執(zhí)行的操作也不是立即完成的。此外,我們還無法保證消息送達后會立刻被處理。消息可能會進入遠程服務器的等待隊列中,等到所有更早到達的消息處理完后才被處理。節(jié)點可能相距很近,也可能很遠,各節(jié)點可能有不同的CPU、內(nèi)存和磁盤配置,可能運行不同的軟件版本和配置。我們不能期望它們以相同的速度處理請求。如果完成一項任務需要等待幾個并行工作的遠程服務器響應,則整個執(zhí)行的完成時間取決于最慢的服務器。與普遍存在的看法相反,隊列容量并非是無限的,堆積更多的請求不會對系統(tǒng)有任何好處。當生產(chǎn)者產(chǎn)生消息的速度大于消費者能夠

11、處理的速度時,我們可以使用背壓(backpressure)策略減慢生產(chǎn)者的速度。背壓是分布式系統(tǒng)中人們了解和應用最少的概念之一,通常是事后才建立,而不是將其視為系統(tǒng)設計必需的一個組成部分。盡管增加隊列容量聽起來像是個好主意可以幫助我們管道化、并行化以及有效地調(diào)度請求,但是,如果消息僅僅是停在隊列中等待處理,什么也不會發(fā)生。增大隊列大小可能對延遲產(chǎn)生負面影響,因為這并不會改善處理速度。通常,進程本地隊列是用于實現(xiàn)以下目標:解耦使接收和處理在時間上分開,并各自獨立發(fā)生。流水線化不同階段的請求由系統(tǒng)中獨立的部分處理。負責接收消息的子系統(tǒng)不用阻塞到上一條消息處理完成。吸收瞬時突發(fā)流量系統(tǒng)負載可能經(jīng)常變

12、化,但是請求到達的間隔時間對負責處理請求的組件是隱藏的??傮w的系統(tǒng)延遲會由于排隊而增加,但這通常仍比響應失敗并重試請求更好。隊列大小取決于工作負載和應用程序。對于相對穩(wěn)定的工作負載,我們可以通過測量任務處理時間以及各任務的平均排隊時間來確定隊列大小,從而確保在提升吞吐量的同時,延遲仍保持在可接受的范圍內(nèi)。在這種情況下,隊列大小相對較小。對于不可預測的工作負載,可能會出現(xiàn)任務提交的突發(fā)流量,這時隊列大小也應當考慮突發(fā)流量和高負載。即使遠程服務器可以快速地處理請求,也并不意味著我們總是能獲得正面的響應。它也可能回應一個失敗:無法進行寫操作、要查找的值不存在或是觸發(fā)了bug??傊?,即使是最順利的情況

13、也需要我們的關注。2.2 時鐘和時間時間是一種幻覺,尤其是午餐時間。 FordPrefect,TheHitchhiker抯GuidetotheGalaxy假設不同的遠程計算機上的時鐘都同步也很危險。再加上延遲為零以及處理是瞬時的這些假設,將會導致不同的特質(zhì),尤其是在時序和實時數(shù)據(jù)處理中。例如,當從時間感知不同的參與者收集和聚合數(shù)據(jù)時,你必須了解它們之間的時間漂移并相應地對時間進行歸一化,而不是依賴源時間戳。除非使用特殊的高精度時間源,否則不能依賴時間戳進行同步或排序。當然,這并不意味著我們完全不能或不該依賴時間:說到底,任何同步系統(tǒng)都依靠本地時鐘實現(xiàn)超時。我們必須始終注意進程之間可能存在的時間

14、誤差,以及傳遞和處理消息所需的時間。例如,Spanner(參見13.5節(jié))使用特殊的時間API,該API返回時間戳和不確定性界限以施加嚴格的事務順序。一些故障檢測算法依賴于共享的時間概念,要求時鐘漂移始終在允許的范圍內(nèi)才能確保正確性GUPTA01。除了分布式系統(tǒng)中的時鐘同步非常困難之外,當前時間也在不斷變化:你可以從操作系統(tǒng)請求當前的POSIX時間戳,并在執(zhí)行幾個步驟后請求另一個當前時間戳,兩次結果是不同的。盡管這是一個明顯的現(xiàn)象,但是了解時間的來源以及時間戳捕獲的確切時刻至關重要。了解時鐘源是否是單調(diào)的(即永遠不會后退),以及與調(diào)度時間相關的操作可能偏移多少,可能也會有所幫助。2.3 狀態(tài)一

15、致性之前說到的假設大多屬于“幾乎總是錯的”一類,但是,還有一些假設最好歸入“并非總是對的”一類。這類假設幫助我們走思維捷徑,通過以特定方式思考來簡化模型,忽略某些棘手的邊緣情形。分布式算法并不總是保證狀態(tài)嚴格一致。一些方法具有較寬松的約束,允許各副本之間的狀態(tài)存在分歧,并依賴沖突解決(檢測和解決系統(tǒng)內(nèi)分歧狀態(tài)的能力)和讀取時數(shù)據(jù)修復(讀取期間,當各副本響應不同結果時,使副本恢復同步的能力)。有關這些概念的更多信息參見第12章。假定狀態(tài)在節(jié)點間完全一致可能會導致難以察覺的bug。最終一致的分布式數(shù)據(jù)庫可能具有這樣的邏輯:讀取時通過查詢Quorum的節(jié)點來處理副本不一致,但是假定數(shù)據(jù)庫表結構和集群

16、視圖是強一致的。除非我們確保這些信息的一致性,否則依賴該假設可能會造成嚴重的后果。例如,Apache Cassandra曾有一個bug,其原因是表結構變更在不同時刻傳播到各個服務器。如果在表結構傳播過程中嘗試從數(shù)據(jù)庫讀取數(shù)據(jù),則可能會讀到損壞的數(shù)據(jù),因為一臺服務器以某種表結構進行編碼,而另一臺服務器使用不同的表結構對其進行解碼。另一個例子是由環(huán)的視圖分歧引起的bug:如果一個節(jié)點假定另一個節(jié)點保存了某個鍵的數(shù)據(jù)記錄,但另一個節(jié)點具有不同的集群視圖,此時讀寫數(shù)據(jù)可能會導致數(shù)據(jù)記錄被錯誤放置,或是獲得一個空的響應,雖然數(shù)據(jù)實際上好端端地存放在另一個節(jié)點上。即使完全的解決方案成本很高,我們也最好事先

17、考慮各種可能的問題。通過了解和處理這些情況,你能以更自然的方式解決問題,比如內(nèi)置防護措施或修改設計。2.4 本地和遠程執(zhí)行將復雜性隱藏在API內(nèi)部可能很危險。例如,對于本地數(shù)據(jù)集上的一個迭代器,即使你對存儲引擎不熟悉,也可以合理地推測內(nèi)部行為。理解遠程數(shù)據(jù)集上的迭代過程則是一個完全不同的問題:你需要理解一致性、傳遞語義、數(shù)據(jù)協(xié)調(diào)、分頁、合并、并發(fā)訪問含義以及許多其他事情。簡單地將兩者隱藏在同一個接口后,即便有用,也可能會產(chǎn)生誤導。調(diào)試、配置和可觀察性可能需要額外的API參數(shù)。我們應該始終牢記,本地執(zhí)行和遠程執(zhí)行是不同的。隱藏遠程調(diào)用最明顯的問題是延遲:遠程調(diào)用的成本比本地調(diào)用高很多倍,因為它涉

18、及雙向網(wǎng)絡傳輸、序列化/反序列化以及許多其他步驟。交錯使用本地調(diào)用和阻塞的遠程調(diào)用可能會導致性能下降和預期之外的副作用VINOSKI08。2.5 處理故障的需要剛開始構建系統(tǒng)的時候,我們可以假設所有節(jié)點都可以正常工作,但如果總是這么想就很危險了。在長時間運行的系統(tǒng)中,節(jié)點可能會關機維護(通常會有個優(yōu)雅關閉的過程)或因為種種原因(例如軟件問題、內(nèi)存耗盡(out-of-memory killer KERRISK10)、運行時bug、硬件問題等)而崩潰。進程會發(fā)生故障,而你能做的最好的事情就是做好準備并知道如何處理它們。如果遠程服務器沒有響應,我們并不總是知道確切的原因。這可能是由系統(tǒng)崩潰、網(wǎng)絡故障

19、、遠程進程或中間鏈路太慢導致的。一些分布式算法使用心跳協(xié)議和故障檢測機制來確定哪些參與者還活著且可達。2.6 網(wǎng)絡分區(qū)和部分故障當兩個或更多服務器無法相互通信時,我們稱這種情況為網(wǎng)絡分區(qū)。Seth Gilbert和Nancy Lynch在Perspectives on the CAP Theorem GILBERT12中區(qū)分了以下兩種情況:兩個參與者無法相互通信;幾組參與者彼此隔開,無法交換消息并繼續(xù)運行算法。網(wǎng)絡的總體不可靠性(數(shù)據(jù)包丟失、重傳、延遲難以預測)令人煩惱但尚可容忍,而網(wǎng)絡分區(qū)則會造成更多的麻煩,因為各個獨立的分組可以繼續(xù)執(zhí)行并產(chǎn)生沖突的結果。網(wǎng)絡鏈路的故障也可能是不對稱的:消息

20、仍然能從一個進程傳遞到另一個進程,反之則不行。為了構建在一個或多個進程出現(xiàn)故障的情況下仍健壯的系統(tǒng),我們必須考慮部分故障的情況TANENBAUM06,如何讓系統(tǒng)在部分不可用或運行不正常的情況下仍能繼續(xù)工作。故障很難檢測,并且在系統(tǒng)的不同部分看來,不總是以相同的方式可見。設計高可用性系統(tǒng)時,我們應該始終考慮邊緣情形:如果我們確實復制了數(shù)據(jù)卻沒有收到確認該怎么辦?要重試嗎?在發(fā)送了確認的節(jié)點上,數(shù)據(jù)仍可用于讀取嗎?墨菲定律注2告訴我們故障一定會發(fā)生。編程界又補充道,故障將以最壞的方式發(fā)生。因此,作為分布式系統(tǒng)工程師,我們的工作是盡可能減少可能出現(xiàn)錯誤的場景,并為故障做好準備包括這些故障可能導致的破

21、壞。避免一切故障是不可能的,但我們?nèi)钥梢詷嫿ㄒ粋€彈性的系統(tǒng),使之在故障出現(xiàn)時仍然能正常運行。設計應對故障的最佳方式是進行故障測試。我們無法考慮清楚每種可能的故障場景,并預測多個進程的行為。最好的解決方法就是通過測試工具來制造網(wǎng)絡分區(qū)、模擬比特位腐爛GRAY05、增加延遲、使時鐘發(fā)生偏移以及放大相對處理速度。現(xiàn)實世界中分布式系統(tǒng)的設置可能是對抗性的、不友好的,甚至是“有創(chuàng)造性的”(然而,以非常敵對的方式),因此測試工作應當嘗試覆蓋盡可能多的場景。過去幾年中出現(xiàn)了一些開源項目,它們能幫助我們構造出各種故障場景。Toxiproxy用于模擬網(wǎng)絡問題:限制帶寬、引入延遲、超時等。Chaos Monkey

22、的方法更為激進,它通過隨機關閉服務使工程師直面生產(chǎn)環(huán)境故障的風險。CharybdeFS模擬文件系統(tǒng)及硬件錯誤與故障。你可以用這些工具來測試軟件,以確保在這些故障出現(xiàn)時軟件仍能正確工作。CrashMonkey是一個與文件系統(tǒng)無關的記錄重放測試框架,用于測試持久性文件的數(shù)據(jù)及元數(shù)據(jù)一致性。設計分布式系統(tǒng)時,我們必須認真考慮容錯性、彈性,以及可能的故障場景和邊緣情形。類似于“足夠多的眼睛,就可讓所有問題浮現(xiàn)”,我們可以說足夠大的集群最終一定會命中所有可能的問題。與此同時,只要有足夠多的測試,我們最終能夠發(fā)現(xiàn)每個存在的問題。2.7 級聯(lián)故障我們做不到總是完全隔離故障:被高負載壓垮的進程會增加集群其余部

23、分的負載,從而使其他節(jié)點更有可能發(fā)生故障。級聯(lián)故障能夠從系統(tǒng)的一部分傳播到另一部分,擴大了問題的范圍。有時,級聯(lián)故障甚至可能來源于完全善意的目的。例如,某個節(jié)點離線了一段時間,因而沒有接收到最近的更新。當它恢復在線時,樂于助人的其他節(jié)點希望幫助它追趕上最近的變化,于是開始向它發(fā)送缺失的數(shù)據(jù),而這又導致網(wǎng)絡資源耗盡,或是導致該節(jié)點啟動后短時間內(nèi)再次發(fā)生故障。為了防止系統(tǒng)的故障擴散并妥善處理故障場景,我們可以使用斷路器(或熔斷機制)。在電氣工程中,斷路器可通過中斷電流來保護昂貴且難以更換的部件,使其免受電流過載或短路的影響。在軟件開發(fā)中,熔斷機制會監(jiān)視故障,并使用回退(fallback)機制保護整個系統(tǒng):避免使用出故障的服務,給它一些時間進行恢復,并妥善處理失敗的調(diào)用。當與某一臺服務器的連接失敗或服務器沒有響應時,客戶端將開始循環(huán)重連。那時候,過載的服務器已經(jīng)難以應付新的連接請求,因而客戶端的循環(huán)重試也無濟于事。為了避免這一情況,我們可以使用退避(backoff)策略,客戶端不要立即重試,而是等待一段時間。退避通過合理安排重試、增加后續(xù)請求之間的時間窗口來避免問題擴大。退避

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論