Ceph BlueStore 解析:Object IO到磁盤的映射


作者:吳香偉 發表於 2017/02/19
版權聲明:可以任意轉載,轉載時務必以超鏈接形式標明文章原始出處和作者信息以及版權聲明


簡單回顧下Ceph OSD后端存儲引擎的歷史。

為解決事務原子性問題,最早的FileStore存儲引擎引入了Journal機制,一個IO先同步寫日志,再異步寫文件,這在解決原子性問題的同時也引入了寫放大的問題,一次IO兩次落盤。NewStore通過Onode索引解耦Object和文件,讓IO直接寫文件,寫成功后更新Onode元數據,從而避免兩次落盤問題(特殊情況下還是需要先寫日志)。NewStore雖然解決了寫放大問題,但不夠徹底,無法消除本地文件系統帶來的消耗。於是,BlockStore登場,在NewStore基礎上拋開本地文件系統直接管理裸塊設備。直接管理磁盤首先要做兩件事情:

(1) 磁盤空間分配;
(2) 將Object數據映射到磁盤;

本文重點分析BlueStore對這兩個問題的解決。

概念

Onode 代表一個Object,類似於VFS中的Inode索引節點;
lextent Object的邏輯范圍;
blob 為Onode分配的一組磁盤空間,可以被多個lextent共享;
pextent 一段連續的物理磁盤空間,默認最小單位為4K字節。一個blob的磁盤空間由多段不連續的物理磁盤空間組成。

磁盤空間分配

概念。
Block 大小為4K字節的一段磁盤空間;
BmapEntry 為一整型,整型的每個bit位代表一個Block;
Zone 一組空間上連續的Block的集合,Block數目默認為1024;
Span 一組空間上連續的Zone的集合,Zone數目默認為1024;

磁盤分配器Allocator將裸塊設備划分成固定大小的Block,分配、釋放磁盤空間時以Block作為最小單元。目前BlueStore提供了兩種磁盤分配策略,一種稱為Stupid,另一種稱為Bitmap,Bitmap為默認配置,本節重點分析Bitmap磁盤管理。Bitmap(位圖)管理磁盤空間的基本思路是,使用一個bit位的兩種狀態0或者1來表示一個Block空閑或已分配兩種狀態。Bitmap是本地FS管理磁盤的一種常用方式,對於一個已經格式化過的塊設備,文件系統會在Superblock中持久化元數據,記錄哪些Block已被使用哪些Block空閑。BlueStore同樣需要記錄這些信息,不過將它記錄在KV數據庫,OSD進程啟動時從KV中加載Block塊狀態,構建出如上圖所示的樹形結構。

樹形結構的每個節點會統計以此為根的子樹中包含的空閑磁盤空間和已分配磁盤空間的字節數,這在分配連續大塊的磁盤空間時可以跳過空間不足的子樹,快速定位到剩余空間能夠滿足要求的子樹,從而提高分配效率。不過,樹形結構也會帶來一些問題。兩棵相鄰子樹會將原本連續的磁盤空間分隔開,可能存在這樣的情況,左邊子樹中最右邊的Block是空閑的,右邊子樹的最左邊Block是空閑的,那么將兩棵子樹合並在一起也能夠分配出一段連續空間。對於這個問題,BlueStore只考慮Zone內不同BmapEntry間的情況,對粒度更大的子樹就不做考慮了。

Object數據對齊

向bluestore_min_alloc_size對齊。
bluestore_min_alloc_size是Onode申請磁盤空間的最小單元,固態硬盤默認為64K字節,HDD默認4K字節。Onode每次申請磁盤空間的大小都是bluestore_min_alloc_size的整數倍,申請到的磁盤空間由blob結構來管理。

如何確定是否要為一個寫IO分配磁盤空間,分配多少磁盤空間?

Onode對磁盤空間的分配是“精簡配置”模式,對一個只在1024K到1088K位置有數據的Object,只要為其分配64K字節而不是1088K字節的磁盤空間。上圖給出了寫IO修改范圍和Object舊數據間的重疊關系,假設IO修改范圍和舊范圍都足夠大,那么每個舊范圍可能都有自己獨立的磁盤空間。通過把IO修改范圍對齊到bluestore_min_alloc_size,將IO修改范圍分割成3部分:頭部、中間部分和尾部。對中間部分,直接丟棄重疊的舊范圍所分配的磁盤空間,為中間部分重新分配物理上連續的磁盤空間;對頭部和尾部,考慮將IO修改范圍應用到已分配的磁盤空間。

為什么單獨為中間部分重新分配磁盤空間,而不為頭、尾部分也重新分配磁盤空間?
跟中間部分重疊的若干舊范圍,這些舊范圍分配的磁盤空間在物理上可能並不連續,在不連續的物理磁盤中讀取邏輯上連續的數據, 性能必然會低。第二個原因是這些舊范圍中的舊數據,即將被新數據覆蓋,已經成為無效數據,棄之並不可惜。頭部和尾部可能需要新分配磁盤空間,也可能直接使用已分配的磁盤空間。在使用已有磁盤空間的情況下,已有磁盤空間中包含舊數據,這些舊數據可能與新數據有重疊部分(如上圖的尾部),可能和新數據沒有重疊部分(如上圖的頭部)。已有磁盤空間中沒有和新數據重疊的數據仍然是有效數據,如果重新分配磁盤空間則需要將這部分有效數據遷移到新磁盤空間,得不償失。

向bdev_block_size對齊。
bdev_block_size是磁盤能分配的最小單元,默認4K字節。傳統機械硬盤的最小讀寫單元是扇區,扇區大小為512字節,如果寫入的數據小於512字節,則需要先讀取扇區內容合並后再寫入。SSD最小讀寫單元是頁,頁大小為4K字節。讀取,合並,再寫入,將嚴重降低寫性能,不可不考慮。解決方法很直接,對沒對齊的修改數據,補零,將其對齊到bdev_block_size大小。

中間部分已經按照bdev_block_size對齊,原因是,中間部分按照bluestore_min_alloc_size對齊,而bluestore_min_alloc_size已經按照bdev_block_size對齊,故而中間部分默認已經bdev_block_size對齊。對首、尾部分又可以再分為兩種情況:一種情況是對齊后,補零部分和Object的舊數據沒有重疊,如上圖(b)和(c)所示;另一種情況是對齊后,補零部分和Object的舊數據重疊,如上圖(a)所示,這種情況不能直接補零,否則將覆蓋舊數據。針對覆蓋舊數據的問題,先從磁盤讀取數據本應該補零的數據,用這部分數據填充新數據以達到對齊的目的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM