想知道更多關於區塊鏈技術知識,請百度【鏈客區塊鏈技術問答社區】 鏈客,有問必答!
分佈式系統核心問題
隨着摩爾定律遇到瓶頸,愈來愈多狀況下要依靠分佈式架構,才能實現海量數據處理能力和可擴展計算能力。
區塊鏈系統,首先是一個分佈式系統。傳統單節點結構演變到分佈式系統,碰到的首要問題就是一致性的保障。很顯然,若是分佈式集羣沒法保證處理結果一致的話,那任何創建於其上的業務系統都沒法正常工做。
本文將介紹分佈式系統領域的核心問題,包括一致性、共識的定義,基本的原理和算法,另外還介紹了評估分佈式系統可靠性的指標。
1、一致性問題
一致性問題是分佈式領域最爲基礎也是最重要的問題。若是分佈式系統能實現「一致」,對外就能夠呈現爲一個完美的、可擴展的「虛擬節點」,相對物理節點具有更優越性能和穩定性。這也是分佈式系統但願能實現的最終目標。
1.一、定義與重要性
定義:一致性(consistency),早期也叫agreement,是指對於分佈式系統中的多個服務節點,給定一系列操做,在約定協議的保障下,試圖使得它們對處理結果達成「某種程度」的認同。
理想狀況下,若是各個服務節點嚴格遵循相同的處理協議,構成相同的處理狀態機,給定相同的初始狀態和輸入序列,則能夠保障在處理過程當中的每一個環節的結果都是相同的。
那麼,爲何說一致性問題十分重要呢?
舉個現實生活中的例子,多個售票處同時出售某線路上的火車票,該線路上存在多個經停站,怎麼才能保證在任意區間都不會出現超售(同一個座位賣給兩我的)的狀況呢?
這個問題看起來彷佛沒那麼難,現實生活中常常經過分段分站售票的機制。然而,爲了支持海量的用戶和避免出現錯誤,存在不少設計和實現上的挑戰。特別在計算機的世界裏,爲了達到遠超普通世界的高性能和高可擴展性需求,問題會變得更爲複雜。
注意:一致性並不表明結果正確與否,而是系統對外呈現的狀態一致與否;例如,全部節點都達成失敗狀態也是一種一致。
1.二、問題與挑戰
看似強大的計算機系統,實際上不少地方都比人類世界要脆弱得多。特別是在分佈式計算機集羣系統中,以下幾個方面很容易出現問題:
節點之間的網絡通訊是不可靠的,包括消息延遲、亂序和內容錯誤等;
節點的處理時間沒法保障,結果可能出現錯誤,甚至節點自身可能發生宕機;
同步調用能夠簡化設計,但會嚴重下降分佈式系統的可擴展性,甚至使其退化爲單點系統。
仍以火車票售賣問題爲例,願意動腦筋的讀者可能已經想到了一些不錯的解決思路,例如:
要出售任意一張票前,先打電話給其餘售票處,確認下當前這張票不衝突。即經過同步調用來避免衝突;
多個售票處提早約好隔離的售票時間。好比第一家能夠在上午8點到9點期間賣票,接下來一個小時是另一家……即經過令牌機制來避免衝突;
成立一個第三方的存票機構,票集中存放,每次賣票前找存票機構查詢。此時問題退化爲中心化單點系統。
固然,還會有更多方案。
實際上,這些方案背後的思想,都是將可能引起不一致的並行操做進行串行化。這實際上也是現代分佈式系統處理一致性問題的基礎思路。只是由於如今的計算機系統應對故障每每不夠「智能」,而人們又但願系統能夠更快更穩定地工做,因此實際可行的方案須要更加全面和更加高效。
注意:這些思路都沒有考慮請求和答覆消息出現失敗的狀況,同時假設每一個售票處的售票機制是正常工做的。
1.三、一致性要求
規範地說,分佈式系統達成一致的過程,應該知足:
可終止性(termination):一致的結果在有限時間內能完成;
約同性(agreement):不一樣節點最終完成決策的結果是相同的;
合法性(validity):決策的結果必須是某個節點提出的提案;
可終止性很容易理解。有限時間內完成,意味着能夠保障提供服務(liveness)。這是計算機系統能夠被正常使用的前提。須要注意,在現實生活中這點並非總能獲得保障的。例如取款機有時候會出現「服務中斷」;撥打電話有時候是「沒法鏈接」的。
約同性看似容易,實際上暗含了一些潛在信息。決策的結果相同,意味着算法要麼不給出結果,任何給出的結果一定是達成了共識的,即安全性(safety)。挑戰在於算法必需要考慮的是可能會處理任意的情形。凡事一旦推廣到任意情形,每每就不像看起來那麼簡單。例如如今就剩一張某區間(如北京–>南京)的車票了,兩個售票處也分別剛經過某種方式確認過這張票的存在。這時,兩家售票處幾乎同時分別來了一個乘客要買這張票,從各自「觀察」看來,本身一方的乘客都是先到的……這種狀況下,怎麼能達成對結果的共識呢?看起來很容易,賣給物理時間上率先提交請求的乘客便可。然而,對於兩個來自不一樣位置的請求來講,要判斷在時間上的「前後」關係並非那麼容易。兩個車站的時鐘多是不一致的;可能沒法記錄下足夠精確的時間;更況且根據相對論的觀點,並不存在絕對的時空觀。
可見,事件發生的前後順序十分重要,這也是解決分佈式系統領域不少問題的核心祕訣:把多件事情進行排序,並且這個順序還得是你們都承認的。
最後一個合法性看似繞口,可是其實比較容易理解,即達成的結果必須是節點執行操做的結果。仍以賣票爲例,若是兩個售票處分別決策某張票出售給張三和李四,那麼最終達成一致的結果要麼是張三,要麼是李四,而絕對不能是其餘人。
1.四、帶約束的一致性
從前面的分析能夠看到,要實現絕對理想的嚴格一致性(strict consistency)代價很大。除非系統不發生任何故障,並且全部節點之間的通訊無需任什麼時候間,這個時候整個系統其實就等價於一臺機器了。實際上,越強的一致性要求每每會形成越弱的處理性能,以及越差的可擴展性。
通常來說,強一致性(strong consistency)主要包括下面兩類:算法
順序一致性(sequential consistency):Leslie Lamport在1979年的經典論文《How to Make a Multiprocessor Computer That Correctly Executes Multiprocess Programs》中提出,是一種比較強的約束,保證全部進程看到的全局執行順序(total order)一致,而且每一個進程看自身的執行順序(local order)跟實際發生順序一致。例如,某進程先執行A,後執行B,則實際獲得的全局結果中就應該爲A在B前面,而不能反過來。同時全部其餘進程在全局上也應該看到這個順序。順序一致性實際上限制了各進程內指令的偏序關係,但不在進程間按照物理時間進行全局排序;數據庫
線性一致性(linearizability consistency):Maurice P.Herlihy與Jeannette M.Wing在1990年的經典論文《Linearizability:A Correctness Condition for Concurrent Objects》中共同提出,在順序一致性前提下增強了進程間的操做排序,造成惟一的全局順序(系統等價因而順序執行,全部進程看到的全部操做的序列順序都一致,而且跟實際發生順序一致),是很強的原子性保證。可是比較難實現,目前基本上要麼依賴於全局的時鐘或鎖,要麼經過一些複雜算法實現,性能每每不高。安全
實現強一致性每每須要準確的計時設備。高精度的石英鐘的偏移率爲10的-7次方,最準確的原子震盪時鐘的偏移率爲10的負13次方。Google曾在其分佈式數據庫Spanner中採用基於原子時鐘和GPS的「TrueTime」方案,可以將不一樣數據中心的時間誤差控制在10ms之內。方案簡單粗暴並且有效,但存在成本較高的問題。
因爲強一致性的系統每每比較難實現,並且不少時候,實際需求並無那麼嚴格須要強一致性。所以,能夠適當地放寬對一致性的要求,從而下降系統實現的難度。例如在必定約束下實現所謂最終一致性(eventual consistency),即總會存在一個時刻(而不是馬上),讓系統達到一致的狀態。大部分Web系統實現的都是最終一致性。相對強一致性,這一類在某些方面弱化的一致性都籠統稱爲弱一致性(weak consistency)。
2、共識算法
共識(consensus)在不少時候會與一致性(consistency)術語放在一塊兒討論。嚴謹地講,二者的含義並不徹底相同。
一致性每每指分佈式系統中多個副本對外呈現的數據的狀態。如前面提到的順序一致性、線性一致性,描述了多個節點對數據狀態的維護能力。而共識則描述了分佈式系統中多個節點之間,彼此對某個狀態達成一致結果的過程。所以,一致性描述的是結果狀態,共識則是一種手段。達成某種共識並不意味着就保障了一致性。
實踐中,要保障系統知足不一樣程度的一致性,核心過程每每須要經過共識算法來達成。
共識算法解決的是對某個提案(proposal)你們達成一致意見的過程。提案的含義在分佈式系統中十分寬泛,如多個事件發生的順序、某個鍵對應的值、誰是領導……等等。能夠認爲任何能夠達成一致的信息都是一個提案。對於分佈式系統來說,各個節點一般都是相同的肯定性狀態機模型(又稱爲狀態機複製問題,state-machine replication),從相同初始狀態開始接收相同順序的指令,則能夠保證相同的結果狀態。所以,系統中多個節點最關鍵的是對多個事件的順序進行共識,即排序。
2.一、問題與挑戰
實際上,若是分佈式系統中各個單節點都能保證以十分「理想」的性能(瞬間響應、超高吞吐)無端障地運行,節點之間通訊瞬時送達,則實現共識過程並不十分複雜,簡單地經過廣播進行瞬時投票和應答便可。
惋惜的是,現實中這樣的「理想」系統並不存在。不一樣節點之間通訊存在延遲(光速物理限制,通訊處理延遲),而且任意環節均可能存在故障(系統規模越大,發生故障可能性越高)。如通訊網絡會發生中斷、節點會發生故障、甚至存在惡意節點故意要僞造消息,破壞系統的正常工做流程。
通常地,把出現故障(crash或fail-stop,即不響應)但不會僞造信息的狀況稱爲「非拜占庭錯誤」(non-byzantine fault)或「故障錯誤」(Crash Fault);僞造信息惡意響應的狀況稱爲「拜占庭錯誤」(Byzantine Fault),對應節點爲拜占庭節點。
2.二、常見算法
根據解決的是非拜占庭的普通錯誤狀況仍是拜占庭錯誤狀況,共識算法能夠分爲Crash Fault Tolerance(CFT)類算法和Byzantine Fault Tolerance(BFT)類算法。
針對常見的非拜占庭錯誤的狀況,已經存在一些經典的解決算法,包括Paxos、Raft及其變種等。這類容錯算法每每性能比較好,處理較快,容忍不超過一半的故障節點。
對於要能容忍拜占庭錯誤的狀況,通常包括PBFT(Practical Byzantine Fault Tolerance)爲表明的肯定性系列算法、PoW爲表明的機率算法等。對於肯定性算法,一旦達成對某個結果的共識就不可逆轉,即共識是最終結果;而對於機率類算法,共識結果則是臨時的,隨着時間推移或某種強化,共識結果被推翻的機率愈來愈小,成爲事實上的最終結果。拜占庭類容錯算法每每性能較差,容忍不超過1/3的故障節點。
此外,XFT(Cross Fault Tolerance)等最近提出的改進算法能夠提供相似CFT的處理響應速度,並能在大多數節點正常工做時提供BFT保障。
注意:實踐中,一致性的結果每每還須要客戶端的額外支持,典型狀況如經過訪問足夠多個服務節點來比對驗證,確保獲取共識後的正確結果。
2.三、理論界限
數學家都喜歡對問題先肯定一個最壞的理論界限。那麼,共識問題的最壞界限在哪裏呢?很不幸,在推廣到任意情形時,分佈式系統的共識問題無通用解。這彷佛很容易理解,當多個節點之間的通訊網絡自身不可靠的狀況下,很顯然,沒法確保實現共識(例如,全部涉及共識的消息都在網絡上丟失)。那麼,對於一個設計得當,能夠大機率保證消息正確送達的網絡,是否是就必定能保證達成共識呢?
科學家們證實,即使在網絡通訊可靠狀況下,可擴展的分佈式系統的共識問題,其通用解法的理論下限是——沒有下限(無解)。
這個結論稱爲「FLP不可能原理」。該原理極其重要,能夠看作是分佈式領域裏的「測不許原理」。
提示:不只在分佈式系統領域,實際上在不少領域都存在相似「測不許原理」的約束。
3、FLP不可能原理
3.一、定義
FLP不可能原理:在網絡可靠,但容許節點失效(即使只有一個)的最小化異步模型系統中,不存在一個能夠解決一致性問題的肯定性共識算法(No completely asynchronous consensus protocol can tolerate even a single unannounced process death)。
提出並證實該定理的論文《Impossibility of Distributed Consensus with One Faulty Process》由Fischer、Lynch和Patterson三位科學家於1985年發表,該論文後來得到了Dijkstra(就是發明最短路徑算法的那位計算機科學家)獎。
FLP不可能原理實際上告訴人們,不要浪費時間,去爲異步分佈式系統設計在任意場景下都能實現共識的算法。
3.二、正確理解
要正確理解FLP不可能原理,首先要弄清楚「異步」的含義。
在分佈式系統中,同步和異步這兩個術語存在特殊的含義。
同步是指系統中的各個節點的時鐘偏差存在上限;而且消息傳遞必須在必定時間內完成,不然認爲失敗;同時各個節點完成處理消息的時間是必定的。對於同步系統,能夠很容易地判斷消息是否丟失。
異步是指系統中各個節點可能存在較大的時鐘差別,同時消息傳輸時間是任意長的,各節點對消息進行處理的時間也多是任意長的,這就形成沒法判斷某個消息遲遲沒有被響應是哪裏出了問題(節點故障仍是傳輸故障?)。不幸地是,現實生活中的系統每每都是異步系統。
FLP不可能性在原始論文中以圖論的形式進行了嚴格證實。要理解這一基本原理並不複雜,一個不嚴謹的例子以下。
三我的在不一樣房間進行投票(投票結果是0或者1)。彼此能夠經過電話進行溝通,但常常有人會時不時睡着。好比某個時候,A投票0,B投票1,C收到了兩人的投票,而後C睡着了。此時,A和B將永遠沒法在有限時間內獲知最終的結果,到底是C沒有應答仍是應答的時間過長。若是能夠從新投票,則相似情形能夠在每次取得結果前發生,這將致使共識過程永遠沒法完成。
FLP原理實際上說明對於容許節點失效狀況下,純粹異步系統沒法確保一致性在有限時間內完成。即使對於非拜占庭錯誤的前提下,包括Paxos、Raft等算法也都存在沒法達成共識的狀況,只是在工程實踐中這種狀況出現的機率很小。
那麼,FLP不可能原理是否意味着研究共識算法壓根沒有意義?
先別這麼悲觀。學術界作研究,每每考慮地是數學和物理意義上最極端的情形,不少時候現實生活要美好得多(感謝這個世界如此魯棒!)。例如,上面例子中描述的最壞情形,每次都發生的機率其實並無那麼大。工程實現上多嘗試幾回,很大可能就成功了。
科學告訴你什麼是不可能的;工程則告訴你,付出一些代價,能夠把它變成可行。這就是科學和工程不一樣的魅力。
那麼,退一步講,在付出一些代價的狀況下,咱們在共識的達成上,能作到多好?回答這一問題的是另外一個很出名的原理:CAP原理。
提示:科學告訴你去賭場賭博從機率上總會是輸錢的;工程則告訴你,若是你願意接受最終輸錢的風險,中間說不定能偶爾小贏幾筆呢!網絡