1.為什么分布式火
隨著摩爾定律碰到瓶頸,越來越多的系統要依靠分布式集群架構來實現海量數據處理和可擴展計算能力。
2.分布式的核心問題
參考資料:https://yeasy.gitbooks.io/blockchain_guide/content/distribute_system/problem.html
2.1一致性問題
多個節點在協議(往往通過某種共識算法)保障下,試圖使得它們對處理結果達成某種程度的一致。
要求;1.Termination,有限時間完成 2.Consensus 不同節點結果一致 3.Validity 合法性,決策的記過必須是其他進程提出的提案
帶約束的一致性
首先明確:一致性約束和性能只能平衡,不能同時精確。就跟物理的測不準性質一樣
強一致性:
順序一致性([Sequential Consistency]:保證局部的一致性,類比于java 的并發,某個線程的a before b
線性一致性([Linearizability Consistency]:這個相當于保證了全局一致性,需要用全局的時鐘或鎖實現
弱一致性:weak consisitency,放寬一致性要求,實現效率Eventual Consistency
2.2 共識算法
問題挑戰:
把故障(不響應)的情況稱為“非拜占庭錯誤”,惡意響應的情況稱為“拜占庭錯誤”(對應節點為拜占庭節點)。
tip: 1: FLP 不可能性原理
FLP 不可能原理:在網絡可靠,存在節點失效(即便只有一個)的最小化異步模型系統中,不存在一個可以解決一致性問題的確定性算法。
不要浪費時間去為異步分布式系統設計在任意場景下都能實現共識的算法。
e.g.三個人在不同房間,進行投票(投票結果是 0 或者 1)。三個人彼此可以通過電話進行溝通,但經常會有人時不時地睡著。比如某個時候,A 投票 0,B 投票 1,C 收到了兩人的投票,然后 C 睡著了。A 和 B 則永遠無法在有限時間內獲知最終的結果。如果可以重新投票,則類似情形每次在取得結果前發生:
FLP 原理實際上說明對于允許節點失效情況下,純粹異步系統無法確保一致性在有限時間內完成。
物理和數學研究確定了問題的極端情況,即邊界的情形,但工程通過多次重復等方式,達到可以接受的的效果,就像物理的不確定性原理,粒子的位置和速度不能同時確定,但仍然能進行量子研究應用
tip 2:CAP原理
在一個分布式系統中,(互相連接和共享數據),不可能同時確保一致性(Consistency)、可用性(Availablity)和分區容忍性(Partition),設計中往往需要弱化對某個特性的保證
這里的分區容忍性(Partition)指:網絡可能發生分區,即節點之間的通信不可保障。
系統如果不能在時限內達成數據一致性,就意味著發生了分區的情況
首先我們考慮P,分區容忍性的前提是分區情況的發生,由于網絡情況是無法預測的,所以你必須保證分區容忍性。
那么我們的選擇有2個,CP和AP,即網絡可能出現分區時候,系統是無法同時保證一致性和可用性的
CP是什么?
出現分區情況時,節點收到請求后因為沒有得到其他人的確認就不應答
AP是什么?
出現分區情況時,節點只能應答非一致的結果
實際應用場景
既然 CAP 不可同時滿足,則設計系統時候必然要弱化對某個特性的支持。
弱化一致性
對結果一致性不敏感的應用,可以允許在新版本上線后過一段時間才更新成功,期間不保證一致性。
例如網站靜態頁面內容、實時性較弱的查詢類數據庫等,CouchDB、Cassandra 等為此設計。
弱化可用性
對結果一致性很敏感的應用,例如銀行取款機,當系統故障時候會拒絕服務。Redis 等為此設計。
Paxos、Raft 等算法,主要處理這種情況。
弱化分區容忍性
現實中,網絡分區出現概率減小,但較難避免。某些關系型數據庫、ZooKeeper 即為此設計。
實踐中,網絡通過雙通道等機制增強可靠性,達到高穩定的網絡通信。
tip 3:Paxos和Raft
故事背景是古希臘 Paxon 島上的多個法官在一個大廳內對一個議案進行表決,如何達成統一的結果。他們之間通過服務人員來傳遞紙條,但法官可能離開或進入大廳,服務人員可能偷懶去睡覺。
Paxos 被廣泛應用在 Chubby、ZooKeeper 這樣的系統
參考資料:https://yeasy.gitbooks.io/blockchain_guide/content/distribute_system/paxos.html
重要概念,proposer:提出提案,acceptor:負責投票,learner:被告知提案結果
需要保證 safety:決議是proposer提出的,且無歧義和liveness:有限時間
當獲取的acceptor支持超過一半時,即發送結果給所有人進行確認,因此當超過1/2的正常節點存在時,系統可以達成共識,如果在proposer提案時故障,則可通過超時機制,加重新新一輪提案加以解決。
需要兩階段提交
Why
在于只有一個階段的話,在多提案+多接收者情況下,無法確認是否獲得通過的提案是最終結果,可能還有后續的提案繼續提交通過。
所以引入新的一個階段,在proposer前一階段拿到反饋后,判斷這個提案是否被大多數接受,需要對其進行最終確認
how
準備階段解決大家對哪個提案進行投票的問題,提交階段解決確認最終值的問題。
prepare階段:
proposer:發送提案和編號到acceptor試探是否獲取多數接受者的支持
acceptor:保留接受到的提案的最大編號和接受的最大提案,時刻更新當前的最大提案號,不接受下雨最大提案號的提案(一般來說,算法當中,越是后提交的,即新的提案,編號越大,使用時間戳等方式)
commit:
proposer:如果收到大多數的回復,則可準備發送帶有提案號的接收消息。如果收到的回復不帶有新的提案,則說明鎖定成功,使用自己的提案;如果收到的回復帶有新的內容,則替換為編號更大的提案;如果沒有收到足夠多的請求,則再次發出請求
acceptor:接受消息后,如果發現提案號不小于已接受的最大提案號,則接受該提案,并更新最大提案號
一旦多數接受了共同的提案值,則形成決議,成為最終確認的提案
Raft
是Paxos的簡化實現。
包括三種角色:leader、candidate 和 follower,其基本過程為:
Leader 選舉:每個 candidate 隨機經過一定時間都會提出選舉方案,最近階段中得票最多者被選為 leader;
同步 log:leader 會找到系統中 log 最新的記錄,并強制所有的 follower 來刷新到這個記錄;
注:此處 log 并非是指日志消息,而是各種事件的發生記錄。
tip 2:拜占庭問題和算法
拜占庭將軍(Byzantine Generals Problem)問題,是 Leslie Lamport 1982 年提出用來解釋一致性問題的一個虛構模型。拜占庭是古代東羅馬帝國的首都,由于地域寬廣,守衛邊境的多個將軍(系統中的多個節點)需要通過信使來傳遞消息,達成某些一致的決定。但由于將軍中可能存在叛徒(系統中節點出錯),這些叛徒將努力向不同的將軍發送不同的消息,試圖會干擾一致性的達成。
對于拜占庭問題來說,假如節點總數為 N,叛變將軍數為 F,則當N≥3F+1時,問題才有解,即 Byzantine Fault Tolerant (BFT) 算法。
最簡單的
例如,N=3,F=1 時。
提案人不是叛變者,提案人發送一個提案出來,叛變者可以宣稱收到的是相反的命令。則對于第三個人(忠誠者)收到兩個相反的消息,無法判斷誰是叛變者,則系統無法達到一致。
提案人是叛變者,發送兩個相反的提案分別給另外兩人,另外兩人都收到兩個相反的消息,無法判斷究竟誰是叛變者,則系統無法達到一致。
更一般的推到了解即可
新的解決思路
拜占庭問題之所以難解,在于任何時候系統中都可能存在多個提案(因為提案成本很低),并且要完成最終的一致性確認過程十分困難,容易受干擾。但是一旦確認,即為最終確認。
比特幣的區塊鏈網絡在設計時提出了創新的 PoW(Proof of Work) 算法思路。一個是限制一段時間內整個網絡中出現提案的個數(增加提案成本),另外一個是放寬對最終一致性確認的需求,約定好大家都確認并沿著已知最長的鏈進行拓寬。系統的最終確認是概率意義上的存在。這樣,即便有人試圖惡意破壞,也會付出很大的經濟代價(付出超過系統一半的算力)。
后來的各種 PoX 系列算法,也都是沿著這個思路進行改進,采用經濟上的懲罰來制約破壞者