ceph簡介
Ceph 是一個統一的分散式儲存系統,設計初衷是提供較好的效能、可靠性和可擴充套件性。底層的rados分散式儲存是ceph的精華所在,ceph以rados為基礎在上層封裝了物件、塊、檔案儲存介面。客戶端可以透過ceph提供的librados庫直連rados叢集,待存物件透過計算獲取指定機器,然後將資料傳送到該機器上儲存。因為都是透過計算的方式,所以rados不需要維護一箇中心table來儲存物件所在的位置,這種計算型的方式不僅快速,而且能夠節省節點的資源。 下圖為ceph的總體框架圖:
資料如何對映
Ceph對叢集中所有儲存資源進行池化管理,物件透過計算直接對映到底層的osd中,為了更好的管理和對映資料,ceph有如下的概念。 - object: 使用者需要儲存的物件,可以是文件、影片、音訊等等檔案,使用者在儲存的時候需要指定唯一的物件名。 - pool:資源池,這是一個虛擬概念,一個叢集可以分出多個pool,也可以使用單個pool,但是必須有一個pool。 使用者可以針對不同的pool指定不同的CRUSH規則,也可以針對不同的pool指定不同的資料冗餘策略。 - pg:全稱 placement groups, 一個pool對應多個pg, 透過hash物件會儲存到pool中的特定pg中。在建立pool的時候就要把pg數量規劃好。pg數量只可以增大不可以縮小。 - osd:最終的資料都是儲存在特定的osd上,一般情況下一個osd會管理一塊磁碟。
物件的對映邏輯架構如下:
pg雜湊演算法
pg雜湊演算法程式碼:
/*
x: 物件key值
b: pg 數
bmask: 掩碼
*/
static inline int ceph_stable_mod(int x, int b, int bmask)
{
if ((x & bmask) < b)
return x & bmask;
else
return x & (bmask >> 1);
}
object透過hash對應到不同的pg中,ceph使用掩碼的方式來代替取模操作。例如PG數目對應的最高位元位為n,則其掩碼為2^n -1, 將某個物件對映到PG時,直接使用 object & (2^n -1)即可。這種直接與的方式其實就是取object二進位制的後 n 位作為pg number,這種方式不僅高效,而且運算速度快。 可能有人會問這個n是怎麼來的,其實n就是PG數二進位制表示中1最高位的1。ceph中如果設定PG數目為a,那麼程式會得到一個最小的n,使 a <= 2^n,例如:(a=12, n=4), (a=16, n=4), (a=17, n=5),以此類推。 但是這種方案存在一個潛在的問題,如果運維人員設定的PG數是2的冪次方的話,那麼這種方案比較完美。如果PG數目不是2的冪次方的話這種對映會產生空穴,即將某些物件對映到一些實際上不存在的PG上。如下圖所示:
上圖中如果如果PG數目為14,但是n=4,直接hash的話會產生 0~15 共計16中不同的結果,但是12 ~ 15這4個PG是不存在的,為了解決這個問題ceph做了降級方案。因為 n 為PG數的最高位,因此可以得到如下的方程式。
2^(n-1) < PG數 <= 2^n
由此可得 [0,2^(n-1)]內PG一定是存在的,可以透過 object & 2^(n-1) 來將那些實際上不存在的PG重新對映到這個小的區間內,如下圖所示:
如上圖所示,ceph會將對映出不存在的PG重新對映到前面存在的區間中。所以如果ceph叢集設定的PG數目不是2的冪次方的話,可能會造成中間某一段的PG所承載的資料高於其它PG,例如:PG數為12時會造成4,5,6,7四個PG所承載的物件數是其它PG的兩倍,所以叢集在穩定時PG數最好的2的冪次方。
PG擴容
在現實使用中如果需要進行擴容,在pg雙倍擴容的情況下可以一步步的擴容以減少一步到位的擴容帶來的資料遷移影響。 例如: 將 pg 數從 8 擴容到 16 ,如果直接擴容到16會遷移 1/2 的資料,這種情況下叢集內部資料遷移可能會影響使用者的使用,管理員可以採取 8 -> 12 -> 16這樣的擴容方式。 根據上述圖的描述,從8 -> 12 會遷移叢集內部 1/4 的資料,也就是將pg數為 0~3 的資料遷移到 8~11 中,而 4~7 的資料是不會遷移的(因為重新hash它還是落到 4~7 這個區間),資料遷移完成後可以再將 pg 數從 12 ~16,這種情況下還是會遷移 1/4 的資料(將pg為 4~7 的資料遷移到 12~15 中),這樣分兩步遷移資料總的資料遷移量是一樣的,都是 1/2,但是分步遷移的話可以緩解一段時間內的資料遷移量。
如果不是進行雙倍擴容的話情況可能就比較複雜了,也可以採取這種透過增長遷移時間來換取短時間內少遷移資料的方案。
直接取模的弊端
可能有人會問為什麼不使用簡單的取模呢,因為這種方式在擴容的時候遷移的資料量無法控制。
設: pg 數為 a,需要將 pg 數擴容至 b, a 和 b 的最小公倍數為 d,某個物件的key值為 q
由此可以得到如下兩個方程式:
ca + e = q, e < a, q < d;
ub + v = q, v < b, q < d;
因為最小公倍數為 d, 如果 c != 0 && u != 0, 所以 ca != ub, 所以 e != v
當 c == u == 0的情況下, e == v,
所以需要遷移資料比例為: (d-a)/d
由此可以得到直接取模的方式無法控制遷移的資料量,例如 pg 數從 8 -> 12,直接取模的話需要遷移 (24 - 8) / 24 = 2/3 的資料。
作者:馮傑