BlueStore——先进的用户态文件系统《一》
目錄
為什么需要 BlueStore
IO 放大
對(duì)象遍歷
其他
BlueStore 介紹
邏輯架構(gòu)
設(shè)計(jì)思想
總結(jié)
引言
分布式存儲(chǔ)系統(tǒng)通過(guò)將數(shù)據(jù)分散到多臺(tái)機(jī)器上來(lái)充分利用多臺(tái)機(jī)器的資源提高系統(tǒng)的存儲(chǔ)能力,每臺(tái)機(jī)器上的數(shù)據(jù)存放都需要本地的單機(jī)存儲(chǔ)系統(tǒng),它是整個(gè)分布式存儲(chǔ)系統(tǒng)的基礎(chǔ),為其提供保障。設(shè)計(jì)高性能、高可靠的分布式存儲(chǔ)系統(tǒng)離不開(kāi)高效、一致、穩(wěn)定、可靠的本地存儲(chǔ)系統(tǒng)。
Ceph 是目前業(yè)內(nèi)比較普遍使用的開(kāi)源分布式存儲(chǔ)系統(tǒng),實(shí)現(xiàn)有多種類(lèi)型的本地存儲(chǔ)系統(tǒng);在較早的版本當(dāng)中,Ceph?默認(rèn)使用 FileStore 作為后端存儲(chǔ),但是由于 FileStore 存在一些缺陷,重新設(shè)計(jì)開(kāi)發(fā)了 BlueStore,并在L版本之后作為默認(rèn)的后端存儲(chǔ)。BlueStore 的一些設(shè)計(jì)思想對(duì)于設(shè)計(jì)滿足分布式存儲(chǔ)系統(tǒng)需求的本地存儲(chǔ)系統(tǒng)具有參考意義,因此我們將對(duì) BlueStore 的一些原理進(jìn)行剖析,供讀者進(jìn)行參考和探討。在這一章中,我們將要了解 BlueStore 的誕生背景,以及它的一些設(shè)計(jì)思想。
?
?
為什么需要 BlueStore
前面提到,BlueStore 的誕生背景是由于 FileStore 存在的一些缺陷,這些缺陷具體是什么?
?
IO 放大
FileStore 底層使用POSIX規(guī)范的文件系統(tǒng)接口,例如 xfs、ext4、btrfs,然而這類(lèi)文件系統(tǒng)本身不支持?jǐn)?shù)據(jù)或元數(shù)據(jù)的事務(wù)操作接口(btrfs 提供事務(wù)鉤子的接口,但是測(cè)試過(guò)程中發(fā)現(xiàn)會(huì)導(dǎo)致系統(tǒng)宕機(jī)),而 Ceph?對(duì)于數(shù)據(jù)寫(xiě)入要求十分嚴(yán)格,需要滿足事務(wù)的特性(ACID);為此 FileStore 實(shí)現(xiàn)了 FileJournal 功能,所有的事務(wù)都需要先寫(xiě)到 FileJournal 中,之后才會(huì)寫(xiě)入對(duì)應(yīng)的文件中,以此來(lái)保證事務(wù)的原子性,但是這導(dǎo)致了數(shù)據(jù) “雙寫(xiě)” 的問(wèn)題,造成至少一半磁盤(pán)帶寬的浪費(fèi)。此外 xfs、ext4、btrfs 這類(lèi)文件系統(tǒng)本身存在一定的 IO 放大(即一次讀寫(xiě)請(qǐng)求實(shí)際在低層磁盤(pán)發(fā)生的 IO 次數(shù)),再加上 FileStore 的日志雙寫(xiě),放大倍數(shù)成倍增加。
下圖中的數(shù)據(jù)表示了以 block 大小為單位對(duì)不同文件系統(tǒng)進(jìn)行讀寫(xiě),在不同場(chǎng)景下的讀寫(xiě)放大及空間放大情況。我們以 ext4 文件系統(tǒng)說(shuō)明下個(gè)參數(shù)的含義。在對(duì)文件進(jìn)行 Overwrite 時(shí),即將數(shù)據(jù)覆蓋寫(xiě)入到文件中,除了寫(xiě)入數(shù)據(jù)外,還涉及到日志的寫(xiě)入(其中日志寫(xiě)入兩次,一次記錄更改的 inode,一次為 commit 記錄,具體可參考)、文件 inode 的更改,每次寫(xiě)的最小單位是block,因此最終相當(dāng)于寫(xiě)入次數(shù)以及空間放大了四倍;而在進(jìn)行 Append 寫(xiě)入時(shí),由于需要新分配空間,因此相對(duì)于 Overwrite 增加了 bitmap 的更改以及 superblock 的更改( superblock 記錄總的空間分配情況),寫(xiě)放大和空間放大均為六倍。讀文件時(shí),在沒(méi)有命中任何緩存的情況下,需要讀大量元數(shù)據(jù),例如:目錄、文件 inode、superblock 等,最終讀放大為六倍;而如果是在順序讀的情況下,像 superblock、bitmap、目錄等這些元數(shù)據(jù)都緩存在內(nèi)存中,只需讀取文件 inode 和文件數(shù)據(jù)。?
同理,其他文件系統(tǒng)由于不同的結(jié)構(gòu)和設(shè)計(jì)原理,其 IO 放大和空間放大系數(shù)也各不相同。下面這個(gè)表展示了不同文件系統(tǒng)在讀寫(xiě)文件時(shí)產(chǎn)生的讀、寫(xiě)和空間放大程度。
?
?
對(duì)象遍歷
Ceph?的數(shù)據(jù)被劃分為 object 存放,object 以 32 位的 hash 值進(jìn)行標(biāo)識(shí),ceph 在進(jìn)行 scrubbing、backfill 或者 recovery 時(shí)都需要根據(jù) hash 值遍歷這些 object;POSIX 文件系統(tǒng)不提供有序的文件遍歷接口,為此 FileStore 根據(jù)文件的數(shù)量和 hash 的前綴將 object 劃分到不同的子目錄,其原則如下:
- 當(dāng)目錄下的文件個(gè)數(shù) >100 個(gè)時(shí),拆分子目錄;目錄名以文件名的 hash 前綴為依據(jù)(拆分一級(jí)目錄時(shí),以 hash 第一位為拆分依據(jù),二級(jí)目錄以第二位 hash 為拆分依據(jù),依次類(lèi)推)。
- 當(dāng)所有子目錄下的文件個(gè)數(shù) <50 個(gè)時(shí),將合并到上級(jí)目錄。
因此 FileStore 在使用過(guò)程中需要不斷合并拆分目錄結(jié)構(gòu);這種方式將文件按照前綴放到不同目錄,但對(duì)于同一目錄中的文件依然無(wú)法很好排序,因此需要將目錄中的所有文件讀到內(nèi)存進(jìn)行排序,這樣在一定程度上增加了 CPU 開(kāi)銷(xiāo)。
?
其他
- FileStore 由于設(shè)計(jì)的較早,無(wú)法支持當(dāng)前較新的存儲(chǔ)技術(shù),例如使用 spdk 技術(shù)讀寫(xiě) NVMe 盤(pán)。
- 數(shù)據(jù)和元數(shù)據(jù)分離不徹底。
- 流控機(jī)制不完整導(dǎo)致 IOPS 和帶寬抖動(dòng)(FileStore 自身無(wú)法控制本地文件系統(tǒng)的刷盤(pán)行為)。
- 頻繁 syncfs 系統(tǒng)調(diào)用導(dǎo)致 CPU 利用率居高不下。
sync() causes all buffered modifications to file metadata and ?data ?to?be written to the underlying filesystems.
syncfs() ?is like sync(), but synchronizes just the filesystem containing file referred to by the open file descriptor fd.
sync() 將導(dǎo)致所有對(duì)文件元數(shù)據(jù)和數(shù)據(jù)的緩沖修改寫(xiě)入底層文件系統(tǒng)。
syncfs() 類(lèi)似于 sync(),但只同步包含打開(kāi)文件描述符 fd 引用的文件的文件系統(tǒng)。
?
?
BlueStore 介紹
首先看下 BlueStore 設(shè)計(jì)之初的一些需求:
- 對(duì)全 SSD 及全 NVMe SSD 閃存適配
- 繞過(guò)本地文件系統(tǒng)層,直接管理裸設(shè)備,縮短 IO 路徑
- 嚴(yán)格分離元數(shù)據(jù)和數(shù)據(jù),提高索引效率
- 使用 KV 索引,解決文件系統(tǒng)目錄結(jié)構(gòu)遍歷效率低的問(wèn)題
- 支持多種設(shè)備類(lèi)型
- 解決日志“雙寫(xiě)”問(wèn)題
- 期望帶來(lái)至少 2 倍的寫(xiě)性能提升和同等讀性能
- 增加數(shù)據(jù)校驗(yàn)及數(shù)據(jù)壓縮等功能
?
邏輯架構(gòu)
BlueStore 的邏輯架構(gòu)如上圖所示,模塊的劃分都還比較清晰,我們來(lái)看下各模塊的作用:
RocksDB:RocksDB?是 FaceBook 基于 leveldb 開(kāi)發(fā)的一款 kv 數(shù)據(jù)庫(kù),BlueStore 將元數(shù)據(jù)全部存放至 RocksDB 中,這些元數(shù)據(jù)包括存儲(chǔ)預(yù)寫(xiě)式日志、數(shù)據(jù)對(duì)象元數(shù)據(jù)、Ceph 的 omap 數(shù)據(jù)信息、以及分配器的元數(shù)據(jù) 。
BlueRocksEnv:這是 RocksDB 與 BlueFS 交互的接口;RocksDB 提供了文件操作的接口 EnvWrapper,用戶(hù)可以通過(guò)繼承實(shí)現(xiàn)該接口來(lái)自定義底層的讀寫(xiě)操作,BlueRocksEnv 就是繼承自 EnvWrapper 實(shí)現(xiàn)對(duì) BlueFS 的讀寫(xiě)。
BlueFS:BlueFS 是 BlueStore 針對(duì) RocksDB 開(kāi)發(fā)的輕量級(jí)文件系統(tǒng),用于存放 RocksDB 產(chǎn)生的 .sst 和 .log 等文件。
BlockDecive:BlueStore 拋棄了傳統(tǒng)的 ext4、xfs 文件系統(tǒng),使用直接管理裸盤(pán)的方式;BlueStore 支持同時(shí)使用多種不同類(lèi)型的設(shè)備,在邏輯上 BlueStore 將存儲(chǔ)空間劃分為三層:慢速(Slow)空間、高速(DB)空間、超高速(WAL)空間,不同的空間可以指定使用不同的設(shè)備類(lèi)型,當(dāng)然也可使用同一塊設(shè)備,具體我們會(huì)在后面的文章進(jìn)行說(shuō)明。
Allocator:負(fù)責(zé)裸設(shè)備的空間管理,只在內(nèi)存做標(biāo)記,目前支持 StupidAllocator 和 BitmapAllocator 兩種分配器,Stupid 基于 extent 的方式實(shí)現(xiàn) 。
?
?
設(shè)計(jì)思想
在設(shè)計(jì)分布式文件系統(tǒng)的本地存儲(chǔ)時(shí),我們必須考慮數(shù)據(jù)的一致性和可靠性。在數(shù)據(jù)寫(xiě)入的過(guò)程中,由于可能存在異常掉電、進(jìn)程崩潰等突發(fā)情況,導(dǎo)致數(shù)據(jù)還未全部寫(xiě)入成功便結(jié)束。雖然硬盤(pán)本身可以保證在扇區(qū)級(jí)別寫(xiě)入的原子性,但是一般文件系統(tǒng)的一個(gè)寫(xiě)請(qǐng)求通常包含多個(gè)扇區(qū)的數(shù)據(jù)和元數(shù)據(jù)更新,無(wú)法做到原子寫(xiě)。
常用的解決辦法是引入日志系統(tǒng),數(shù)據(jù)寫(xiě)入磁盤(pán)之前先寫(xiě)到日志系統(tǒng),然后再將數(shù)據(jù)落盤(pán);日志寫(xiě)入成功后,即便寫(xiě)數(shù)據(jù)時(shí)出現(xiàn)異常,也可以通過(guò)日志回放重新寫(xiě)入這部分?jǐn)?shù)據(jù);如果寫(xiě)日志的過(guò)程中出現(xiàn)異常,則直接放棄這部分日志,視為寫(xiě)入失敗即可,以此保證原子寫(xiě)入。但是這種方式導(dǎo)致每份數(shù)據(jù)都需要在磁盤(pán)上寫(xiě)入兩次,嚴(yán)重降低了數(shù)據(jù)的寫(xiě)入效率。
另一種方式則是采用 ROW(Redirect on write)的方式,即數(shù)據(jù)需要覆蓋寫(xiě)入時(shí),將數(shù)據(jù)寫(xiě)到新的位置,然后更新元數(shù)據(jù)索引,這種方式由于不存在覆蓋寫(xiě),只需保證元數(shù)據(jù)更新的原子性即可。對(duì)于對(duì)齊的覆蓋寫(xiě)入時(shí),這種方式?jīng)]有問(wèn)題,但是如果是非對(duì)齊的覆蓋寫(xiě)呢?
我們舉個(gè)例子:某文件的邏輯空間 [0,4096) 區(qū)間的數(shù)據(jù)在磁盤(pán)上的物理映射地址為 [0, 4096),磁盤(pán)的塊(即磁盤(pán)讀寫(xiě)的最小單元)大小為 4096 ;如果要覆蓋寫(xiě)文件 [0,4096) 區(qū)間的數(shù)據(jù),那使用 ROW 的方式?jīng)]有問(wèn)題,重新再磁盤(pán)上分配一個(gè)新的塊寫(xiě)入,然后更新元數(shù)據(jù)中的映射關(guān)系即可;但是如果寫(xiě)文件 [512,4096) 區(qū)域,也就是非對(duì)齊的覆蓋寫(xiě)時(shí),新分配的塊中只有部分?jǐn)?shù)據(jù),舊的物理空間中仍有部分?jǐn)?shù)據(jù)有效,這樣元數(shù)據(jù)中需要維護(hù)兩份索引,而且在讀取文件的該塊數(shù)據(jù)時(shí),需要從多塊磁盤(pán)塊中讀取數(shù)據(jù),如果多次進(jìn)行非對(duì)齊覆蓋寫(xiě),這種問(wèn)題將更嚴(yán)重。
解決這種問(wèn)題辦法是使用 RMW(Read Modify Write)的方法,即在發(fā)生非對(duì)齊覆蓋寫(xiě)時(shí),先讀取舊的數(shù)據(jù),更新的數(shù)據(jù)合并后,對(duì)齊寫(xiě)入到磁盤(pán)中,從而減少元數(shù)據(jù)、提高讀性能,但這種方式也存在一種缺點(diǎn),寫(xiě)數(shù)據(jù)時(shí)需要先讀數(shù)據(jù),存在一定的性能損耗。
分析完 ROW 的方式后,讀者是否會(huì)有疑問(wèn),每次寫(xiě)入都放到新的位置,那么文件在磁盤(pán)中的物理連續(xù)性豈不是無(wú)法保證?的確,在傳統(tǒng)的文件系統(tǒng)設(shè)計(jì)時(shí),都是面向 HDD 盤(pán),這種類(lèi)型的盤(pán)在讀寫(xiě)時(shí)會(huì)有磁頭尋道的時(shí)間,對(duì)于非連續(xù)的物理空間讀寫(xiě),性能極差,在設(shè)計(jì)時(shí)會(huì)盡可能考慮數(shù)據(jù)存放的連續(xù)性,因此很少會(huì)采用 ROW 的方式。但是隨著 SSD 盤(pán)的逐漸普及,隨機(jī)讀寫(xiě)的性能不再成為主要的性能關(guān)注點(diǎn),越來(lái)越多的存儲(chǔ)系統(tǒng)開(kāi)始采用全閃存的磁盤(pán)陣列,相信 ROW 的方式會(huì)成為更加主流的方式。
?
?
總結(jié)
BlueStore 的設(shè)計(jì)考慮了 FileStore 中存在的一些硬傷,拋棄了傳統(tǒng)的文件系統(tǒng)直接管理裸設(shè)備,縮短了 IO 路徑,同時(shí)采用 ROW 的方式,避免了日志雙寫(xiě)的問(wèn)題,在寫(xiě)入性能上有了極大的提高。
通過(guò)分析 BlueStore 的基本結(jié)構(gòu)、考慮的問(wèn)題以及設(shè)計(jì)思想,我們對(duì)于 BlueStore 有了大概的了解;BlueStore 在設(shè)計(jì)時(shí)有考慮到未來(lái)存儲(chǔ)的應(yīng)用環(huán)境,是一種比較先進(jìn)的本地文件系統(tǒng),但也不可避免存在一些缺陷,例如較為復(fù)雜的元數(shù)據(jù)結(jié)構(gòu)和 IO 邏輯,在大量小 IO 下可能存在的 double write 問(wèn)題,較大的元數(shù)據(jù)內(nèi)存占用等(當(dāng)然有些問(wèn)題在 Ceph?的使用場(chǎng)景下可能不存在,但是我們?nèi)绻M梃b BlueStore 來(lái)設(shè)計(jì)本地文件系統(tǒng)就不得不考慮這些問(wèn)題)。
在后續(xù)的文章中,我們將繼續(xù)深入剖析各個(gè)模塊的設(shè)計(jì)原理和流程,也會(huì)對(duì) BlueStore 測(cè)試過(guò)程中發(fā)現(xiàn)的一些問(wèn)題展開(kāi)討論。
?
參考資料
https://ceph.com/community/new-luminous-bluestore/
Jayashree Mohan, Rohan Kadekodi, Vijay Chidambaram. Analyzing IO Amplification in Linux File Systems. arXiv:1707.08514v1 [cs.OS] 26 Jul 2017 .
謝型果等. Ceph設(shè)計(jì)原理與實(shí)現(xiàn)[M]. 北京:機(jī)械工業(yè)出版社,2017.12.
?
原文鏈接:知乎鏈接
總結(jié)
以上是生活随笔為你收集整理的BlueStore——先进的用户态文件系统《一》的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 九种 0-1 背包问题详解
- 下一篇: Google Spanner:谷歌的全球