2012年8月21日 星期二

理解 CAP 理論


CAP 理論在搞分散式的程式師中已經是路人皆知了。但是 CAP 理論就好比是相對論,雖然所有的人都知道,但是卻沒有多少人真正理解。

要真正理解 CAP 理論必須要讀懂它的形式化描述。 形式化描述中最重要的莫過於對 Consistency, Availability, Partition-tolerance 的準確定義。

Consistency (一致性) 實際上等同於系統領域的 before-or-after atomicity 這個術語,或者等同於 linearizable (可序列化) 這個術語。具體來說,系統中對一個資料的讀和寫雖然包含多個子步驟並且會持續一段時間才能執行完,但是在調用者看來,讀操作和寫操作都必須是單個的即時完成的操作,不存在重疊。對一個寫操作,如果系統返回了成功,那麼之後到達的讀請求都必須讀到這個新的資料;如果系統返回失敗,那麼所有的讀,無論是之後發起的,還是和寫同時發起的,都不能讀到這個資料。

要說清楚 Availability 和 Partition-tolerance 必須要定義好系統的故障模型。在形式化證明中,系統包含多個節點,每個節點可以接收讀和寫的請求,返回成功或失敗,對讀還要返回一個資料。和調用者之間的連接是不會中斷的,系統的節點也不會失效,唯一的故障就是報文的丟失。 Partition-tolerance 指系統中會任意的丟失報文(這和“最終會有一個報文會到達”是相對的)。 Availability 是指所有的讀和寫都必須要能終止。

注: “Availability 是指所有的讀和寫都必須要能終止” 這句話聽上去很奇怪,為什麼不是“Availability 是指所有的寫和讀都必須成功”? 要回答這個問題,我們可以仔細思考下“什麼是成功”。“成功”必須要相對於某個參照而言,這裡的參照就是 Consistency。

CAP 理論說在一個系統中對某個資料不存在一個演算法同時滿足 Consistency, Availability, Partition-tolerance 。 注意,這裡邊最重要和最容易被人忽視的是限定詞“對某個資料不存在一個演算法”。這就是說在一個系統中,可以對某些資料做到 CP, 對另一些資料做到 AP,就算是對同一個資料,調用者可以指定不同的演算法,某些演算法可以做到 CP,某些演算法可以做到 AP。

要做到 CP, 系統可以把這個資料只放在一個節點上,其他節點收到請求後向這個節點讀或寫資料,並返回結果。很顯然,序列化是保證的。但是如果報文可以任意丟失的話,接受請求的節點就可能永遠不返回結果。

要做到 CA, 一個現實的例子就是單點的資料庫。你可能會疑惑“資料庫也不是 100% 可用的呀?” 要回答這個疑惑,注意上面說的故障模型和 availability 的定義就可以了。

要做到 AP, 系統只要每次對寫都返回成功,對讀都返回固定的某個值就可以了。

如果我們到這裡就覺得已近掌握好 CAP 理論了,那麼就相當於剛把橘子剝開,就把它扔了。

CAP 理論更重要的一個結果是, 在 Partial Synchronous System (半同步系統) 中,一個弱化的 CAP 是能達到的:

* 對所有的資料訪問,總返回一個結果
* 如果期間沒有報文丟失,那麼返回一個滿足 consistency 要求的結果。

這裡的半同步系統指每個節點存在一個時鐘,這些時鐘不需要同步,但是按照相同的速率流逝。更通俗的來說,就是一個能夠實現超時機制的系統。

舉個例子,系統可以把這個資料只放在一個節點上,其他節點收到請求後向這個節點讀或寫資料,並設置一個計時器,如果超時前得到結果,那麼返回這個結果,否則返回失敗。

更進一步的,也是最重要的,實現一個滿足最終一致性 (Eventually Consistency) 和 AP 的系統是可行的。 現實中的一個例子是 Cassandra 系統。

沒有留言: