您的位置:首頁>正文

分散式存儲系統能力縱談

異常分類

分散式存儲系統所關注的異常類型和單體系統不一樣, 有如下幾種:

伺服器宕機:設計存儲系統時需要考慮如何通過讀取持久化介質(如機械硬碟, 固態硬碟)中的資料來恢復記憶體資訊。

網路異常:設計容錯系統的一個基本原則是:網路永遠是不可靠的, 任何一個消息只有收到對方的回復後才可以認為發送成功, 系統設計時總是假設網路將會出現異常並採取相應的處理措施。

磁片故障:對於磁片資料錯誤, 往往可以採用校驗和( checksum)機制來解決。

除了異常之外, 還存在“超時”狀態, RPC執行的結果有三種狀態:“成功”、“失敗”、“超時”(未知狀態),

也稱為分散式存儲系統的三態。

一致性保證

副本是分散式存儲系統容錯技術的唯一手段。 由於多個副本的存在, 如何保證副本之間的一致性是整個分散式系統的理論核心。 從用戶端的角度來看, 一致性包含如下三種情況:

1、強一致性:

2、弱一致性:

3、最終一致性:最終一致性是弱一致性的一種特例。 “最終”一致性有一個“不一致視窗”(時間延遲), 最終一致性描述比較粗略, 其常見的變體如下:

讀寫( Read-your-writes)-致性

會話( Session)-致性

單調讀( Monotonic read)-致性

單調寫( Monotonic write)-致性

從存儲系統的角度看, 一致性主要包含如下幾個方面:

1) 副本一致性:存儲系統的多個副本之間的資料是否一致, 不一致的時間視窗等;

2) 更新順序一致性:存儲系統的多個副本之間是否按照相同的循序執行更新操作。

衡量指標

評價分散式存儲系統有一些常用的指標:

性能:吞吐能力(QPS、TPS)、回應延遲。

可用性:系統的可用性可以用系統停服務的時間與正常服務的時間的比例來衡量。

一致性:越是強的一致性模型,

使用者使用起來越簡單。 如果系統部署在同一個資料中心, 只要系統設計合理, 在保證強一致性的前提下, 不會對性能和可用性造成太大的影響。

可擴展性:系統的可擴展性( scalability)指分散式存儲系統通過擴展集群伺服器規模來提高系統存儲容量、計算量和性能的能力。

性能分析

一般來說, 對分散式系統的性能分析的結果是不精確的, 然而, 至少可以保證, 估算的結果與實際值不會相差一個數量級。 舉個例子, Google的BigTable中隨機寫和順序寫的性能是差不多的, 寫入操作需要首先將操作日誌寫入到GFS, 接著修改本地記憶體。 為了提高性能, BigTable實現了成組提示技術。

只有理解存儲系統的底層設計和實現, 並在實踐中不斷地練習,

性能估算才會越來越准。

資料分佈

1、雜湊分佈(代表:Dynomo):如果雜湊函數的散列特性很好, 雜湊方式可以將資料比較均勻地分佈到集群中去。 然而, 找出一個散列特性很好的雜湊函數是很難的。 這是因為, 如果按照主鍵散列, 那麼同一個使用者id下的資料可能被分散到多台伺服器, 這會使得一次操作同一個用戶id下的多條記錄變得困難;如果按照使用者id散列, 容易出現“資料傾斜”(data skew)問題, 即某些大使用者的資料量很大, 無論集群的規模有多大, 這些用戶始終由一台伺服器處理。 另一種思路就是採用一致性雜湊( Distributed Hash Table, DHT)演算法(順時針查找)。 一致性雜湊的優點在於節點加入/刪除時只會影響到在雜湊環中相鄰的節點, 而對其他節點沒影響。

一致性雜湊演算法在很大程度上避免了資料移轉。 Dynamo系統通過犧牲空間換時間, 在每台伺服器維護整個集群中所有伺服器的位置資訊, 將查找伺服器的時間複雜度降為O(l)。 一致性雜湊還需要考慮負載均衡, 比較好的做法是引入“虛擬節點”的概念。

2、順序分佈(代表:BigTable):雜湊散列破壞了資料的有序性, 只支援隨機讀取操作, 不能夠支援順序掃描。 順序分佈在分散式表格系統中比較常見, 一般的做法是將大表順序劃分為連續的範圍, 每個範圍稱為一個子表。 Bigtable將一張大表根據主鍵切分為有序的範圍, 每個有序範圍是一個子表。 為了支援更大的集群規模, Bigtable這樣的系統將索引分為兩級:根表以及中繼資料表(Meta表), 由Meta表維護User表的位置資訊。 順序分佈與B+樹資料結構比較類似,每個子表相當於葉子節點,隨著資料的插入和刪除,某些子表可能變得很大,某些變得很小,資料分佈不均勻。如果採用順序分佈,系統設計時需要考慮子表的分裂與合併。子表合併的目的是為了防止系統中出現過多太小的子表,減少系統中的中繼資料。

3、負載均衡:工作節點通過心跳包(Heartbeat,定時發送)將節點負載相關的資訊,如CPU,記憶體,磁片,網路等資源使用率,讀寫次數及讀寫資料量等發送給主控節點。負載均衡操作需要控制節奏,負載均衡操作需要做到比較平滑,一般來說,從新機器加入,到集群負載達到比較均衡的狀態需要較長一段時間,比如30分鐘到一個小時。

複製

複製協議分為兩種:強同步複製和非同步複製,如圖1。

圖1 主備複製協議示範

強同步複製和非同步複製都是將主副本的資料以某種形式發送到其他副本,這種複製協議稱為基於主副本的複製協議( Primary-based protocol)。這種方法要求在任何時刻只能有一個副本為主副本,由它來確定寫操作之間的順序。如果主副本出現故障,需要選舉一個備副本成為新的主副本,這步操作稱為選舉,經典的選舉協定為Paxos協定。

主備副本之間的複製一般通過操作日誌來實現。操作日誌的原理很簡單:為了利用好磁片的順序讀寫特性,將用戶端的寫操作先順序寫入到磁片中,然後應用到記憶體中,由於記憶體是隨機讀寫設備,可以很容易通過各種資料結構,比如B+樹將資料有效地組織起來。當伺服器宕機重啟時,只需要重播操作日誌就可以恢復記憶體狀態。為了提高系統的併發能力,系統會積攢一定的操作日誌再批量寫入到磁片中,這種技術一般稱為成組提交。

如果每次伺服器出現故障都需要重播所有的操作日誌,效率是無法忍受的,檢查點( CheckPoint)正是為了解決這個問題。系統定期將記憶體狀態以檢查點檔的形式dump到磁片中,並記錄檢查點時刻對應的操作日誌重播點。檢查點檔成功創建後,重播點之前的日誌可以被垃圾回收,以後如果伺服器出現故障,只需要重播檢查點之後的操作日誌。(記憶體中只有“檢查點”之後的資料)

分散式存儲系統要求能夠自動容錯,也就是說,CAP理論中的“分區可容忍性”總是需要滿足的,因此,一致性和寫操作的可用性不能同時滿足。例如,Oracle教據庫的DataGuard複製元件包含三種模式:

最大保護模式( Maximum Protection):即強同步複製模式,寫操作要求主庫先將操作日誌(資料庫的redo/undo日誌)同步到至少一個備庫才可以返回用戶端成功。

最大性能模式( Maximum Performance):即非同步複製模式,寫操作只需要在主庫上執行成功就可以返回用戶端成功。

最大可用性模式( Maximum Availability):上述兩種模式的折衷。

容錯

常見故障中,單機故障和磁片故障發生概率最高。在分散式系統中,可以通過租約(Lease)機制進行故障檢測。

租約機制就是帶有超時時間的一種授權。假設機器A需要檢測機器B是否發生故障,機器A可以給機器B發放租約,機器B持有的租約在有效期內才允許提供服務,否則主動停止服務。需要注意的是,實現租約機制時需要考慮一個提前量。

故障恢復中,總控節點一般需要等待一段時間,比如1個小時,如果之前下線的節點重新上線,可以認為是臨時性故障,否則,認為是永久性故障。停服務時間包含兩個部分,故障檢測時間以及故障恢復時間。故障檢測時間一般在幾秒到十幾秒,和集群規模密切相關,集群規模越大,故障檢測對總控節點造成的壓力就越大,故障檢測時間就越長。

圖2 故障恢復

可擴展性

分散式存儲系統大多都帶有總控節點,基於這點,很多人會自然地認為總控節點存在瓶頸問題,認為去中心化的P2P架構更有優勢。然而,事實卻並非如此,主流的分散式存儲系統大多帶有總控節點,且能夠支援成千上萬台的集群規模。可擴展性應該綜合考慮節點故障後的恢復時間,擴容的自動化程度,擴容的靈活性等。

分散式存儲系統中往往有一個總控節點用於維護資料分佈資訊,執行工作機管理,資料定位,故障檢測和恢復,負載均衡等全域調度工作。通過引入總控節點,可以使得系統的設計更加簡單,並且更加容易做到強一致性,對用戶友好。那麼,總控節點是否會成為性能瓶頸呢?如果總控節點成為瓶頸,例如需要支援超過一萬台的集群規模,或者需要支援海量的小檔,那麼,可以採用兩級結構,如圖3所示。

圖3 兩級中繼資料結構

在資料庫的擴容中,如果系統的讀取能力不足,可以通過增加副本的方式解決,如果系統的寫入能力不足,可以根據業務的特點重新拆分數據,常見的做法為雙倍擴容,即將每個分片的資料拆分為兩個分片,擴容的過程中需要遷移一半的資料到新加入的存儲節點。傳統的資料庫架構在可擴展性上面臨如下問題:

1. 擴容不夠靈活。

2. 擴容不夠自動化。

3. 增加副本時間長。

同一個組內的節點服務相同的資料,這樣的系統稱為同構系統。同構系統的問題在於增加副本需要遷移的資料量太大,由於拷貝資料的過程中存儲節點再次發生故障的概率很高,所以這樣的架構很難做到自動化,不適用大規模分散式存儲系統。而異構系統將資料劃分為很多大小接近的分片,每個分片的多個副本可以分佈到集群中的任何一個存儲節點。由於整個集群都參與到節點的故障恢復過程,故障恢復時間很短,而且集群規模越大,優勢就會越明顯。

圖4 同構系統和異構系統的區別

分散式協定

在電腦世界裡,為了解決一件事情,另外的問題就會接踵而至,從另一個層面印證了IT架構永遠是一種平衡的藝術。

“BASE”其核心思想是根據業務特點,採用適當的方式來使系統達到最終一致性(Eventual consistency);在互聯網領域,通常需要犧牲強一致性來換取系統的高可用性,只需要保證資料的“最終一致”,只是這個最終時間需要在使用者可以接受的範圍內;但在金融相關的交易領域,仍然需要採用強一致性的方式來保障交易的準確性與可靠性。

業界常見的交易處理模式很多,包括兩階段提交、三階段提交、Sagas長事務、補償模式、可靠事件模式(本地事件表、外部事件表)、可靠事件模式(非事務消息、事務消息)、TCC、Paxos及其相關變種等等。不同的事務模型支援不同的資料一致性,這裡我們不對每種協議都展開詳細討論,在分散式存儲方面,用的最多的是兩階段提交協定及Paxos協定,以下重點介紹這兩種協議。

1、兩階段提交協議( Two-phase Commit,2PC):經常用來實現分散式事務,在兩階段協定中,系統一般包含兩類節點:一類為協調者( coordinator),通常一個系統中只有一個;另一類為事務參與者(participants,cohorts或workers),一般包含多個。

協定中假設每個節點都會記錄操作日誌並持久化到非易失性存儲介質,即使節點發生故障日誌也不會丟失。在提交階段,協調者將基於第一個階段的投票結果進行決策:提交或者取消。並通過引入事務的超時機制防止資源一直不能釋放的情況。

兩階段提交協定可能面臨兩種故障:

事務參與者發生故障。給每個事務設置一個超時時間,如果某個事務參與者一直不回應,到達超時時間後整個事務失敗。

協調者發生故障。協調者需要將事務相關資訊記錄到操作日誌並同步到備用協調者,假如協調者發生故障,備用協調者可以接替它完成後續的工作。如果沒有備用協調者,協調者又發生了永久性故障,事務參與者將無法完成事務而一直等待下去。

總而言之,兩階段提交協定是阻塞協定。

2、Paxos協議:用於解決多個節點之間的一致性問題。只要保證了多個節點之間操作日誌的一致性,就能夠在這些節點上構建高可用的全域服務,例如分散式鎖服務,全域命名和配置服務等。為了實現高可用性,主節點往往將資料以操作日誌的形式同步到備節點。如果主節點發生故障,備節點會提議自己成為主節點。網路磁碟分割的時候,可能會存在多個備節點提議(Proposer,提議者)自己成為主節點。Paxos協議保證,即使同時存在多個proposer,也能夠保證所有節點最終達成一致,即選舉出唯一的主節點。

(3)Paxos與2PC的區別:Paxos協定和2PC協定在分散式系統中所起的作用並不相同。Paxos協定用於保證同一個資料分片的多個副本之間的資料一致性。當這些副本分佈到不同的資料中心時,這個需求尤其強烈。2PC協定用於保證屬於多個資料分片上的操作的原子性。這些資料分片可能分佈在不同的伺服器上,2PC協議保證多台眼務器上的操作要麼全部成功,要麼全部失敗。

Paxos協議有兩種用法:一種用法是用它來實現全域的鎖服務或者命名和配置服務,例如Google Chubby以及Apache Zookeeper。另外一種用法是用它來將使用者資料複製到多個資料中心,例如Google Megastore以及Google Spanner。

2PC協議最大的缺陷在於無法處理協調者宕機問題。如果協調者宕機,那麼,2PC協議中的每個參與者可能都不知道事務應該提交還是回滾,整個協議被阻塞,執行過程中申請的資源都無法釋放。因此,常見的做法是將2PC和Paxos協議結合起來,通過2PC保證多個資料分片上的操作的原子性,通過Paxos協定實現同一個資料分片的多個副本之間的一致性。另外,通過Paxos協定解決2PC協定中協調者宕機問題。當2PC協定中的協調者出現故障時,通過Paxos協定選舉出新的協調者繼續提供服務。

跨機房部署

機房之間的資料同步方式可能為強同步或者非同步。如果採用非同步模式,那麼,備機房的資料總是落後於主機房;如果採用強同步模式,那麼,備機房的資料和主機房保持一致。當主機房出現故障時,除了手工切換,還可以採用自動切換的方式,即通過分散式鎖服務檢測主機房的服務,當主機房出現故障時,自動將備機房切換為主機房。

順序分佈與B+樹資料結構比較類似,每個子表相當於葉子節點,隨著資料的插入和刪除,某些子表可能變得很大,某些變得很小,資料分佈不均勻。如果採用順序分佈,系統設計時需要考慮子表的分裂與合併。子表合併的目的是為了防止系統中出現過多太小的子表,減少系統中的中繼資料。

3、負載均衡:工作節點通過心跳包(Heartbeat,定時發送)將節點負載相關的資訊,如CPU,記憶體,磁片,網路等資源使用率,讀寫次數及讀寫資料量等發送給主控節點。負載均衡操作需要控制節奏,負載均衡操作需要做到比較平滑,一般來說,從新機器加入,到集群負載達到比較均衡的狀態需要較長一段時間,比如30分鐘到一個小時。

複製

複製協議分為兩種:強同步複製和非同步複製,如圖1。

圖1 主備複製協議示範

強同步複製和非同步複製都是將主副本的資料以某種形式發送到其他副本,這種複製協議稱為基於主副本的複製協議( Primary-based protocol)。這種方法要求在任何時刻只能有一個副本為主副本,由它來確定寫操作之間的順序。如果主副本出現故障,需要選舉一個備副本成為新的主副本,這步操作稱為選舉,經典的選舉協定為Paxos協定。

主備副本之間的複製一般通過操作日誌來實現。操作日誌的原理很簡單:為了利用好磁片的順序讀寫特性,將用戶端的寫操作先順序寫入到磁片中,然後應用到記憶體中,由於記憶體是隨機讀寫設備,可以很容易通過各種資料結構,比如B+樹將資料有效地組織起來。當伺服器宕機重啟時,只需要重播操作日誌就可以恢復記憶體狀態。為了提高系統的併發能力,系統會積攢一定的操作日誌再批量寫入到磁片中,這種技術一般稱為成組提交。

如果每次伺服器出現故障都需要重播所有的操作日誌,效率是無法忍受的,檢查點( CheckPoint)正是為了解決這個問題。系統定期將記憶體狀態以檢查點檔的形式dump到磁片中,並記錄檢查點時刻對應的操作日誌重播點。檢查點檔成功創建後,重播點之前的日誌可以被垃圾回收,以後如果伺服器出現故障,只需要重播檢查點之後的操作日誌。(記憶體中只有“檢查點”之後的資料)

分散式存儲系統要求能夠自動容錯,也就是說,CAP理論中的“分區可容忍性”總是需要滿足的,因此,一致性和寫操作的可用性不能同時滿足。例如,Oracle教據庫的DataGuard複製元件包含三種模式:

最大保護模式( Maximum Protection):即強同步複製模式,寫操作要求主庫先將操作日誌(資料庫的redo/undo日誌)同步到至少一個備庫才可以返回用戶端成功。

最大性能模式( Maximum Performance):即非同步複製模式,寫操作只需要在主庫上執行成功就可以返回用戶端成功。

最大可用性模式( Maximum Availability):上述兩種模式的折衷。

容錯

常見故障中,單機故障和磁片故障發生概率最高。在分散式系統中,可以通過租約(Lease)機制進行故障檢測。

租約機制就是帶有超時時間的一種授權。假設機器A需要檢測機器B是否發生故障,機器A可以給機器B發放租約,機器B持有的租約在有效期內才允許提供服務,否則主動停止服務。需要注意的是,實現租約機制時需要考慮一個提前量。

故障恢復中,總控節點一般需要等待一段時間,比如1個小時,如果之前下線的節點重新上線,可以認為是臨時性故障,否則,認為是永久性故障。停服務時間包含兩個部分,故障檢測時間以及故障恢復時間。故障檢測時間一般在幾秒到十幾秒,和集群規模密切相關,集群規模越大,故障檢測對總控節點造成的壓力就越大,故障檢測時間就越長。

圖2 故障恢復

可擴展性

分散式存儲系統大多都帶有總控節點,基於這點,很多人會自然地認為總控節點存在瓶頸問題,認為去中心化的P2P架構更有優勢。然而,事實卻並非如此,主流的分散式存儲系統大多帶有總控節點,且能夠支援成千上萬台的集群規模。可擴展性應該綜合考慮節點故障後的恢復時間,擴容的自動化程度,擴容的靈活性等。

分散式存儲系統中往往有一個總控節點用於維護資料分佈資訊,執行工作機管理,資料定位,故障檢測和恢復,負載均衡等全域調度工作。通過引入總控節點,可以使得系統的設計更加簡單,並且更加容易做到強一致性,對用戶友好。那麼,總控節點是否會成為性能瓶頸呢?如果總控節點成為瓶頸,例如需要支援超過一萬台的集群規模,或者需要支援海量的小檔,那麼,可以採用兩級結構,如圖3所示。

圖3 兩級中繼資料結構

在資料庫的擴容中,如果系統的讀取能力不足,可以通過增加副本的方式解決,如果系統的寫入能力不足,可以根據業務的特點重新拆分數據,常見的做法為雙倍擴容,即將每個分片的資料拆分為兩個分片,擴容的過程中需要遷移一半的資料到新加入的存儲節點。傳統的資料庫架構在可擴展性上面臨如下問題:

1. 擴容不夠靈活。

2. 擴容不夠自動化。

3. 增加副本時間長。

同一個組內的節點服務相同的資料,這樣的系統稱為同構系統。同構系統的問題在於增加副本需要遷移的資料量太大,由於拷貝資料的過程中存儲節點再次發生故障的概率很高,所以這樣的架構很難做到自動化,不適用大規模分散式存儲系統。而異構系統將資料劃分為很多大小接近的分片,每個分片的多個副本可以分佈到集群中的任何一個存儲節點。由於整個集群都參與到節點的故障恢復過程,故障恢復時間很短,而且集群規模越大,優勢就會越明顯。

圖4 同構系統和異構系統的區別

分散式協定

在電腦世界裡,為了解決一件事情,另外的問題就會接踵而至,從另一個層面印證了IT架構永遠是一種平衡的藝術。

“BASE”其核心思想是根據業務特點,採用適當的方式來使系統達到最終一致性(Eventual consistency);在互聯網領域,通常需要犧牲強一致性來換取系統的高可用性,只需要保證資料的“最終一致”,只是這個最終時間需要在使用者可以接受的範圍內;但在金融相關的交易領域,仍然需要採用強一致性的方式來保障交易的準確性與可靠性。

業界常見的交易處理模式很多,包括兩階段提交、三階段提交、Sagas長事務、補償模式、可靠事件模式(本地事件表、外部事件表)、可靠事件模式(非事務消息、事務消息)、TCC、Paxos及其相關變種等等。不同的事務模型支援不同的資料一致性,這裡我們不對每種協議都展開詳細討論,在分散式存儲方面,用的最多的是兩階段提交協定及Paxos協定,以下重點介紹這兩種協議。

1、兩階段提交協議( Two-phase Commit,2PC):經常用來實現分散式事務,在兩階段協定中,系統一般包含兩類節點:一類為協調者( coordinator),通常一個系統中只有一個;另一類為事務參與者(participants,cohorts或workers),一般包含多個。

協定中假設每個節點都會記錄操作日誌並持久化到非易失性存儲介質,即使節點發生故障日誌也不會丟失。在提交階段,協調者將基於第一個階段的投票結果進行決策:提交或者取消。並通過引入事務的超時機制防止資源一直不能釋放的情況。

兩階段提交協定可能面臨兩種故障:

事務參與者發生故障。給每個事務設置一個超時時間,如果某個事務參與者一直不回應,到達超時時間後整個事務失敗。

協調者發生故障。協調者需要將事務相關資訊記錄到操作日誌並同步到備用協調者,假如協調者發生故障,備用協調者可以接替它完成後續的工作。如果沒有備用協調者,協調者又發生了永久性故障,事務參與者將無法完成事務而一直等待下去。

總而言之,兩階段提交協定是阻塞協定。

2、Paxos協議:用於解決多個節點之間的一致性問題。只要保證了多個節點之間操作日誌的一致性,就能夠在這些節點上構建高可用的全域服務,例如分散式鎖服務,全域命名和配置服務等。為了實現高可用性,主節點往往將資料以操作日誌的形式同步到備節點。如果主節點發生故障,備節點會提議自己成為主節點。網路磁碟分割的時候,可能會存在多個備節點提議(Proposer,提議者)自己成為主節點。Paxos協議保證,即使同時存在多個proposer,也能夠保證所有節點最終達成一致,即選舉出唯一的主節點。

(3)Paxos與2PC的區別:Paxos協定和2PC協定在分散式系統中所起的作用並不相同。Paxos協定用於保證同一個資料分片的多個副本之間的資料一致性。當這些副本分佈到不同的資料中心時,這個需求尤其強烈。2PC協定用於保證屬於多個資料分片上的操作的原子性。這些資料分片可能分佈在不同的伺服器上,2PC協議保證多台眼務器上的操作要麼全部成功,要麼全部失敗。

Paxos協議有兩種用法:一種用法是用它來實現全域的鎖服務或者命名和配置服務,例如Google Chubby以及Apache Zookeeper。另外一種用法是用它來將使用者資料複製到多個資料中心,例如Google Megastore以及Google Spanner。

2PC協議最大的缺陷在於無法處理協調者宕機問題。如果協調者宕機,那麼,2PC協議中的每個參與者可能都不知道事務應該提交還是回滾,整個協議被阻塞,執行過程中申請的資源都無法釋放。因此,常見的做法是將2PC和Paxos協議結合起來,通過2PC保證多個資料分片上的操作的原子性,通過Paxos協定實現同一個資料分片的多個副本之間的一致性。另外,通過Paxos協定解決2PC協定中協調者宕機問題。當2PC協定中的協調者出現故障時,通過Paxos協定選舉出新的協調者繼續提供服務。

跨機房部署

機房之間的資料同步方式可能為強同步或者非同步。如果採用非同步模式,那麼,備機房的資料總是落後於主機房;如果採用強同步模式,那麼,備機房的資料和主機房保持一致。當主機房出現故障時,除了手工切換,還可以採用自動切換的方式,即通過分散式鎖服務檢測主機房的服務,當主機房出現故障時,自動將備機房切換為主機房。

同類文章
Next Article
喜欢就按个赞吧!!!
点击关闭提示