1. 程式人生 > >Paxos算法——前世

Paxos算法——前世

容錯 正常 們的 一定的 服務器 可變 請求 分發 服務器端

Paxos算法是基於消息傳遞且具有高度容錯特性的一致性算法。我們將從一個簡單的問題開始,逐步的改進我們的設計方案,最終得到Paxos,一個可以在逆境下工作的協議。

一、客戶端-服務器模型

我們從最小的分布式系統開始,在這個系統中,只有兩個結點,客戶端結點與服務端結點,客戶端結點能夠操作(存儲或更新)遠程服務器結點上的數據。

算法1.1 樸素的客戶端/服務器算法:客戶端每次向服務器發送一條命令。

在存在消息丟失的消息傳遞模型中,該算法卻不能很好的工作,客戶端不能確認消息是否正確的被服務器所接受。因此我們需要對其進行一些小的改進。

算法1.2 待確認的客戶端/服務器算法

1.客戶端向服務端發送一條請求命令消息。

2.服務端接受請求並回復確認信息。

3.客戶端在一定的時間範圍內,沒有收到服務器端發送的請求確認信息的回復,則重新發送命令請求信息。

  • 該算法描述了,客戶端在發送一條請求命令後,在收到服務端的確認回復前,是不會發送下一條請求命令。
  • 客戶端在發送的過程中消息可能丟失,服務端在回復的確認消息時,消息也可能丟失,對於服務端確認消息的丟失情況,在到達一定超時時間後,客戶端未收到確認回復,會重新發送消息,此時該消息已經被服務器端處理,所以我們需要有一種機制能夠保證消息的冪等性。例如給消息加上序列號。
  • 該算法可以很容易的擴展到多服務器端的場景,客戶端發送命令請求給每一個服務器端,當收到所有服務器的確認消息,就可以認為這條命令執行成功。
  • 如何處理多個客戶端的場景?
基於可變消息延遲模型我們可以得出如下定理,即消息的延遲時間是不定的,同一對結點的消息發送的時間延遲也是不同的。

定理1.1 如果算法在多個客戶端與服務端運行,服務器收到的命令順序可能是不同的,這會導致不一致的狀態。

假設在如下的場景中,存在客戶端c1,c2 ,服務端 s1,s2. 服務端s1,s2存在相同的值x = 0。 如果此時 c1,向服務器s1,s2 發送 x = x + 1. 在同一時刻 c2 向服務器 s1,s2 發送 x = 2*x. 假設c1 先於 c2 到達 s1 ,則此時s1的狀態值x為 2, 而 c2 先於 c1 到達 s2 , 則此時 s2 的狀態值x為 1. 導致集群的狀態不一致。

定義1.1 (狀態復制)對於一組結點,如果所有結點都以相同的順序執行命令序列 c1,c2,c3,c4……,則這組結點實現了狀態復制

  • 狀態復制是分布式系統的基本特征
  • 因為單個系統天然實現狀態復制,可以令單個服務器系統實現序列化器,自動對請求進行排序來分發命令,從而實現狀態復制。

算法1.3 借助單一的串行化器實現狀態復制

1. 所有的客戶端將請求命令發送到串行化器

2.串行化器逐個處理客戶端請求,並將客戶端請求逐個發送給所有服務器

3.當串行化器接受到所有服務器的確認消息時,它將返回給對應客戶端命令執行成功的消息。

  • 這個想法有時也被成為主從復制。
  • 改算法存在單點故障。串行化器
  • 我們是否可以構造一個更分布式的方法來解決狀態復制的問題。去掉串行化器。任何時刻最多只有一個結點可以發送請求命令,是否可以采用互斥或各自加鎖的思想?

算法 1.4 兩階段鎖

階段 1 :

客戶端向所有服務器請求獲取鎖

階段 2:

if 客戶端獲得所有服務器的加鎖請求

客戶端以可靠的方式向所有服務器發送命令請求,釋放鎖

else

客戶端釋放已經獲取的鎖,休眠一段時間,進入階段 1

  • 算法 1.4 是否能夠很好的應對結點崩潰呢?在該算法中要求所有的服務器結點都必須能夠正常的工作
  • 如果僅獲取部分服務器的鎖能否工作,獲得過半數服務器的鎖是否就足夠了?
  • 如果超過兩個以上的客戶端試圖獲取超過半數服務器的鎖,怎麽應對死鎖的問題,是否需要釋放已經獲取的服務器鎖,如果客戶端在釋放鎖之前就發生了故障,怎麽辦,是否需要一個與鎖不同的概念。

下一節中我們將從弱化的鎖機制來引出paxos算法 。

Paxos算法——前世