多IDC的數據分佈設計(一)

上個月跟某個朋友談及多IDC數據同時讀寫訪問的問題(tweet),當時覺得有不少解決方案,但覺得思路還不夠清晰。最近看了Google App Engine工程師Ryan Barrett介紹GAE後端數據服務的演講稿Transactions Across Datacenters(視頻),用Ryan的方法來分析這個問題後就豁然開朗。

按Ryan的方法,多IDC實現有以下幾種思路。

一、Master/slave

這個是多機房數據訪問最常用的方案,一般的需求用此方案即可。因此大家也經常提到“premature optimization is the root of all evil”。
優點:利用mysql replication即可實現,成熟穩定。
缺點:寫操作存在單點故障,master壞掉之後slave不能寫。另外slave的延遲也是個困擾人的小問題。

二、Multi-master

Multi-master指一個系統存在多個master, 每個master都具有read-write能力,需根據時間戳或業務邏輯合併版本。比如分佈式版本管理系統git可以理解成multi-master模式。具備最終一致性。多版本數據修改可以借鑑Dynamo的vector clock等方法。

優點:解決了單點故障。
缺點:不易實現一致性,合併版本的邏輯複雜。

三、Two-phase commit(2PC)

Two-phase commit是一個比較簡單的一致性算法。由於一致性算法通常用神話(如Paxos的The Part-Time Parliament論文)來比喻容易理解,下面也舉個類似神話的例子。

某班要組織一個同學聚會,前提條件是所有參與者同意則活動舉行,任意一人拒絕則活動取消。用2PC算法來執行過程如下

Phase 1

Prepare: 組織者(coordinator)打電話給所有參與者(participant) ,同時告知參與者列表。
Proposal: 提出週六2pm-5pm舉辦活動。
Vote: participant需vote結果給coordinator:accept or reject。
Block: 如果accept, participant鎖住週六2pm-5pm的時間,不再接受其他請求。

Phase 2

Commit: 如果所有參與者都同意,組織者coodinator通知所有參與者commit, 否則通知abort,participant解除鎖定。

Failure 典型失敗情況分析

Participant failure:
任一參與者無響應,coordinator直接執行abort
Coordinator failure:
Takeover: 如果participant一段時間沒收到cooridnator確認(commit/abort),則認爲coordinator不在了。這時候可自動成爲Coordinator備份(watchdog)
Query: watchdog根據phase 1接收的participant列表發起query
Vote: 所有participant回覆vote結果給watchdog, accept or reject
Commit: 如果所有都同意,則commit, 否則abort。

優點:實現簡單。
缺點:所有參與者需要阻塞(block),throughput低;無容錯機制,一節點失敗則整個事務失敗。

四、Three-phase commit (3PC)

Three-phase commit是一個2PC的改進版。2PC有一些很明顯的缺點,比如在coordinator做出commit決策並開始發送commit之後,某個participant突然crash,這時候沒法abort transaction, 這時候集羣內實際上就存在不一致的情況,crash恢復後的節點跟其他節點數據是不同的。因此3PC將2PC的commit的過程1分爲2,分成preCommit及commit, 如圖。
 


(圖片來源:http://en.wikipedia.org/wiki/File:Three-phase_commit_diagram.png)

從圖來看,cohorts(participant)收到preCommit之後,如果沒收到commit, 默認也執行commit, 即圖上的timeout cause commit。

如果coodinator發送了一半preCommit crash, watchdog接管之後通過query, 如果有任一節點收到commit, 或者全部節點收到preCommit, 則可繼續commit, 否則abort。

優點:允許發生單點故障後繼續達成一致。
缺點:網絡分離問題,比如preCommit消息發送後突然兩個機房斷開,這時候coodinator所在機房會abort, 另外剩餘replicas機房會commit。

五、Paxos

Google Chubby的作者Mike Burrows說過, “there is only one consensus protocol, and that’s Paxos” – all other approaches are just broken versions of Paxos. 意即“世上只有一種一致性算法,那就是Paxos”,所有其他一致性算法都是Paxos算法的不完整版。相比2PC/3PC, Paxos算法的改進

  • P1a. 每次Paxos實例執行都分配一個編號,編號需要遞增,每個replica不接受比當前最大編號小的提案
  • P2. 一旦一個 value v 被replica通過,那麼之後任何再批准的 value 必須是 v,即沒有拜占庭將軍(Byzantine)問題。拿上面請客的比喻來說,就是一個參與者一旦accept週六2pm-5pm的proposal, 就不能改變主意。以後不管誰來問都是accept這個value。
  • 一個proposal只需要多數派同意即可通過。因此比2PC/3PC更靈活,在一個2f+1個節點的集羣中,允許有f個節點不可用。

另外Paxos還有很多約束的細節,特別是Google的chubby從工程實現的角度將Paxos的細節補充得非常完整。比如如何避免Byzantine問題,由於節點的持久存儲可能會發生故障,Byzantine問題會導致Paxos算法P2約束失效。

以上幾種方式原理比較如下

 

(圖片來源:http://snarfed.org/space/transactions_across_datacenters_io.html)

後文會繼續比較實踐環境選取何種策略合適。

(PS: 寫完後在Google Reader上發現本文跟王建碩最近發表的《關於兩個機房的討論》文章有點類似,特別是本文一、二方式。不過他的文章偏MySQL的實現,我的重點是一致性算法,大家可以有選擇性的閱讀。)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章