1. 程式人生 > >分散式一致性演算法:paxos

分散式一致性演算法:paxos

一、背景

分散式系統中存在資料一致性問題,一般可以通過共享記憶體(需要鎖)或者訊息傳遞實現。目前解決此類問題的主流演算法是Paxos 演算法,採用的是訊息傳遞實現。

二、介紹

作為一個基於訊息傳遞的一致性演算法, LeslieLamport 在 1990 年提出,近幾年被廣泛應用於分散式計算中,被認為是到目前為止唯一的分散式一致性演算法,其它的演算法都是 Paxos的改進或簡化。有個問題要提一下, Paxos 有一個前提:沒有拜占庭將軍問題。就是說 Paxos只有在一個可信的計算環境中才能成立,這個環境是不會被入侵所破壞的。(暫時理解為指一方向另一方傳送訊息,另一方沒有收到,傳送方也無法確認訊息確實丟失的情形,也即節點之間訊息傳遞要不成功要不失敗,沒有模糊不清楚的情況

!)

三、應用

         Paxos演算法主要應用為分散式協調服務框架:

Google 的Chubby;

Apache 的Zookeeper,是Google 的 Chubby一個開源的實現。

四、原理

         Paxos描述了這樣一個場景,有一個叫做 Paxos 的小島(Island)上面住了一批居民,島上面所有的事情由一些特殊的人決定,他們叫做議員(Senator)。議員的總數(Senator Count)是確定的,不能更改。島上每次環境事務的變更都需要通過一個提議(Proposal),每個提議都有一個編號(PID),這個編號是一直增長的,不能倒退。每個提議都需要超過半數((Senator Count)/2+1)的議員同意才能生效。每個議員只會同意大於當前編號的提議,包括已生效的和未生效的。如果議員收到小於等於當前編號的提議,他會拒絕,並告知對方:你的提議已經有人提過了。這裡的當前編號是每個議員在自己記事本上面記錄的編號,他不斷更新這個編號。整個議會不能保證所有議員記事本上的編號總是相同的。現在議會有一個目標:保證所有的議員對於提議都能達成一致的看法。

好,現在議會開始運作,所有議員一開始記事本上面記錄的編號都是 0。有一個議員發了一個提議:將電費設定為1元/度。他首先看了一下記事本,嗯,當前提議編號是 0,那麼我的這個提議的編號就是 1,於是他給所有議員發訊息: 1 號提議,設定電費 1 元/度。其他議員收到訊息以後查了一下記事本,哦,當前提議編號是 0,這個提議可接受,於是他記錄下這個提議並回復:我接受你的 1 號提議,同時他在記事本上記錄:當前提議編號為 1。發起提議的議員收到了超過半數的回覆,立即給所有人發通知: 1 號提議生效!收到的議員會修改他的記事本,將 1 好提議由記錄改成正式的法令,當有人問他電費為多少時,他會檢視法令並告訴對方:1 元/度。

現在看衝突的解決:假設總共有三個議員S1-S3,S1 和 S2同時發起了一個提議:1 號提議,設定電費。 S1 想設為 1 元/度, S2 想設為 2 元/度。結果 S3 先收到了 S1 的提議,於是他做了和前面同樣的操作。緊接著他又收到了 S2 的提議,結果他一查記事本,咦,這個提議的編號小於等於我的當前編號 1,於是他拒絕了這個提議:對不起,這個提議先前提過了。於是 S2 的提議被拒絕, S1 正式釋出了提議: 1 號提議生效。 S2 向 S1 或者 S3 打聽並更新了 1號法令的內容,然後他可以選擇繼續發起 2 號提議。

好, Paxos 的精華就這麼多內容。現在讓我們來對號入座,看看在 ZK Server 裡面 Paxos是如何得以貫徹實施的。

         小島(Island)——ZK Server Cluster

         提議(Proposal)——ZNodeChange(Create/Delete/SetData)

         提議編號(PID)——Zxid(ZooKeeperTransaction Id)

         正式法令——所有 ZNode及其資料

         議員——ZK節點

         貌似關鍵的概念都能一一對應上,但是等一下, Paxos 島上的議員應該是人人平等的吧,而 ZK Server 好像有一個 Leader 的概念。沒錯,其實 Leader 的概念也應該屬於 Paxos 範疇的。如果議員人人平等,在某種情況下會由於提議的衝突而產生一個“活鎖”(所謂活鎖我的理解是大家都沒有死,都在動,但是一直解決不了衝突問題)。 Paxos 的作者 Lamport 在他的文章”The Part-Time Parliament“中闡述了這個問題並給出瞭解決方案——在所有議員中設立一個總統,只有總統有權發出提議,如果議員有自己的提議,必須發給總統並由總統來提出。好,我們又多了一個角色:總統。

         總統——ZK ServerLeader

又一個問題產生了,總統怎麼選出來的?

現在我們假設總統已經選好了,下面看看 ZKServer 是怎麼實施的。

情況一:

平民甲(Client)到某個議員(ZKServer)那裡詢問(Get)某條法令的情況(ZNode 的資料),議員毫不猶豫的拿出他的記事本(local storage),查閱法令並告訴他結果,同時宣告:我的資料不一定是最新的。你想要最新的資料?沒問題,等著,等我找總統 Sync 一下再告訴你。

情況二:

平民乙(Client)到某個議員(ZKServer)那裡要求政府歸還欠他的一萬元錢,議員讓他在辦

公室等著,自己將問題反映給了總統,總統詢問所有議員的意見,多數議員表示欠屁民的錢一定要還,於是總統發表宣告,從國庫中拿出一萬元還債,國庫總資產由 100 萬變成 99 萬。屁民乙拿到錢回去了(Client 函式返回)。

         情況三:

總統突然掛了,議員接二連三的發現聯絡不上總統,於是各自發表宣告,推選新的總統,總統大選期間政府停業,拒絕平民的請求。

         到此為止,當然還有很多其他的情況,但這些情況總是能在 Paxos 的演算法中找到原型並加以解決。這也正是我們認為 Paxos 是 Zookeeper 的靈魂的原因。