由于FileStore底層仍然通過(guò)操作系統(tǒng)自帶的本地文件系統(tǒng)管理磁盤,所以為了能夠使用本地文件系統(tǒng),所有針對(duì)RADOS的操作都需要轉(zhuǎn)換成POSIX語(yǔ)義。
所以引入了BlueStore直接管理文件。
1.設(shè)計(jì)原理
文件系統(tǒng)提供的核心操作就是讀和寫,BlueStore也是。
對(duì)于文件系統(tǒng),讀操作除非緩存命中,否則都是從磁盤讀出數(shù)據(jù);而對(duì)于寫操作,一般都是寫入內(nèi)存即可應(yīng)答,再由文件系統(tǒng)合適組織寫入磁盤,以此達(dá)到加速寫性能。
但由于內(nèi)存掉電數(shù)據(jù)會(huì)丟失,為了保證可靠性,BlueStore采用日志、雙寫來(lái)加速寫操作,也就是先寫入緩存NVRAM或者SSD,再寫入磁盤。
BlueStore引入日志后,接踵而來(lái)的問(wèn)題是,NVRAM或者SSD可以充當(dāng)緩存的原因是I/O時(shí)延非常低,但是對(duì)于海量數(shù)據(jù)的寫入,時(shí)延已經(jīng)不是瓶頸,數(shù)據(jù)傳輸?shù)臅r(shí)間才是瓶頸,所以當(dāng)有海量數(shù)據(jù)寫操作時(shí),寫日志雖然寫進(jìn)緩存很快,但是仍有大部分時(shí)間消耗給數(shù)據(jù)傳輸,再由于雙寫,性能損失反而更加嚴(yán)重。
所以BlueStore的寫操作采用首尾塊非對(duì)齊部分采用寫日志RMW策略,中間對(duì)齊的大部分?jǐn)?shù)據(jù)采用重定向?qū)慍OW策略
BlueStore提供的讀寫API的粒度是PG,讀是并發(fā)的,寫是排他的。也就是同一時(shí)間兩個(gè)線程可以同步執(zhí)行讀同一個(gè)PG的數(shù)據(jù),但是只能互斥寫同一個(gè)PG。
讀請(qǐng)求是同步的,但出于效率考慮,寫請(qǐng)求是異步的,所以對(duì)每一個(gè)PG還有一個(gè)FIFO隊(duì)列OpSequencer來(lái)給寫請(qǐng)求保序。
同步異步的意思是線程沒(méi)有讀完會(huì)阻塞,沒(méi)有寫完不會(huì)阻塞。
2.BlueStore的磁盤數(shù)據(jù)結(jié)構(gòu)
BlueStore的對(duì)象類似于文件,我們知道文件是依靠每個(gè)文件專屬的元數(shù)據(jù)inode記錄了本文件的大小、文件數(shù)據(jù)所在的扇區(qū)地址等信息。BlueStore的元數(shù)據(jù)結(jié)構(gòu)叫onode,也是記錄了對(duì)象大小和數(shù)據(jù)位置等信息,具體如下:
其中size是對(duì)象大小、而extent_map_shards則記錄了extent-map在RocksDB數(shù)據(jù)庫(kù)的索引,也就是說(shuō)每個(gè)對(duì)象有一個(gè)onode,onode包含了一張extent-map,而extent-map很大所以存儲(chǔ)在數(shù)據(jù)庫(kù)中。
extent-map記錄了對(duì)象數(shù)據(jù)在磁盤的地址。extent-map具體如下:
其中extent_map包含了對(duì)象的若干個(gè)邏輯數(shù)據(jù)段extent(每個(gè)邏輯段并不一定連續(xù)且與磁盤塊對(duì)齊)。
extent具體如下:
其中blob記錄了該邏輯段對(duì)應(yīng)的磁盤物理段。
blob_offset用于邏輯段extent的強(qiáng)制對(duì)齊,從而方便了映射磁盤物理段:
blob結(jié)構(gòu)具體如下:
由于每個(gè)邏輯段extent在物理磁盤上并不一定連續(xù),屬于邏輯段和物理段是一對(duì)多的關(guān)系,所以表中extents記錄了多個(gè)物理段pextent。
pextent結(jié)構(gòu)具體如下:
上述的offset、length一定是塊的整數(shù)倍。
整體結(jié)構(gòu)圖如下:
3.緩存機(jī)制
緩存替換算法本質(zhì)是對(duì)于未來(lái)的讀寫請(qǐng)求序列,依靠時(shí)空局部性原理進(jìn)行預(yù)測(cè),因此如果請(qǐng)求序列完全隨機(jī),那么任何算法不可避免存在誤淘汰的可能。
BlueStore需要緩存的元數(shù)據(jù)有兩種,Collection和Onode,分別對(duì)應(yīng)PG上下文與對(duì)象上下文內(nèi)存管理結(jié)構(gòu)。Collection小巧故常駐內(nèi)存。
所以BlueStore需要緩存的數(shù)據(jù)只有Onode和用戶數(shù)據(jù)。
BlueStore針對(duì)Onode采用LRU緩存替換算法、針對(duì)用戶數(shù)據(jù)采用2Q。共四個(gè)隊(duì)列。2Q有三個(gè)(A1in、Am、A1out)
4.BlueStore的磁盤空間管理
對(duì)于文件系統(tǒng)而言,除了元數(shù)據(jù)inode,還需要磁盤空間管理系統(tǒng)【位圖】來(lái)管理磁盤的空閑塊,比如每次追加寫文件,文件需要擴(kuò)容,那么就需要向位圖申請(qǐng)磁盤塊,再將磁盤塊塊號(hào)記錄于該文件元數(shù)據(jù)inode中,再完成寫入操作。
對(duì)于現(xiàn)代海量存儲(chǔ)場(chǎng)景,一個(gè)bit表示一個(gè)扇區(qū)的做法,會(huì)導(dǎo)致位圖過(guò)大,1.3PB的磁盤空間需要300GB內(nèi)存,這使得位圖無(wú)法常駐內(nèi)存,不適用于集中式存儲(chǔ)系統(tǒng),因此有了段管理。一個(gè)段兩個(gè)成員offset、length,128位就可以表示一大段磁盤空間。
由于Ceph是分布式的,并且Ceph的定位面向SSD,比HDD有更大的基本塊,所以,BlueStore默認(rèn)采用位圖管理磁盤
對(duì)于文件系統(tǒng),已分配磁盤塊和空閑塊是對(duì)立的,已知一種便可以恢復(fù)另一種。
由于已分配磁盤塊在onode中已經(jīng)詳細(xì)記錄,所以BlueStore將空閑塊列表用數(shù)據(jù)庫(kù)存盤,BlueStore上電后通過(guò)加載空閑塊列表,最終還原出已分配空間列表。(雖然onode也在數(shù)據(jù)庫(kù),但是onode不僅僅記錄了已分配塊信息,非常龐大)。
上述空閑塊列表即FreelistManager,還原出的已分配空間列表即Allocator(常駐內(nèi)存用于分配空閑塊,響應(yīng)磁盤塊請(qǐng)求)。
4.1 BitmapFreelistManager
BitmapFreelistManager將數(shù)量固定,物理上連續(xù)的磁盤塊組成一個(gè)段,從而將磁盤空間劃分為若干連續(xù)的段管理。每個(gè)段以磁盤起始地址為編號(hào),故在BlueStore實(shí)例內(nèi)為唯一索引,單個(gè)塊用一個(gè)比特表示狀態(tài),所以每個(gè)段是一段比特流。
由于使用數(shù)據(jù)庫(kù)存儲(chǔ)段信息,段大小設(shè)置過(guò)大或者過(guò)小都不利于充分發(fā)揮數(shù)據(jù)庫(kù)性能
4.2 BitmapAllocator
BitmapAllocator具體如下:
每一個(gè)BitmapEntry可以是64位位圖,管理64個(gè)基本塊。
BitmapAreaZone是BitmapAllocator單次最大可分配單位,大小可配置,所有API是原子的,因此不同的BitmapAreaZone之間可以并發(fā)操作。
BitmapAreaLeaf是葉子節(jié)點(diǎn),包含固定數(shù)量的BitmapAreaZone,為了提升索引效率可以在往上組若干層BitmapAreaInternal。
整個(gè)BitmapAllocator的拓?fù)浣Y(jié)構(gòu)是可以配置的,主要受兩個(gè)參數(shù)的約束:一是BitmapAreaZone的大小,決定了單次可分配最大連續(xù)空間,也決定了并發(fā)操作粒度;二是單個(gè)節(jié)點(diǎn)(中間或葉子)的跨度(span-size),這個(gè)參數(shù)決定了樹(shù)的高度,從而決定了索引的效率。
為了減少空間碎片化,同時(shí)提升索引效率,BitmapAllocator還可以自定義配置最小可分配空間,所有BitmapAllocator分配的空間必須是最小可分配空間整數(shù)倍。
5.BlueFS
RocksDB具有以下特點(diǎn):
1)專為使用本地SSD設(shè)備作為存儲(chǔ)后端且存儲(chǔ)容量不超過(guò)幾個(gè)TB的應(yīng)用程序設(shè)計(jì),是一種內(nèi)嵌式的非分布式數(shù)據(jù)庫(kù)。
2)適合于存儲(chǔ)小型或者中型鍵值對(duì);性能隨鍵值對(duì)長(zhǎng)度上升下降很快。
3)性能隨CPU核數(shù)以及后端存儲(chǔ)設(shè)備的I/O能力呈線性擴(kuò)展
由于RocksDB設(shè)計(jì)理念與BlueStore高度一致,所以BlueStore默認(rèn)使用RocksDB作為元數(shù)據(jù)存儲(chǔ)引擎。
但是由于操作系統(tǒng)自帶的本地文件系統(tǒng)(例如XFS、ext3、ext4、ZFS等)對(duì)RocksDB而言很多不是必須,所以需要對(duì)本地文件系統(tǒng)進(jìn)行剪裁,所以BlueFS應(yīng)運(yùn)而生。
BlueFS是一個(gè)簡(jiǎn)易的用戶態(tài)日志型文件系統(tǒng),將BlueStore分成了三個(gè)層次:
1)慢速(Slow)空間:這類空間主要用于存儲(chǔ)對(duì)象數(shù)據(jù),可有普通大容量機(jī)械磁盤提供,由BlueStore自行管理。
2)高速(DB)空間:這類空間主要用于存儲(chǔ)BlueStore內(nèi)部產(chǎn)生的元數(shù)據(jù)(如onode、雙寫的日志)由RocksDB最終通過(guò)BlueFS直接管理。
3)超高速(WAL)空間:這類空間主要用于存儲(chǔ)RocksDB內(nèi)部產(chǎn)生的.log文件??捎蒒VMe SSD或NVRAM等時(shí)延相較普通SSD更小的設(shè)備充當(dāng),容量需求和2)相當(dāng)(實(shí)際上還取決于RocksDB相關(guān)參數(shù)設(shè)置)。超高速空間也有BlueFS直接管理
DB設(shè)備和WAL設(shè)備由BlueFS單獨(dú)管理,對(duì)BlueStore不可見(jiàn),由于BlueFS存儲(chǔ)BlueStore元數(shù)據(jù),因此BlueFS的元數(shù)據(jù)較少,所以每次BlueFS上電后,遍歷BlueFS的元數(shù)據(jù)恢復(fù)三個(gè)空間的Allocator
整個(gè)Ceph有四個(gè)Allocator,一個(gè)是BlueStore管理慢速空間的Allocator,剩下三個(gè)是BlueFS管理慢速(當(dāng)做高速、超高速)、高速、超高速空間的Allocator
BlueFS也允許慢速空間當(dāng)做高速、超高速空間。具體策略為:BlueStore通過(guò)自身周期性被喚醒的同步線程實(shí)時(shí)查詢BlueFS的可用空間,如果BlueFS可用空間占比過(guò)小,則分配一些慢速空間,反之的回收一部分慢速空間。成功分配給BlueFS的空間段單獨(dú)寫入bluefs_extents的集合,并從自身的Allocator扣除。每次更新bluefs_extents后,BlueStore都會(huì)將其作為元數(shù)據(jù)存盤,后續(xù)BlueFS上電時(shí),通過(guò)BlueStore傳遞預(yù)先從數(shù)據(jù)庫(kù)加載的bluefs_extents,即可正確初始化BlueFS的慢速空間的Allocator。
6.BlueFS的磁盤數(shù)據(jù)結(jié)構(gòu)
BlueFS也采用層級(jí)結(jié)構(gòu),但是由于只用于存儲(chǔ)BlueStore的元數(shù)據(jù),所以只有扁平的兩層,第一層目錄絕對(duì)路徑,第二層文件,結(jié)構(gòu)如下:
BlueFS的文件也采用類似inode的結(jié)構(gòu)來(lái)管理,叫做bluefs_fnode_t簡(jiǎn)稱fnode,file_map是文件名和fnode的映射。fnode結(jié)構(gòu)如下:
每個(gè)文件可能來(lái)自多個(gè)不同的塊空間(WAL、DB、Slow),所以extent還需要額外記錄歸屬塊設(shè)備標(biāo)識(shí)。
BlueFS是日志型文件系統(tǒng),每次操作只會(huì)記錄一個(gè)簡(jiǎn)單的日志即向RocksDB返回操作成功。BlueFS采用增量日志模式,隨著時(shí)間增加,隔一段時(shí)間需要將日志壓縮成一個(gè)獨(dú)立的日志事務(wù),來(lái)節(jié)省WAL設(shè)備空間,日志事務(wù)結(jié)構(gòu)如下:
所以每隔一段時(shí)間,BlueFS會(huì)將增量日志進(jìn)行合并化簡(jiǎn),然后將剩余的多條日志編碼成op_bl作為一個(gè)日志事務(wù),BlueFS下次上電,重放這個(gè)日志事務(wù),就可以還原出完整最新的dir_map和file_map。
由于日志事務(wù)也是一個(gè)文件,所以需要一個(gè)超級(jí)塊來(lái)記錄日志文件位置,這樣掛載BlueFS即讀入超級(jí)塊后,就可以恢復(fù)BlueFS的dir_map和file_map以供用戶查看。超級(jí)塊結(jié)構(gòu)如下:
BlueFS整體架構(gòu)如下:
7.實(shí)現(xiàn)原理
7.1 mkfs
我們知道,linux中對(duì)一個(gè)塊設(shè)備執(zhí)行mkfs命令的意思是對(duì)塊設(shè)備格式化文件系統(tǒng),底層是將文件系統(tǒng)的超級(jí)塊中的數(shù)據(jù)初始化好后保存到塊設(shè)備指定位置,而mount掛載文件系統(tǒng)的時(shí)候,也就是將該塊設(shè)備的超級(jí)塊讀到內(nèi)存。根據(jù)超級(jí)塊的信息,os就可以還原或查詢當(dāng)前文件系統(tǒng)文件目錄的拓?fù)浣Y(jié)構(gòu)、文件信息等所有文件系統(tǒng)元數(shù)據(jù)。
對(duì)于BlueStroe同理,mkfs將BlueStore的配置項(xiàng)(也就是fs的超級(jí)塊)寫入塊設(shè)備。
只不過(guò)Ceph對(duì)于存儲(chǔ)后端有FileStroe、BlueStore兩種實(shí)現(xiàn),對(duì)于FreelistManager也有段式和位圖兩種方式實(shí)現(xiàn)。
7.2 mount
Ceph的mount也就是將ObjectStore的配置項(xiàng)讀出后,校驗(yàn)ObjectStore,加載鎖定fsid。
和普通文件系統(tǒng)不一樣的是,文件系統(tǒng)元數(shù)據(jù)固化在磁盤,讀出超級(jí)塊就可以找到元數(shù)據(jù)從而知曉整個(gè)文件系統(tǒng)。
但是BlueStore元數(shù)據(jù)存儲(chǔ)在RocksDB,因此mount還需要加載數(shù)據(jù)庫(kù)并從數(shù)據(jù)庫(kù)讀出元數(shù)據(jù)(元數(shù)據(jù)包括BlueFS的超級(jí)塊),有了BlueStore的元數(shù)據(jù)和BlueFS的超級(jí)塊,也就知曉了整個(gè)BlueStore和BlueFS。
我們知道文件系統(tǒng)的元數(shù)據(jù)包括兩樣:inode(記錄文件信息)和空閑塊位圖(記錄所有磁盤塊狀態(tài)),這兩樣可能不會(huì)常駐內(nèi)存,但是超級(jí)塊記錄了這兩樣在磁盤的位置以便cache未命中元數(shù)據(jù)時(shí)可以隨時(shí)讀盤訪問(wèn)他們。
而B(niǎo)lueStore的元數(shù)據(jù)均存儲(chǔ)在RocksDB,包括:Onode(記錄對(duì)象信息)、Collection(記錄PG信息)、FreelistManger(固化的BlueStore的空閑塊列表,可以還原出Allocator,因?yàn)閛node太大固化內(nèi)存或者遍歷效率低)
BlueFS的元數(shù)據(jù)也存儲(chǔ)在RocksDB,包括BlueFS日志文件(重放日志可以恢復(fù)dir_map、file_map,而file_map記錄了Bluefs的fnode)、fnode(保存BlueFS的文件信息,遍歷fnode可以還原DB、WAL設(shè)備的Allocator)、bluefs_extents(分配給BlueFS的慢速設(shè)備,可以恢復(fù)出BlueFS的慢速設(shè)備的Allocator)
根據(jù)上述分析,mount讀出上述表格的元數(shù)據(jù),即可創(chuàng)建BlueStore的FreelistManager,同時(shí)再依靠bluefs_extents(知道那些給了BlueFS)還原出BlueStore的Allocator(慢速設(shè)備)。也加載了BlueFS
最后加載Collection,BlueFS的日志重放
7.3 read
BlueStore的read、write針對(duì)PG提供,API粒度都是PG、多線程。read同步、write異步,訪問(wèn)的是PG的某個(gè)對(duì)象中的某段數(shù)據(jù)。
上圖很清晰,read()是同步的,查詢Collection的時(shí)間可以忽略不計(jì)。
7.4 write
所有寫請(qǐng)求通過(guò)標(biāo)準(zhǔn)(由ObjectStore定義)的queue_transactions接口提交至BlueStore處理,顧名思義,queue_transactions提交的是多個(gè)事務(wù),這些事務(wù)形成一個(gè)事務(wù)組,作為一個(gè)整體同樣遵循ACID語(yǔ)義。
一致性指的是,對(duì)于修改操作,要么事務(wù)的操作全部完成,要么一個(gè)不做,不可能介于兩者狀態(tài)之間。(ALL or Nothing)
OpSequencer用于對(duì)同一個(gè)PG提交的多個(gè)事務(wù)組進(jìn)行保序,其中每一個(gè)事務(wù)組,對(duì)于同一個(gè)事務(wù)組的多個(gè)操作,BlueStore會(huì)創(chuàng)建一個(gè)事務(wù)上下文TransContext,將每個(gè)寫操作順序添加至TransContext,然后批量處理。
queue_transactions提交的事務(wù)組都是異步執(zhí)行,執(zhí)行成功會(huì)執(zhí)行回調(diào)函數(shù)on_commit和on_readable。
上圖對(duì)于MAS(最小分配空間,可配置)對(duì)齊的寫時(shí)重定向很清晰不復(fù)雜,對(duì)于MAS非對(duì)齊的頭尾基本塊稍微復(fù)雜一些,具體如下:
1)能否也采用COW
2)能否直接復(fù)用已有的Extent的unused塊(MAS大于基本塊時(shí),Extent可能會(huì)存在基本塊空穴)
這種情況就是只用向新塊寫數(shù)據(jù),不存在寫覆蓋,不需要COW、RMW。
3)以上兩種情況均不存在,RMW不可避免,必須WAL寫
可以看到,假如MAS等于基本塊大小,頭尾基本塊未對(duì)齊的四種基本塊情況如上圖
右斜杠表示的數(shù)據(jù)則是原數(shù)據(jù),需要補(bǔ)齊讀,左斜杠是需要寫入新數(shù)據(jù),和補(bǔ)齊讀的合并,白色的是基本塊內(nèi)的空穴、用0填充。然后再對(duì)這樣的基本塊中的數(shù)據(jù)生成一個(gè)日志事務(wù),并將其加入對(duì)應(yīng)的TransContext。以上過(guò)程存在補(bǔ)齊讀、合并、填充0、生成日志事務(wù),所以WAL寫效率很低。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-786658.html
值得注意的是,產(chǎn)生RMW寫的日志事務(wù)是和COW寫同步IO進(jìn)行,元數(shù)據(jù)同步至數(shù)據(jù)庫(kù)后,才會(huì)開(kāi)始覆蓋寫。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-786658.html
到了這里,關(guān)于ceph之rados設(shè)計(jì)原理與實(shí)現(xiàn)第五章:高效的本地對(duì)象存儲(chǔ)引擎Bluestore的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!