Blobstore是位于SPDK bdev之上的Blob管理層,用于與用戶態(tài)文件系統(tǒng)Blobstore Filesystem (BlobFS)集成,從而代替?zhèn)鹘y(tǒng)的文件系統(tǒng),支持更上層的服務(wù),如數(shù)據(jù)庫MySQL、K-V存儲引擎Rocksdb以及分布式存儲系統(tǒng)Ceph、Cassandra等。以Rocksdb為例,通過BlobFS作為Rocksdb的存儲后端的優(yōu)勢在于,I/O經(jīng)由BlobFS與Blobstore下發(fā)到bdev,隨后由SPDK用戶態(tài)driver寫入磁盤。整個I/O流從發(fā)起到落盤均在用戶態(tài)操作,完全bypass內(nèi)核。此外,可以充分利用SPDK所提供的異步、無鎖化、Zero Copy、輪詢等機制,大幅度減少額外的系統(tǒng)開銷。它們之間的關(guān)系如下所示(以NVMe bdev為例):
BlobFS在管理文件時,主要依賴于Blobstore對blob的分配與管理。Blob類似于文件的概念,而又不完全等同于文件,其并不支持所有文件的POSIX接口。BlobFS與Blobstore的關(guān)系可以理解為Blobstore實現(xiàn)了對Blob的管理,包括Blob的分配、刪除、讀取、寫入、元數(shù)據(jù)的管理等,而BlobFS是在Blobstore的基礎(chǔ)上進行封裝的一個輕量級文件系統(tǒng),用于提供部分對于文件操作的接口,并將對文件的操作轉(zhuǎn)換為對Blob的操作,BlobFS中的文件與Blobstore中的Blob一一對應(yīng)。在Blobstore下層,與SPDK bdev層對接。SPDK bdev層類似于內(nèi)核中的通用塊設(shè)備層,是對底層不同類型設(shè)備的統(tǒng)一抽象管理,例如NVMe bdev、Malloc bdev、AIO bdev等。
Blobstore中結(jié)構(gòu)的劃分
在blobstore中,將SSD中的塊劃分為多個抽象層,主要由Logical Block、Page、Cluster、Blob組成,它們之間的關(guān)系如下所示:
Logical Block:與塊設(shè)備中所提供的邏輯塊相對應(yīng),通常為512B或4KiB。
Page:由多個連續(xù)的Logical Block構(gòu)成,通常一個page的大小為4KiB,因此一個Page由八個或一個Logical Block構(gòu)成,取決于Logical Block的大小。在Blobstore中,Page是連續(xù)的,即從SSD的LBA 0開始,多個或一個塊構(gòu)成Page 0,接下來是Page 1,依次類推。
Cluster:由多個連續(xù)的Page構(gòu)成,通常一個Cluster的大小默認為1MiB,因此一個Cluster由256個Page構(gòu)成。Cluster與Page一樣,是連續(xù)的,即從SSD的LBA 0開始的位置依次為Cluster 0到Cluster N。
Blob:Blobstore中主要的操作對象為Blob,與BlobFS中的文件相對應(yīng),提供read、write、create、delete等操作。一個Blob由多個Cluster構(gòu)成,但構(gòu)成Blob中的Cluster并不一定是連續(xù)的。
那么Blobstore是如何管理塊的分配呢?
在Blobstore中,會將cluster 0作為一個特殊的cluster。該cluster用于存放Blobtore的所有信息以及元數(shù)據(jù),對每個blob數(shù)據(jù)塊的查找、分配都是依賴cluster 0中所記錄的元數(shù)據(jù)所進行的。Cluster 0的結(jié)構(gòu)如下:
Cluster 0中的第一個page作為super block,Blobstore初始化后的一些基本信息都存放在super block中,例如cluster的大小、已使用page的起始位置、已使用page的個數(shù)、已使用cluster的起始位置、已使用cluster的個數(shù)、Blobstore的大小等信息。
Cluster 0中的其它page將組成元數(shù)據(jù)域(metadata region)。元數(shù)據(jù)域主要由以下幾部分組成:
Metadata Page Allocation:用于記錄所有元數(shù)據(jù)頁的分配情況。在分配或釋放元數(shù)據(jù)頁后,將會對metadata page allocation中的數(shù)據(jù)做相應(yīng)的修改。
Cluster Allocation:用于記錄所有cluster的分配情況。在分配新的cluster或釋放cluster后會對cluster allocation中的數(shù)據(jù)做相應(yīng)的修改。
Blob Id Allocation:用于記錄blob id的分配情況。對于blobstore中的所有blob,都是通過唯一的標識符blob id將其對應(yīng)起來。在元數(shù)據(jù)域中,將會在blob allocation中記錄所有的blob id分配情況。
Metadata Pages Region:元數(shù)據(jù)頁區(qū)域中存放著每個blob的元數(shù)據(jù)頁。每個blob中所分配的cluster都會記錄在該blob的元數(shù)據(jù)頁中,在讀寫blob時,首先會通過blob id定位到該blob的元數(shù)據(jù)頁,其次根據(jù)元數(shù)據(jù)頁中所記錄的信息,檢索到對應(yīng)的cluster。對于每個blob的元數(shù)據(jù)頁,并不是連續(xù)的。
對于一個blob來說,metadata page記錄了該blob的所有信息,數(shù)據(jù)存放于分配給該blob的cluster中。在創(chuàng)建blob時,首先會為其分配blob id以及metadata page,其次更新metadata region。當對blob進行寫入時,首先會為其分配cluster,其次更新該blob的metadata page,最后將數(shù)據(jù)寫入,并持久化到磁盤中。
為了實現(xiàn)對磁盤空間的動態(tài)分配管理,Blobstore中為每個blob分配的cluster并不是連續(xù)的。對于每個blob,通過相應(yīng)的結(jié)構(gòu)維護當前使用的cluster以及metadata page的信息:clusters與pages。Cluster中記錄了當前該blob所有cluster的LBA起始地址,pages中記錄了當前該blob所有metadata page的LBA起始地址。
Blobstore實現(xiàn)了對磁盤空間分配的動態(tài)管理,并保證斷電不丟失數(shù)據(jù),因此Blob具有persistent特性。Blobstore中的配置信息與數(shù)據(jù)信息均在super block與metadata region中管理,在重啟后,若要保持persistent,可以通過Blobstore中所提供的load操作。
注意:
Blob的persistent主要是針對NVMe這類bdev。對于Malloc bdev,由于其本身的性質(zhì),是無法保證Blob的persistent,需要重啟后進行重新配置。
下面通過文件的讀寫來講解BlobFS與Blobstore中的I/O流程:
文件讀取:文件讀取操作的流程圖如下所示:
為了提高文件的讀取效率,BlobFS在內(nèi)存中提供了cache buffer。在文件讀寫時,首先會進行read ahead操作,將一部分數(shù)據(jù)從磁盤預(yù)先讀取到內(nèi)存的buffer中。其后,根據(jù)cache buffer的大小,對文件的I/O進行切分,使每個I/O的最大長度不超過一個cache buffer的大小。對于拆分后的文件I/O,會根據(jù)其offset在cache buffer tree中查找相應(yīng)的buffer。若存在,則直接從cache buffer中讀取數(shù)據(jù),進行memcpy。而對于沒有緩存到cache buffer中的數(shù)據(jù),將會對該文件的讀取,轉(zhuǎn)換到該文件對應(yīng)的Blob進行讀取。對Blob讀取時候,根據(jù)已打開的blob結(jié)構(gòu)中記錄的信息,可以獲取該blob所有cluster的LBA起始位置,并根據(jù)讀取位置的offset信息,計算相應(yīng)的LBA地址。最后向SPDK bdev層發(fā)送異步的讀請求,并等待I/O完成。BlobFS所提供的讀操作為同步讀,I/O完成后會在callback函數(shù)中,通過信號量通知BlobFS完成信號,至此文件讀取結(jié)束。
對于cache buffer tree,其結(jié)構(gòu)如下所示:
Cache buffer tree是由多層樹結(jié)構(gòu)組成。最底層Level 0葉子節(jié)點為buffer node,是用于存放數(shù)據(jù)的buffer。Level 0以上的其它層中,均為tree node,用于構(gòu)建樹的索引結(jié)構(gòu)。在文件讀寫的時候,根據(jù)文件結(jié)構(gòu)中的根節(jié)點以及讀取位置的offset信息,在樹結(jié)構(gòu)中通過索引查找buffer node的位置,即從Level N,逐步定位到對應(yīng)的Level 0的葉子節(jié)點。
文件寫入:文件寫入操作的流程圖如下所示:
BlobFS目前用于支持上層的Rocksdb,在Rocksdb的抽象環(huán)境層中提供文件的接口,目前僅支持append類型的寫操作。在進行文件寫入時,首先會根據(jù)文件當前的寫入位置檢查是否符合cache buffer寫入需求,若滿足,則直接將數(shù)據(jù)寫入到cache buffer中,同時觸發(fā)異步的flush操作。在flush的過程中,BlobFS觸發(fā)Blob的寫操作,將cache buffer中的數(shù)據(jù),寫入到文件對應(yīng)blob的相應(yīng)位置。若不滿足cache buffer的寫入需求,BlobFS則直接觸發(fā)文件對應(yīng)的blob的寫操作。Blobstore首先為該blob分配cluster,根據(jù)計算得到的寫入LBA信息,向SPDK bdev層發(fā)送異步的寫請求,將數(shù)據(jù)寫入,并更新相應(yīng)的元數(shù)據(jù)。對于元數(shù)據(jù)的更新,出于性能考慮,當前對元數(shù)據(jù)的更新都在內(nèi)存中操作,當用戶使用強制同步或卸載Blobstore時,更新后的元數(shù)據(jù)信息才會同步到磁盤中。此外,blob結(jié)構(gòu)中維護了兩份可變信息(指cluster與metadata page)的元數(shù)據(jù),分別為clean與active。Clean中記錄的是當前磁盤的元數(shù)據(jù)信息,而active中記錄的是當前在內(nèi)存中更新后的元數(shù)據(jù)信息。同步操作會將clean中記錄的信息與active記錄的信息相匹配。
總結(jié)
Blobstore實現(xiàn)對Blob管理,Blob類似與文件的概念,但又不完全等同于文件,Blob沒有完全遵循文件的POSIX接口,因此避免與文件混淆,在SPDK中稱之為Blob而不是File。Blobstore Filesystem (BlobFS)是基于Blobstore實現(xiàn)的輕量級文件系統(tǒng),對Blobstore進行封裝,提供一些文件的常用接口,如read、write、open、sync等,其目的在于作為文件系統(tǒng)支持更上層的應(yīng)用,例如Rocksdb。但其本質(zhì)仍然是Blobstore,因此命名為BlobFS。目前SPDK基于維護了Rocksdb的一個分支,該分支下的Rocksdb在環(huán)境抽象層主要通過BlobFS進行對接,I/O可以經(jīng)由BlobFS繞過內(nèi)核I/O棧。關(guān)于Rocksdb的搭建與測試步驟,可以參考[3]。
-
磁盤
+關(guān)注
關(guān)注
1文章
379瀏覽量
25234 -
數(shù)據(jù)庫
+關(guān)注
關(guān)注
7文章
3839瀏覽量
64543 -
MySQL
+關(guān)注
關(guān)注
1文章
819瀏覽量
26651
原文標題:再見,Linux內(nèi)核!文件系統(tǒng)直接訪問SSD
文章出處:【微信號:SSDFans,微信公眾號:SSDFans】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論