Copyset模塊結合chunk的放置共同解決了集羣數據如何分佈的問題,這裏主要的設計考慮點是數據分佈的均衡性以充分利用磁盤空間和避免熱點。git
1. 背景
Curve是網易數帆在2020年7月份開源的一個高性能、高可用、高可靠的分佈式存儲系統,主打高性能、低延遲。github
Github代碼倉庫:https://github.com/opencurve/curve算法
Curve存儲系統的基礎設計框架與經典的GFS基本相似,採⽤有中心節點的架構,核心服務由4個部分組成:服務器
- 元數據節點MDS,主要有兩個職責,一方面管理和存儲元數據信息,另外一方面感知集羣狀態並進⾏調度。元數據存儲在etcd中。
- 數據節點ChunkServer, 一方面負責數據的存儲,另外一方面負責數據一致性(若是底層是多副本,須要負責副本間的數據一致性)。在咱們的實踐中,一個chunksever對應與一塊盤。
- 客⼾端Client, 向上層應用提供對文件的操做接口(open、read、write等), 會和MDS以及ChunkServer交互,與MDS交互實現對元數據的增刪改查;與ChunkServer交互實現對數據的增刪改查。
- 快照克隆服務器獨立於核心服務,對外提供了HTTP接口,用於處理和管理快照克隆任務。
在Curve系統中,存儲資源被分紅了一個個分片,稱之爲Chunk,典型的Chunk大小是16MB。爲了實現數據高可用、高可靠,chunk一般會被複制多個副本,較爲常見的是3個副本的配置,這樣的三個副本的組合,叫作複製組,也就是咱們稱之爲CopySet的概念。本文所描述的CopySet Replication指的就是一種複製組如何分佈到上述這些ChunkServer上的一種算法。session
CopySet Replication的概念由文獻「Copysets: Reducing the Frequency of Data Loss in Cloud Storage」而來,本意是爲了提升分佈式存儲系統中的數據持久性,下降數據丟失的機率。以下圖所示。架構
該文獻給出的copyset相關的幾個術語:併發
- R : 副本數
- N : 節點數
- S : scatter width 每一個節點的數據,複製到了多少個其餘的節點
- copyset: 複製組,R個副本所在節點的集合
- permutation:集羣N個節點的一個排列
還給出了一種copyset replication的算法:框架
首先,每次排列的每兩個copyset之間只有一個重複的節點,例如{4,5,6}和{3,6,9}之間重複的節點是6。這保證了每增長一個copyset增長該節點的scatter width的R-1。分佈式
其次,這種模式(scheme)確保了copyset均勻地覆蓋全部節點。由於每一次permutation爲scatter width增長R-1,那麼總的scatter width爲S = P * (R-1),其中P爲permutation的次數。總共的copyset數爲P(N/R)=(S/(R-1))(N/R)。性能
2. curve的copyset生成策略
2.1 設計目標:
copyset生成策略的設計目標是建立集羣的一個均衡的初始分佈,達到幾個目的:
- copyset需知足故障域約束的要求
- 每一個ChunkServer的copyset數量保持一致
- 每一個ChunkServer的scatter-width知足故障恢復的要求,而且儘量的均衡
Copyset模塊結合chunk的放置共同解決了集羣數據如何分佈的問題,這裏主要的設計考慮點是數據分佈的均衡性以充分利用磁盤空間和避免熱點。
2.2 核心概念:
2.2.1 copyset
- Copyset指的是複製組,底層ChunkServer使用的是Raft分佈式一致性算法,所以,copyset實際上也就天然對應了底層一個raft group。
- 每若干個ChunkServer組成一個copyset,每一個ChunkServer上會有多個copyset,也就是說copyset跟ChunkServer是多對多的關係。
- copyset沒有一個容量的概念,能夠類比桶的概念,chunk能夠落到的copyset對應的桶裏面。當集羣滿載的狀況下,最終copyset內最大會有多少數據,取決於總的空間除以copyset的數量。
2.2.2 physicalPool
- 物理池是咱們擴容的基本單元,也就是一次擴容一個physicalPool。
- 物理池內包含若干臺服務器,每臺服務器上具備若干個ChunkServer節點。
2.2.3 logicalPool
- 在物理池之上,咱們會建立logicalPool和copyset。
- copyset屬於邏輯池,每一個邏輯池一開始建立固定數量的copyset。
- copyset Id 在邏輯池內惟一,邏輯池Id + copyset Id 惟一肯定一個copyset。
2.2.4 Zone
zone指的是curve的故障域,它是一個邏輯概念,zone能夠對應到一個實際的物理機架,實現機架級別的物理隔離。
2.2.5 scatter-width
- scatter-width 指的是一個節點上的數據分佈到了多少個其餘節點上,它表示的是一個節點上的數據分佈的分散程度。
- scatter-width 越大,當節點發生故障時,可用於恢復的其餘節點數就越多,也就是說scatter-width決定了節點故障時,可用於恢復的併發度。
2.3 copyset生成策略實現
Curve的Copyset生成策略借鑑了「Copysets: Reducing the Frequency of Data Loss in Cloud Storage」中的Copyset算法,並擴展考慮了故障域的設計。其設計基於如下幾點考慮:
2.3.1 生成固定數量的copyset
固定數量的copyset是很重要的一個抉擇點,根本考慮點是相對於動態數量的copyset方法,更簡單,而且實踐證實也是夠用的。
- 首先建立遠超實際節點數的copyset數,均勻分配到每一個節點。
- 若是集羣中添加了一個新節點,該新節點能夠從每一個現有的節點上勻走幾個copyset,直到copyset再次達到全局平衡。
- 若是從集羣中刪除節點,則採起相反的均衡措施。
固定數量copyset帶來的問題:
- 第一個問題是,當邏輯池內節點數不斷增長時,每一個節點上的copyset數量就會不斷減小。因此只適用於邏輯池節點數相對變化不大的狀況。目前Curve擴容是主要是按照擴pool的方式進行,所以不會有這個問題。
- 第二個問題是,初始的copyset數量的肯定。這個咱們是根據scatter-width的要求來肯定的,有兩種方式,一種方式是根據scatter-width的要求,生成知足scatter-width的最小copyset數量,還有一種方式是指定copyset數量,驗證生成的copyset是否知足scatter-width的要求。其中scatter-width的計算能夠依據SLA的要求即故障恢復時間和預留恢復帶寬來計算。目前咱們的計算結果來看,scatter-width所要求的copyset數量是較少的,通常每一個ChunkServer 100個copyset就徹底能知足scatter-width的需求,能夠說對copyset的約束是比較寬的,咱們能夠較輕鬆的選擇copyset數量。
2.3.2 在故障域內,基於隨機化方法生成copyset
首先要均衡,那麼最簡單的方法就是隨機。可是咱們又須要知足故障域的要求,所以,咱們採用在故障域內隨機。自己故障域內的機器數量是基本均衡的,所以在故障域內隨機,整體上仍然能達到均衡。
咱們使用3個參數來表示copyset生成的故障域約束:
- 故障域數: ZoneNum
- 副本數: ReplicaNum
- 副本放置到多少個故障域: ZoneChoseNum
其中ZoneChosenNum <= ZoneNum是必定的。
通常來講ZoneChoseNum == ReplicaNum, 可是也存在例如在有3個故障域的集羣中將3副本放在2個故障域中,即ZoneNum=3, ReplicaNum=3,ZoneChoseNum=2的狀況,所以此處是3個參數。
目前Curve的代碼實現中,只支持ZoneChoseNum == ReplicaNum的狀況。
首先來考慮一種最簡單的狀況:對於一個有3個故障域的集羣,集羣的副本數未3副本,而且分佈方式是該3副本分佈到3個故障域中,那麼ZoneNum=3, ReplicaNum=3,ZoneChoseNum=3。
- 首先對集羣的節點按照故障域分爲3個組。
- 對3個組各自進行隨機排列。
- 按照各個組依次取一個節點的方式,組成3副本,生成一個copyset。
- 當取徹底部copyset後,重複從第2步再次執行排列。
- 當取到的copyset數量知足給定的copyset數量後,即完成了一次copyset的生成。
那麼將上述推廣到,ZoneNum = ANY,ReplicaNum == ZoneChoseNum <= ZoneNum 的狀況,第3步驟中將按照以下順序選取各個zone中的節點:
zone1 zone2 zone3 zone4 ... zoneN 1 2 3 4 ... N N+1 N+2 N+3 N+4 ... 2N ... ... ... ... ... ...
2.3.3 使用一系列度量來衡量算法的好壞,重試直到獲得一個合理的結果
當咱們經過隨機化的方法生成了copyset之後,如何確保copyset以及scatter width的均衡性?
這裏就經過一系列的度量指標去判斷。這些指標包括:
- scatter-width的方差與標準差
- scatter-witdth的極差
- scatter-witdth偏離均值百分比
當每次生成copyset時,計算上述一貫或多項指標(根據配置),判斷生成的copyset是否知足上述指標,若是不知足,則重試生成copyset,直到知足上述指標爲止。
這一步驟的流程圖以下:
3. scatter width的計算
最後,相當重要的就是scatter-width的計算,scatter width越大,恢復帶寬越大,scatter width 表示的是最大同時有多少個copyset可參與恢復。所以:
總恢復帶寬 = scatter width * 單個copyset的恢復帶寬, scatter width = 總的恢復帶寬 / 單個copyset的恢復帶寬 = (數據容量 / 指望恢復時間)/ 單個copyset的恢復帶寬
假設節點每一個盤4T,恢復時間3600s,單個copyset的恢復帶寬爲10MB/s,那麼S = (4 * 1024 * 1024) / 3600 / 10 = 116.51,這是scatter width的下限。
下表列出了以單個盤(ChunkServer)大小爲4T狀況下,單copyset恢復帶寬從5MB/s至100MB/s, 恢復時間從1800s至7200s所需scatter width下限:
恢復時間\ 恢復帶寬 | 5MB/s | 10MB/s | 20MB/s | 50MB/s |
---|---|---|---|---|
1800s | 466.03 | 233.02 | 116.51 | 46.60 |
3600s | 233.02 | 116.51 | 46.60 | 23.30 |
5400s | 155.34 | 77.67 | 38.84 | 15.53 |
7200s | 116.51 | 46.60 | 23.30 | 11.65 |
做者簡介:許超傑,網易數帆資深系統開發工程師,自研分佈式存儲系統Curve的核心開發。