基於版本一致性演算法

2022-09-20 12:03:13 字數 2825 閱讀 7226

本文主要討論基於版本的一致性演算法,實現高可用和低延遲並且lazy read式的強資料一致性。可以利用在分布式的檔案系統的元資料管理。它主要解決以下內容:

避免使用鎖提供一致性

避免複製日誌提供一致性

快速故障恢復

自由集群擴容或縮容

缺點:無法提供高併發,需要使用其它機制提供高負載能力。

基於版本一致性演算法是乙個類paxos演算法,file store是由該演算法實現的分布式檔案管理系統(以下簡稱系統),本文以該系統為例說明該演算法。

該演算法定義了三個階段:選舉期,平穩期和故障期。系統大部分時間是在平穩期,就算是發生故障時,系統也不會立刻進入選舉期,只有在有讀寫操作失敗後才會由外部觸發新的選舉。選舉成功後,系統會立刻恢復到平穩期。

該系統中所有服務節點都是平等的citizen,但他們會在不同時期擔任以下三種角色中的一種:

leader - 負責寫操作,通知到所有節點備份和節點狀態管理

follower - 負責任何節點發起的選舉,負責資料的備份和讀取

candidate - 負責選舉

理論上任何乙個節點都可以隨時將自己設定為候選人從而發起選舉。但通常只有外部訪問失敗時才需要通知集群中某個節點發起選舉。

public bool startelection()

return false;

}

每次選舉最多只能產生乙個leader。為了實現這個要求,每個節點都持有乙個線性增長的選舉號。節點發起選舉時首先將自己的選舉號增加1個點,然後發起選舉給到所有節點。只有得到大多數節點的同意後選舉才算成功,否則選舉失敗。

所有節點在接收到選舉請求時都需要立刻執行選舉操作:

public bool dovote(int election_no, citizen citizen)

return false;

}

接收到選舉號後比較自己已經投出的選舉號,如果是新選舉號則同意這次選舉。

如果同一時間有多個節點發起選舉,選民會第一時間更新自己投出的選舉號(原子操作)因此不會同時同意兩個候選人發起的選舉。就算毫秒間先後同意了兩個候選人,然後候選人做後續的寫操作時也會失敗,從而修改自身的錯誤資訊。

只有leader才有資料的寫入權,當乙個leader接受到client的寫請求時:

public bool write(int index, bucket bucket)

this.type = citizentype.citizen;

return false;

}

leader首先會把資料加上自己當選的選舉號和資料的版本號,然後通知所有節點寫入備份,只有得到大多數節點的認可才更新本地資訊,否則修正自己的角色。

所有節點在接收到備份請求時都需要立刻執行備份操作:

public bool dowrite(bucket bucket, citizen citizen)

if (bucket.leaderno> this.votedno)

//s**e bucket to local disk

return true;

}

首先比較資料的建立者是否為自己投的leader,只有自己認可的或高於自己認可的leader的請求才處理,否則不執行任何操作。另外高於自己認可的leader的請求時,需要同步自己的leader資訊。

因為leader隨時都可能更改,但為了提高併發能力,資料一致性的確認只能在讀取時處理,所以資料讀取時,首先要確保本地資料是最新的,如果不是最新需要通知其它節點讀取最新的。

public bucket read(int index)

if (sendmessage("read", index))

else}​

public bool ensurerecovery(int index)

if (sendmessage("read", index))

return false;}​

首先判斷資料建立者是否為自己認可的leader,如果不是自己認可的leader建立,則立刻通知節點同步資料。需要注意的是,就算是自己認可的leader建立的資料也不能說明本地的資料已經最新,可能該節點已經失聯,也可能該節點在選舉和寫資料時失聯。因此還需要向所有節點傳送讀資料確認資料已經最新,然後才能返回資料。

所有節點在接收到讀取請求時都需要立刻執行讀取操作:

public tuple doread(int index, int versionno, citizen citizen)

if (versionno == bucket.leaderno)

return new tuple(false, null);

}

讀取本地資料並與要讀取資料的版本號比較,如果本地版本比較高則返回本地資料。如果版本相同只返回true,否則證明自己的資料已經無效。注意發現資料不同步後,並不需要及時解決資料一致性,直到有讀取操作時才去確保資料一致性。

因此寫入和讀取都需要得到大多數節點的確認,因此不存在資料一致性問題。最差的情況是,多數節點在讀取時失聯,從而會導致讀取失敗,這種情況只能由客戶端重試。

為了防止不一致性,該系統的節點擴/縮容需要緩慢進行。

擴容時,首先新節點的加入必須得到所有節點的確認,即所有節點都已經成功更新本地配置。然後確保只有乙個節點加入成功後才能增加新的節點。

縮容時,首先是停掉乙個節點,然後再通知所有節點移除該節點,並得到所有節點確認。

該系統理論上是強資料一致性的,由上面流程也能看出,所有的讀取都需要得到大多數節點的確認,這需要消耗多次的網路連線。因此建議:

系統需要盡量保證節點間的通訊穩定和高速

系統儲存的資料應該盡量少,比較適合儲存元資料

應對讀多寫少,而且對資料一致性要求不高的情況下,可以修改大多數讀確認的定義

強一致性 弱一致性 最終一致性

這種方式在es等分布式系統中也有體現,可以設定主shard提交即返回成功,或者需要replica shard提交成功再返回。提到分布式架構就一定繞不開 一致性 問題,而 一致性 其實又包含了資料一致性和事務一致性兩種情況,本文主要討論資料一致性 事務一致性指acid 複製是導致出現資料一致性問題的唯...

一致性hash演算法 面試必備 一致性hash演算法

最近公司在招人,我們準備的問題中有一道是關於一致性hash演算法的問題,只有一些面試者能夠回答上來,而且答的也不是很全面,有的面試者只是聽說過,有的連聽都沒聽過,下面我把一致性hash演算法整理一下分享給大家 一致性雜湊演算法在1997年由麻省理工學院的karger等人在解決分布式cache中提出的...

一致性hash演算法虛擬節點 一致性hash演算法

hash 演算法也叫做雜湊演算法,他可以讓任意長度的資料m對映成為長度固定的值h。hash演算法的第乙個作用就是資料的快速儲存與查詢。寫過程式的人都知道,基本上主流的程式語言裡面都有個資料結構叫做map dictionary或者 hash table 它是根據key來直接訪問結果的資料結構。key的...