我們知道的HDFS、Gluster、Ceph、Swift等互聯網常用的大規模集群文件系統無一例外都屬于分布式集群文件系統。分布式集群文件系統可擴展性更強,目前已知最大可擴展至10K節點。對于分布式集群,其對文件元數據的管理方式又可以分為single path image和single filesystem image兩種方式。
異常分類
分布式存儲系統所關注的異常類型和單體系統不一樣,有如下幾種:
服務器宕機:設計存儲系統時需要考慮如何通過讀取持久化介質(如機械硬盤,固態硬盤)中的數據來恢復內存信息。
網絡異常:設計容錯系統的一個基本原則是:網絡永遠是不可靠的,任何一個消息只有收到對方的回復后才可以認為發送成功,系統設計時總是假設網絡將會出現異常并采取相應的處理措施。
磁盤故障:對于磁盤數據錯誤,往往可以采用校驗和( checksum)機制來解決。
除了異常之外,還存在“超時”狀態,RPC執行的結果有三種狀態:“成功”、“失敗”、“超時”(未知狀態),也稱為分布式存儲系統的三態。
一致性保證
副本是分布式存儲系統容錯技術的唯一手段。由于多個副本的存在,如何保證副本之間的一致性是整個分布式系統的理論核心。從客戶端的角度來看,一致性包含如下三種情況:
1、強一致性:
2、弱一致性:
3、最終一致性:最終一致性是弱一致性的一種特例。“最終”一致性有一個“不一致窗口”(時間延遲),最終一致性描述比較粗略,其常見的變體如下:
會話( 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協議選舉出新的協調者繼續提供服務。
跨機房部署
機房之間的數據同步方式可能為強同步或者異步。如果采用異步模式,那么,備機房的數據總是落后于主機房;如果采用強同步模式,那么,備機房的數據和主機房保持一致。當主機房出現故障時,除了手工切換,還可以采用自動切換的方式,即通過分布式鎖服務檢測主機房的服務,當主機房出現故障時,自動將備機房切換為主機房。
評論
查看更多