分佈式同步

原文地址:http://blog.sina.com.cn/s/blog_4b99f86c0100073d.html

分佈式同步(synchronization)

    集中式系統中,由於只有一個時間源,所以同步不是問題。分佈式系統中,每個進程都運行在不同的機器上,所以很難對時間達成一致。這會影響程序的正確性,比如unix裏面的make。

1 時鐘同步
    由於絕對的同步無法達到,那麼需要了解分佈式的時鐘的基本要求:
    -沒有交互的進程之間時鐘不需要同步
    -進程間不是需要一個統一的時間,而是需要知道事件發生的先後順序
    -邏輯時鐘可以滿足上面要求
    邏輯時鐘:不需要和實際時間一致,只要能表示順序就行
    物理時鐘:必須和實際時間一致(UTC)

物理時鐘同步
Christian算法
   一種集中式的時間服務器擁有標準時間,所有機器都通過週期性詢問的方式與這個時間服務器同步。

Berkeley算法
    集中式的時間守護進程(daemon)沒有標準時間,通過週期性詢問所有的機器得到它們的時間,然後對這個時間取平均,再告訴每個機器如何同步(快幾分鐘或慢幾分鐘)。

邏輯時鐘同步
    目的是確定事件之間的happens-before關係。Happens-before關係定義爲:
    -同一進程內a發生先於b,則a->b(箭頭->表示happens-before關係)
    -a是進程1發送消息的事件,而b是進程2接收到那個消息的事件,則a->b
    -happens-before關係是可傳遞的,a->b and b->c則a->c
    -如果以上都不能確定關係的x和y,稱它們爲並行的事件(a||b)


Lamprot Timestamp
    當要確定兩個事件的先後順序的時候,通過比較時間戳來確定。時間戳可以是一個二元組(Ti, i),其中Ti是事件發生時進程i的邏輯時鐘,而i是進程i的進程id,其作用在於當兩個事件的邏輯時鐘相等時,雙方依然還是能夠給出一個一致的對於順序看法。
    Lamport算法其實也就是雙方互相比較Lamport時間戳,同步到比較快的時間。

Lamport算法
    使用時間戳確定事件的先後順序。每個進程有一個邏輯時鐘,本質上也就是一個不斷增加的計數器。
    Lamport算法的問題:
    1 不反映事件真實的順序;
    2 也無法反映事件的因果關係。
    解決辦法使用向量時鐘。

向量時鐘(vector clock)
    向量時鐘也就是每個進程都有一個邏輯時鐘向量,其中保存了它對所有其他進程邏輯時鐘的觀點(也就是它以爲別的進程的邏輯時鐘是什麼)。每個進程間的通信的消息都會帶上邏輯時間戳,而接收進程可以通過這個時間戳來更新它自己的時間。更新的原則是比較向量中每個元素,取相應元素的最大值。

確定事件先後關係
  • 如果兩事件的時間戳向量的所有分量都相等就是事件是同時發生的。
  • 如果事件a的時間戳的所有分量都小於事件b的時間戳,則說a->b。
  • 如果無法通過上面兩個辦法判斷,則說兩事件是並行的(concurrent)。


2 全局狀態和選舉算法
2.1 全局狀態
    有些應用需要知道全局狀態,比如垃圾回收(GC),死鎖檢測,進程的終止等。一個進程需要知道的全局狀態包括進程本身的狀態和當前要發送給該進程的消息。獲得全局狀態的算法主要是快照(snapshot)算法。   

快照(Snapshot)算法
    算法主要思想是通過一個特殊的消息(marker),把需要獲得全局狀態那個時刻與當前進程相關的信道的消息都擠空。
    算法過程:
    發起:
    a) 進程1需要知道全局狀態,則向所有其他進程發送marker消息,並開始記錄發送過marker消息的信道的狀態。
    記錄:
    a) 當進程從某個信道第一次收到marker消息的時候,則開始記錄該信道狀態。並且向所有其他信道發送marker。
    b) 若進程從某個信道第二次收到marker消息的時候,則結束記錄該信道狀態。將記錄到的信息當作該信道狀態。
    假設系統進程之間的聯繫可以表示成有向完全圖。如果把初始進程開始記錄消息看作是由於收到一個虛擬信道(不存在的)來的marker的話。那麼可以看出,每個進程第一次收到一個marker的時候,該進程的記錄就開始了,以後任何信道來的marker作用都只是結束記錄了。那麼,顯然每個進程都發送了n-1條消息,那麼n個進程共發送了(n-1)*n條消息,剛好覆蓋了所有的邊,每個信道剛好是一出一進,一開一關,所以算法最終會結束,而每個進程都會記錄到與之有關的全局狀態。

2.2 競選問題
假設:
    -每個進程有唯一數字ID
    -每個機器只有一個進程
    -每個進程都知道其他全部進程
    -進程並不知道哪些進程正常工作,那些已經出故障

大欺小(Bully)算法:
    1 某個進程x發起選舉,向所有id大於它的進程發選舉消息
    2 如果接收到大id進程的回覆,則放棄選舉
    3 接收到選舉消息的進程最回覆以後,會自己發起選舉,轉1
    4 如果沒有收到任何回覆,則x通知所有進自己作爲協調者
    選舉結果就是當前存在的id最大的進程會勝出。

環(Ring)算法
    將所有進程組織成環,如果協調進程崩潰了,發現協調者崩潰的進程發起一個選舉,首先把自己的進程號傳給下一個進程,每個進程收到選舉消息以後把自己的進程號加進去然後傳給下一個,如果下一個進程崩潰了,則傳給再下一個。當消息第二次回到發起進程時,消息就變成了確定協調者。發起進程再把確定消息發送出去,每個進程看到這個消息都以消息中編號最大的進程作爲協調者,當消息傳完這一圈以後就消失。


3 共享資源的同步
互斥
    臨界區的訪問問題。三個互斥條件:
  •     ME1 同一時間只有一個進程在臨界區中執行(safty)
  •     ME2 進入和推出臨界區的請求都要在有限時間內滿足(liveness)
  •     ME3 如果一個請求先於另外一個,那麼臨界區的授權也必須按照這個順序(order)

集中式算法
    由單一管理進程管理臨界區的使用。進入和推出都要求管理進程的同意。
分佈式算法(Ricart & Agrawala)
    每個要進入臨界區的進程先向所有其他進程發消息,得到全部同意後纔可進入。當有兩個進程同時想進入的時候,比較時間戳,小的可以進入。通過使用Lamport時間戳,可以使得所有進程對於進入請求達成一致。

令牌環
    進程組織成環,令牌在環中按順序傳播,誰得到令牌誰能進入。

事務處理
    事務模型、兩階段鎖、私人工作區、寫日誌、線性化。
  •     悲觀鎖  一次把所有將要用的資源都鎖定
  •     樂觀鎖  只是鎖定當前要用的資源

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