分佈式存儲框架的舉例說明

分佈式存儲系統變得越來越重要。這些系統往往採用廉價的商用機器或硬件,失效出錯成為了分佈式存儲系統的常態,因此,容錯是這類系統實現可用性和可靠性的關鍵。雖然有很多理論證明可以用,但理論距離現實還是有一定差距的,理論可以不管不顧消息在網絡中傳遞的次數,系統性能,吞吐量,系統設計的難易問題等等,但是真實的系統設計必須以整體的性能為根本依據。

因此如何權衡理論和現實系統,設計一個可用,正確,高效的複製協議變得尤為重要。相比於單純為了需求而設計一個具體的,特定的複製協議算法,不如選擇設計一個簡單,實用,具有普適適用性的複製框架,這樣不同的策略都可藉助於該框架實現,並且有助於不同的策略優劣的比較。

PacificA可稱之為一個原型系統。該框架簡單,實用,提供強一致性,並且可以適配不同的複製策略。以它為例來說明對我們理解分佈式系統的強一致性,容錯,仲裁有很好的指導意義。PacificA的設計特點:

  • 設計了一個通用和抽象的複製框架,模型容易驗證正確性,實現不同的策略實例

  • 配置管理和數據複製分離,Paxos負責管理配置,主副本策略負責數據複製

  • 將錯誤檢測和配置更新容在數據複製的交互裡面,去中心化,降低瓶頸

1、系統框架

整個系統框架主要有兩部分組成:存儲集群配置管理集群

存儲集群:負責系統數據的讀取和更新,通過使用多副本方式保證數據可靠性和可用性;

配置管理集群:維護副本信息,包括副本的參與節點,主副本節點,當前副本的版本等。

數據被存儲在數據分片上,數據分片實際上是數據集合,每個數據分片的大小基本固定,在存儲節點上,數據分片表現為磁盤上的一個大文件。而數據分片也是多副本的基本單位。

配置管理集群維護的其實是分片的副本信息(分片位於哪些節點)。數據分片的副本稱之為複製組(Replication Group)。因為每個存儲節點上會存在眾多的數據分片,因此,每個存儲節點會位於多個複製組中。

分佈式存儲框架的舉例說明

配置管理集群維護所有分片的位置信息,配置管理集群使用Paxos協議維護該數據的一致性。存儲集群以配置管理集群維護的分片位置信息為準。

2、數據複製框架

PacificA副本數據使用主從式框架來保證數據一致性。分片的多個副本中存在一個主副本Primary和多個從副本Secondary。所有的數據更新和讀取都進入主副本,當主副本出現故障無法訪問時系統會從其他從副本中選擇合適的節點作為新的主。

在PacificA協議中,每個節點都維護,數據更新的流程如下:

  1. 更新記錄進入主副本節點處理,為該記錄分配Sn(Serial Number),然後將該記錄插入prepare list,該list上的記錄按照sn有序排列;

  2. 主副本節點將攜帶sn的記錄發往從節點,從節點同樣將該記錄插入到prepare list;

  3. 一旦主節點收到所有從節點的響應,確定該記錄已經被正確寫入所有的從節點,那就將commit list向前移動,並將這些消息應用到主節點的狀態機;

  4. 主節點提交後即可給客戶端返回響應,同時向所有從節點發送消息,告訴從節點可以提交剛剛寫入的記錄了。

通過上面的分析可以知道,commit list和prepare list必然滿足以下條件:所有的讀需要全部發往主節點,這是因為客戶端來讀時,主節點有可能尚未將commit消息發送至從,因此,如果讀從節點可能會無法獲取最新數據。當然,如果應用能夠忍受一定的窗口,那讀從也無所謂。

分佈式存儲框架的舉例說明

3、配置管理服務

前面的PacificA架構中我們提到該框架一個很重要的組成部分是配置管理服務。該服務維護所有複製組信息,主要是複製組的當前節點信息:其中replica1,replica2…是複製組所有參與節點的地址,而version是當前複製組拓撲的版本,用來檢測拓撲是否最新。

在系統運行過程中可能有以下幾種情形導致複製組信息發生變更:

  • 複製組從節點離線;

  • 複製組主節點離線;

  • 複製組增加新節點

對每種情況處理方法:

  • 從節點離線,主節點能檢測到該事件(檢測方法下面部分說明),此時主節點向配置管理服務彙報最新的拓撲,注意此時的拓撲中已經不包含離線的從節點;

  • 主節點離線,從節點能檢測到該事件(檢測方法下面部分說明),此時從節點向配置管理服務彙報最新的拓撲,注意此時拓撲中已經不包含離線的主節點,同時從節點會將自己設置為主節點

  • 複製組增加新節點,可能是因為原來離線的節點又重新上線了,此時主節點向配置管理服務彙報最新的拓撲,注意此時的拓撲中加上該新增節點

需要注意的是:節點在向配置管理服務彙報新的拓撲時,會將自己當前維護的拓撲信息的版本號+1,然後再提交給配置管理服務。而配置管理服務在收到拓撲更新請求時,會對比客戶端傳入的拓撲版本和自己維護的拓撲的版本,如果客戶端的版本大於本地維護版本,接收之,否則,拒絕。

分佈式存儲框架的舉例說明

4、節點異常檢測

系統運行過程中難免出現節點宕機離線等諸多異常。如何保證在節點異常情況下協議的正常運行是分佈式系統設計中的關鍵問題。PacificA是一種強一致協議,通過主節點來維護多副本數據一致性。因此,需要確保每個副本的唯一主,避免二主問題的發生就非常關鍵。

PacificA使用了lease機制來保證不會產生二主問題。主節點與從節點維護心跳信息:主節點定期發送心跳,只要從節點響應該心跳,主節點就確定自己還是主。對於以下兩種可能的異常:

  • 如果主節點在一定時間內(lease period)未收到從節點對心跳的回應,那主節點認為從節點異常,於是向配置管理服務彙報更新複製集拓撲,將該異常從節點從複製集中移除,同時,它也將自己降級不再作為主;

  • 如果從節點在一定時間內(grace period)未收到主節點的心跳信息,那麼其認為主節點異常,於是向配置管理服務彙報回信複製集拓撲,將主節點從複製集中移除,同時將自己提升為新的主。

分析可知,只要lease period <= grace peroid,就不會產生二主問題,因為:

  • 假如主從之間出現網絡分區。只要lease period <= grace peroid,主必然先檢測到從沒有回覆的事件,於是他開始停止作為主服務,並且通知配置管理服務;

  • 由於lease period <= grace peroid,那麼從節點檢測到主節點異常則是在主節點停止作為主以後,此時該副本集是不存在主的,因此,必然不會產生二主現象。

說明:為什麼主在檢測到從節點異常時需要停止自己作為主的身份。

如果不這樣有可能會出現多主情況。分析一下,主節點不停止自己作為主,繼續對外提供更新服務,而直接向配置管理服務彙報從複製集中移除從節點的消息M1,而從節點經過一段時間後向配置管理服務彙報移除主節點並將自己提升為新主的消息M2,但是由於網絡傳輸的不確定性,配置管理服務可能會先處理M2,於是問題來了,這時候就產生了兩個主,破壞系統的強一致性。

使用租約機制保證一致性是眾多分佈式系統的標準做法,例如GFS、Bigtable等。但是諸如GFS、Bigtable都是從一個集中式服務中申請lease,而PacificA則是一種去中心化式的租約機制。另外,主從之間的數據流動也天然發揮了心跳信息的功能,因此只要主從之間有數據交換,就可以無需發送心跳。

5、節點異常處理

5.1、從節點異常

從節點異常時,主節點降級,不再作為主,並向配置管理服務發送請求從複製集集中移除異常從節點。接下來,配置管理服務器更新本地的複製集,新的複製集中不再包含異常從節點。接下來從節點再向配置管理服務申請成為新的主,於是,接下來選出的新的主再對外提供服務。

5.2、主節點變更

當從節點檢測到主節點異常時,向配置管理服務申請將主節點從複製集中移除並且將自己提升為新的主。一旦配置管理服務批准了從節點的請求,那從節點變成新的主,這時候主也被從副本集中剔除。

分佈式存儲框架的舉例說明

上面是Primary和Secondary-2兩個節點之間出現了網絡異常。接下來,配置管理服務器可能會收到三個節點發起的拓撲重配置請求M1,M2和M3。

M1:主節點DATA NODE 2將自己降級為從,同時向配置管理服務發起移除dn3的請求,我的理解是,如果配置管理服務批准了該請求,那麼該節點重新成為主;

M2:從節點DATA NODE 3可能只是與主節點出現網絡分區,進程還在,此時從節點DATA NODE 3向配置管理服務發起Change Primary請求並將主節點DATA NODE 2從複製集中移除;

M3:因為主節點DATA NODE 2放棄了主節點的身份,因此,可能導致DATA NODE 1在心跳週期內也無法獲得心跳,於是它也有可能發起一次Change Primary請求,將主節點dn2移除,將自己提升為新的主。

而配置管理服務器會根據請求的先後順序來處理,對於上述M1、M2、M3請求,只有一個會得到批准,假如M1得到批准,那麼新的結構就變為:

分佈式存儲框架的舉例說明

此時DATA NODE 3便被從複製集中剔除了。當然,如果DATA NODE 3進程依然存活的話,它接下來還是可以向配置管理服務申請將自己加入複製組的。在確定新的複製組拓撲後,還要經歷一個reconciliation過程。該過程的主要目的是保持從節點和主節點的數據一致性,主要過程是主節點將自己的prepare list上的操作記錄全部提交至狀態機並將自己的prepare list記錄同步至從。對於從節點來說,有可能其prepare list落後於主節點,這時候需要補齊,有可能其prepare list領先於從節點,這時候需要截斷。無論如何,由於滿足prepare list和commit list的定式關係,因此不會出現已經提交的記錄被回滾的情況。

分佈式存儲框架的舉例說明

6、基於日誌的數據同步方法

基於日誌的狀態機同步方案的架構一般如下:

分佈式存儲框架的舉例說明

LOG:日誌,保證數據可靠性,所有的更新都是按照sn順序寫入日誌,

IN-MEMORY: 內存狀態機,當更新記錄追加日誌成功後便可以被更新在內存狀態機;

CHECKPOINT:內存狀態機容量有限,需要定期將內存狀態機內容寫入磁盤,內存狀態機在磁盤的映像就是Checkpoint了,一旦執行了Checkpoint,那LOG中與該Checkpoint相關的日誌項便可以刪除了;

ON-DISK-IMAGE:CHECKPOINT數量眾多,需要將眾多的CHECKPOINT進行merge為ON-DISK-IMAGE,

6.1、同步日誌

該方法在主從節點上同時維護上述一整套結構,主節點向從節點同步LOG,從節點執行LOG內容,這也是多數分佈式系統維護主從狀態一致性的做法,就不再多說了。

6.2、同步日誌變種

這種方法在上面的基礎上作了一點改動:從節點不再維護IN-MEMORY、CHECKPOINT、ON-DISK-IMAGE等結構,為了減少從節點的內存和計算開銷。主節點除同步LOG外,還將CHECKPOINT、ON-DISK-IMAGE也一併同步至從節點,這樣做的缺點是:1. 增加網絡負載;2. 從節點在變成新的主以後,還要加載Checkpoint和日誌,以便在內存中構造IM-MEMORY狀態機,延長了系統不可用時間。一般這種做法不多。

6.3分層設計

嚴格來說,這種屬於偷懶做法:將可靠性交給底層的文件系統來保證,即存放LOG的不再是單機文件系統,而是分佈式文件系統。BigTable、HBase等都是採用這種做法。BigTable底層使用了GFS,而HBase底層則使用了HDFS。


分享到:


相關文章: