在分佈式系統的學習過程中,無論是讀論文還是做項目,總能看到好多名詞:Consistency, failure detector, order, timer;好多問題:Consensus, broadcast; 好多結論:FLP, CAP。瞭解單一名詞的意義比較容易,但這些名詞背後和分佈式系統的聯繫,和商業分佈式系統是如何利用這些理論的,一直不是很直觀。啃了好多論文,卻是隻見樹木,不見森林。偶然間翻閱到一個大神寫的博客,剛好串起了這個領域裏的一些知識點。
需要說明的是,因爲大神寫的也不是正式的論文,裏面難免有不嚴謹的地方。而我這篇博客也只是總結性質,又加上了自己的理解,難免有不嚴謹甚至錯誤的地方,發現之後再補充完善。附上原文鏈接,感興趣的同學可以之間看原文教程:
1. Distributed systems 介紹
一般來說,我們利用分佈式系統是爲了:
-
Storage:擴展存儲能力
-
Computation:擴展計算能力
當一個網站的數據量很小的時候,沒有必要使用分佈式系統,單點系統更加簡單可靠。但當數據量增大到一定數目時,單點系統可能會不足,而更換更好的單點系統又過於昂貴。這時候,我們可以採用分佈式系統。之所以要使用分佈式系統,根源在於數據量和業務量的擴張。
1.1 分佈式系統想要達成的目標
Scalability:
“Is the ability of a system,network, or process, to handle a growing amount of work in a capable manner or its ability to be enlarged to accommodate that growth。”
一個系統處理 “增長” 的能力(即增長之後性能不會受太大影響)。“增長”可以劃分爲三個維度:
-
Size scalability:增加nodes,可以使系統線性增長,增加dataset不會增加latency
-
Geographic scalability:
-
Administrative scalability:增加nodes不應該增加administrative costs
Performance(and latency):
Is characterized by the amount of useful work accomplished by a computer system compared to the time and resources used.
Performance就是看反應時間和消耗的資源。具體來說:
-
Low latency: 延遲
-
High throughout:吞吐量
-
Low utilization of computing resource: 資源利用率
Availability:
The proportion of time a system is in a functioning condition. If a user cannot access the system, it is said to be unavailable.
一個系統可用的時間所佔的比例。
從技術角度來說,availability 與 fault tolerant 相關。一個系統容錯能力強,它的availability也就可能越高。
Fault tolerance:
Ability of a system to behave in a well-defined manner once faults occur.
一個系統在出現錯誤時依然可以”behave in a well-defined manner”.
這裏所說的容錯,是容納你能考慮到的錯誤。定義所有你能想到的faults,之後用系統或算法來“容忍”它們。注意,你不能“容忍”沒有定義的faults。
1.2 分佈式系統中的模型
Abstractions and Models:
-
System model (asynchronous / synchronous)
-
Failure model: (crash-fail, partitions, Byzantine)
-
Consistency model:(strong, weak, eventual)
理想狀態下,我們想讓分佈式系統“表現得好像一個單系統”。但事與願違,不同種類的failures讓這個目標實現起來很困難。比如當出現partition(分區)的時候,你是要爲了availability接受用戶請求呢,還是爲了safety拒絕用戶。關於權衡分佈式系統各個方面的表現,最著名的就是CAP理論。
1.3 分佈式系統常用技術
Design techniques: partition and replicate
在節點之間如何分發數據是很重要的,它決定了如何定位數據以及我們如何處理它們。分佈式系統中關於數據有兩種technique:
-
Partition:把數據且分開,便於並行處理
-
Replication:把數據拷貝多份便於fault tolerance
在設計分佈式系統時,要想着這兩種方式。這是解決分佈式問題的兩大法寶,針對對兩個技術,有若干算法。
Partition的好處是:
-
Performance:限制數據塊大小,提高處理效率
-
Availability: 一個數據分塊,提高availability(一部分的損壞不會影響其餘部分)
Replication允許我們達到availability, performance,fault-telerance。
-
Afraid of loss of availability? 備份!
-
Slow computation? 在多個系統中進行計算
-
Slow I/O? 在本地緩存中備份數據。
但replication的引入也引起了consistency的問題。所以定義了不同級別的consistency model:
-
Strong model可以讓程序員感覺不到replication的存在。
-
weak model會讓程序員看到一些內部狀態,但是又提供了更短的latency和更高的 availability
2. Up and down the level of abstraction
爲了更好地描述分佈式系統,需要定義一系列的抽象來描述系統的特徵
-
System model
-
Nodes in the system model
-
Communication link between nodes
-
Timing / Ordering assumptions
在這些假設和抽象的基礎之上,我們又介紹了幾個很重要的問題和結論
-
The consensus problem
-
FLP and CAP
-
Consistency model
A system model
A set of assumptions about the environment and facilities on which a distributed system is implemented.
System model 是爲了抽象地描述一個分佈式系統的特徵。它一組assumptions,包括了各種特性:同步異步?通
一個System model也有強弱信延遲情況?之分,而一個健壯的system model是用了儘量弱的假設來構建的,這樣的話,針對這個模型所做的算法也更能適應其他模型。
Nodes in our system model
Nodes 是用來執行程序,儲存數據,提供時鐘的。它可以執行一系列的指令。
Nodes 可以有不同的Failure:
-
Crash-recovery. Node只可能停止工作。在停止工作後有方法可以恢復
-
Byzantine fault tolerance. 真實的系統中,很少應用byzantine fualt tolerance,引文它太過複雜和昂貴。
Communication links in our system model
這個特徵是用來描述信道的,例如信道是否可靠?
最多常用的設定是,一個系統中的不同節點之間有不同的信道,每個信道是FIFO的,每條接受到的消息必須是發送過的,消息不能丟失。
當節點還能工作,網絡又斷了的時候,network partition就出現了。
Timing / ordering assumptions
-
Synchronous:一條消息有確認的延遲上限。
-
Asynchronous: 一條消息沒有確定的延遲上限。
The consensus problem:
Consensus 問題就是所有的節點對某個值打成了共識。
Some computers (or nodes) achieve consensus if they all agree on some value. More formally:
-
Agreement: 所有正常的節點都同意
-
Integrity:所有的正常節點只能對最多一個值打成一致
-
Termination:最終總會達成一致
-
Validity:如果所有節點都提出V, 那麼系統要決定是V
Consensus 問題是很多商業分佈式系統的核心。 而consensus問題跟atomic broadcast和atomic commit都是相關聯的。
Two impossibility results:
兩個著名的“不可能推論”:FLP 和 CAP
FLP:
Assumption:
-
Asynchronous: 異步
-
Failure crash:只考慮crash
-
Message isn’t be lost:通信健壯
-
At most one process may fail:至多一個進程出問題
推論:
沒有一個consensus算法。
FLP告訴我們,當消息時延沒上限沒有的時候(異步系統),不存在一個完美的consensus算法。 話句話說,在一個收窄的異步模型當中(異步環境並且至多一個節點宕機),一個consensus算法不能同時滿足satety和liveness。
CAP:
Consistency, availability, partition tolerance不能同時達到
Consistency: 所有節點在看同一數據在同一時刻應該是同一狀態(注意,這裏的consistency和ACID中的不太一樣)。
Availability: 節點失效不會阻止倖存節點繼續工作。(針對節點失效)
Partition tolerance: 在消息丟失(網絡故障或者單點故障)時,系統可以繼續工作。(針對消息丟失)
不同的算法側重點也不一樣:
-
CA: 一些full strict quorum protocols。 比如two-phase commit
-
CP: 大部分的quorum protocols. 比如Paxos, RAFT
-
AP:protocols using conflict resolution. 比如 Dynamo,Gossip.
CA和CP在consistency方面都提供了 strong consistency。但他們的容錯能力是不一樣的,
CA不能容忍任何一個單點錯誤,而CP可以容忍一半以下的單點錯誤(參照Paxos)。
而在現有的分佈式體系中,常常需要保證分區容錯性,所以大多數情況下我們都需要在conssitency和availability中作抉擇:
不同級別的consistency:
-
Strong consistency models (capable of maintaining a single copy)
-
Linearizable consistency: 每個節點按原有的時間順序執行指令
-
Sequential consistency:每個節點按同樣的時間順序執行指令
-
-
Weak consistency models(not strong)
-
Client-centric consistency:
-
Causal consistency :
-
Eventual consistency :
-
簡單來說,Strong consistency可以讓我們把系統的所有節點等效想象成一個。 而weak consistency會出現不同的異常,但我們可以通過編碼來處理這些異常。
3. Time and order
本章講了一個分佈式系統中的時間和順序。對於order,定義的是先後順序。而對於time來說,除了先後順序以外,還包含了interpretation(如何解釋時間),duration(定義事件間隔)
3.1 Order
對於order,有兩種常見的order
-
Partial order
-
Total order
有個很簡單的數學表示:
Definition(partial order): A binary relation R on a set A is a partial order if and only if it is
(1) reflexive: a <= a
(2) antisymmetric: a<=b AND b<= a => a=b
(3) transitive: a<=b AND b<=c => a<=c
Definition(total order): A binary relation R on a set A is a total order if and only if it is
(1) a partial order, and
(2) for any pair of elements a and b of A, < a, b > R or < b, a > R.
比較起來,partial order定義了關係R的特性,而Total order強制每兩個事件之間都應該存在關聯。
3.2 Time
在不同的分佈式系統中,time的流動速率可能是不一樣的。“時間是按相同的速率在流動嗎?”
-
“Global clock”: yes
-
“Local clock” : no, but…...
-
“No clock” : no!
這三種時鐘,對應了三個系統模型
-
Synchronous: 支持Total Order
-
Partially synchronous:一種Partial order. 本地有序,跟遠程無序。
-
Asynchronous:另一種Partial order. 本地有序,遠程需要交互才能確定順序。
Global clock:
理想狀態下,這是指分佈式的每個節點共享同一個時鐘,保證”total order”,即系統範圍內的任意兩個操作都可以被賦予順序。
Cassandra就是建立在同步時鐘的基礎上,它利用全局的時間戳來判斷那個寫操作生效。
換句話說,你可以比較兩個不同節點上的時間戳來判斷順序
“Local Clock”:
Local clock 是指每個節點有一個本地時鐘(注意,時鐘的表現形式有多種,比如時間戳),我們保證本地的每兩個操作都是可以被賦予順序的。它提供了一種(注意,是一種!)“partial order”:本地的所有事件都是有序的,跨節點之間的事件時無序的。
換句話說,你不能通過比較本地時間戳和遠程時間戳來判斷兩個操作的順序,你不能直接比較兩個不同節點上的時間戳。
“No Clock”:
這裏的沒有時鐘clock,我們可以使用Vector clock或者causality(意味着我們不能定義間隔的長短)。它提供了另一種partial order:可以確定本地的順序,跨節點之間的順序需要由message change來確定。它不能使用duration!
3.3 如何使用Order和Time?
How is time used in a distributed system?
Order在分佈式系統中非常重要:
-
確定操作的順序可以保證正確性
-
確定操作的順序可以解決資源爭奪時候的先後問題
而一個Global clock可以確定整個系統的的order(即使節點之間沒有交流)。如果沒有Global clock,我們需要通過communication 來確定順序。
而Time可以用在failure detector上。Time 可以用在確定“high latency”還是”link is down”。即通過延遲來判斷系統究竟是延遲多了,還是宕機了。這裏,就引入了一個問題, failure detector!
3.4 系統中的邏輯時鐘
但是,在整個系統中使用真的時鐘很昂貴。
Lamport clock:
A Lamport clock is simple. Each process maintains a counter using the following rules:
-
Whenever a process does work, increment the counter
-
Whenever a process sends a message, include the counter
-
When a message is received, set the counter to max(local_counter, received_counter) + 1
弱點:比方說出現了partition 情況,這個時鐘就出現問題了。
Vector clock:
即給每節點都定一個計數,相當於每個節點都維護自己的一個lamport clock。
弱點:每個節點都要佔一位,太昂貴了。 有很多研究致力於減少時鐘的位數。
3.5 Failure detector
在分佈式系統中,一個節點需要“知道”另一個節點是出故障了還是僅僅因爲網絡延遲。理論上來說,我們可以通過合理的延遲時間來判斷,但是,什麼是合理的延遲時間呢?這個很難確定。
這個時候,我們就用到Failure detector了。簡單來說,failure detector用 “heartbeat messages” 和 “timers” 來實現。即不斷髮送“心跳信息”之後計算時間。而衡量Failure detector,有兩個重要特性: completeness 和 accuracy.
-
Strong completeness: Every crashed process is eventually suspected by every correct process
-
Weak completeness: Every crashed process is eventually suspected by some correct process.
-
Strong accuracy: No correct process is suspected ever.
-
Weak accuracy: Some correct process is never suspected.
通過不斷的給一個分佈式系統加限制,我們可以得到下面這個圖,它解釋了我們解決某個某個問題所需要的條件。
-
Reliable broadcast:
-
Consensus (Atomic broadcast)
-
Termination Reliable Broadcast (Non-blocking atomic commit)
-
Clock synchronization.
上圖表示在不同的系統中,我們可以解決的問題。值得注意的是,在一個異步系統中,如果我們加了 evetually weak failure detector(eventually weak accuracy + weak completeness),我們便可以解決consensus問題了。這是一個很有用的推論。FLP告訴我們即使在一個收窄的異步系統中,也不能解決consensus,但一旦加上了<>W ,就可以解決了。
3.6 總結
討論Time + Order + Synchronous要具體情況具體分析,並不是每個分佈式系統都要強制這些特性,在很多情況下,通過放鬆對某個方面的限制,我們可以得到更加好的成果。
4. Replication: preventing divergence
分佈式系統中經常會出現Replication. 這個章節在於介紹“preventing divergence”的Replication 策略,目的是保證不出現“不同”。
4.1 兩個基本的replication模型
Synchronous replication 和 Asynchronous replication是兩個最基礎的模型,後續講解的算法都是這兩個模型的具體實現。
Synchronous replication
在這種情況下,一次寫要接受所有其他節點的回覆。也就是,系統的性能依賴於最差的服務器。
Asynchronous replication:
4.2 兩種處理Replication的策略
有兩種處理Replication的策略:第一種是保證不出現“不同”,第二種是要處理“不同”
-
Replication methods that prevent divergence (single copy systems)
-
Replication methods that risk divergence (multi-master systems)
Single copy system讓整個系統“表現的像是一個節點”。每當部分節點宕機,系統可以保證只有一個active的值,還有,可以保證這個值被大家接受(其實就是consensus問題)
另外,consensus的解決也之間作用於 mutual exclusion, leader election, multicast, atomic broadcast.
4.3 Single copy consistency 的算法
用來維護single-copy consistency的算法有:
-
1n messages (asynchronous primary/backup)
-
2n messages (synchronous primary/backup)
-
4n messages (2-phase commit, multi-Paxos)
-
6n messages (3-phase commit, Paxos with repeated leader election)
需要區分的是,上述算法都是爲了保證single-copy,但是他們的容錯能力是不同的。注意區分算法和容錯能力。比如前兩種算法設計理想狀態都能保證一致性。但一旦出錯,出現不一致,這是它容錯性的問題。
4.4 Primary/backup
一個節點作爲主機,所有的update都作用在主機上,之後把log傳遞到其餘的副本。對於synchrounous來說(“update”+”acknowledge recipet”). 而對於asynchronous來說 (“update”.
例子: MySQL就是採用的異步P/B來進行數據備份。
缺陷: 就在於容錯的缺陷(比如主機掛掉),就會產生很多問題(副本寫入未寫入?)。
4.5 Two phase commit (2PC)
1. Voting: coordinator 給所有的participants發提議,participants同意之後把數據存到緩衝區,並回ACK
2. Decision: 拿到所有肯定的ACK後,coordinator發送commit請求
這個在synchronous P/B 的基礎上,增加了一次回覆,相當於允許系統回滾。比方說主機在等待ACK的時候掛了,那麼緩衝區的數據將被丟棄。
缺點: 只能保證CA, 不能保證P
4.6 Single copy中可以保證P的consensus算法
當我們看上述幾種算法的時候,我們發現他們並沒有保證P這個性質,下面,我們來討論可以保證P的算法
Single-copy中保證P的consensus算法:
-
Paxos:
-
Raft
-
ZAB:Zookeeper atomic broadcast.
4.7 總結
Primary/Backup
-
Single, static master
-
Replicated log, slaves are not involved in executing operations
-
No bounds on replication delay
-
Not partition tolerant
-
Manual/ad-hoc failover, not fault tolerant, "hot backup"
2PC
-
Unanimous vote: commit or abort
-
Static master
-
2PC cannot survive simultaneous failure of the coordinator and a node during a commit
-
Not partition tolerant, tail latency sensitive
Paxos
-
Majority vote
-
Dynamic master
-
Robust to n/2-1 simultaneous failures as part of protocol
-
Less sensitive to tail latency
5. Replication: weak consistency model protocols
第四章中提到的各個算法都是爲了保證single-copy,也就是強一致性。在這一章節裏,我們關注第二種策略:處理“不同”。即我們允許出現不同(而且不同是正常的),我們要做的就是如何處理這些不同然後得出正確的結果。
而允許不同處理不同的過程就違反了strong consistency,而轉向了eventual consistency:這些節點可以有不一樣的狀態,但是我保證到最後他們會趨於一致。
值得注意的是Dynamo, Cassandra等分佈式數據庫爲了提供A都部分捨棄了C, 毫無例外的提供了eventual consistency。而自上而下,我們總結一下Dynamo的設計思路是:
-
consistent hashing to determine key placement
-
partial quorums for reading and writing
-
conflict detection and read repair via vector clocks and
-
gossip for replica synchronization:當新加入節點或者節點恢復的時候,需要節點之間進行同步,Dynamo用的是gossip協議(基於分佈式failure detector 和 membership的)
通過consistent hashing來確定數據存放位置,利用Partial quorums來讀寫(W,R ,N),通過vector clocks來探測處理衝突, 利用Gossip協議來維持failure detector 和 membership.
6. 我的問題
在這個教程裏,並沒有特別詳盡得闡述一些問題,下面,我把我覺得重要或者自己不清楚的點列出來,以後有機會了再深入的學習:
-
CAP的理解。不同算法對應的是哪兩個特性?爲什麼Paxos對應CP,二段提交對應AP? 這個我存在疑問。
-
不同級別的consistency model。有很多不同的分類,需要確定一下。
-
Consensus算法和atomic broadcast等問題的等價性。
-
Dynamo 詳細研究
-
Gossip 的用法? 依照論文來說,Gossip是爲了同步節點,它的具體過程是什麼?如何運作的?
-
update算法
-
-
Paxos 和 Raft 的對比。
-
Zookeeper的使用
-
分佈式事務的判斷