龔 恒,李小勇
(上海交通大學(xué) 網(wǎng)絡(luò)空間安全學(xué)院,上海 200240)
傳統(tǒng)意義上,文件系統(tǒng)是操作系統(tǒng)內(nèi)核的一部分。隨著分布式存儲(chǔ)系統(tǒng)[1]的出現(xiàn)和大數(shù)據(jù)分析技術(shù)[2]需求的增大,面對(duì)海量的數(shù)據(jù)文件,用戶實(shí)現(xiàn)數(shù)據(jù)訪問(wèn)的步驟也越來(lái)越繁瑣,開(kāi)發(fā)面向用戶場(chǎng)景的用戶態(tài)文件系統(tǒng)[3]勢(shì)在必行。
本文底層使用分布式對(duì)象存儲(chǔ)系統(tǒng),結(jié)合fuse[4-5]技術(shù)和分布式數(shù)據(jù)庫(kù)MongoDB[6],設(shè)計(jì)基于分布式存儲(chǔ)的用戶態(tài)文件系統(tǒng)bfs-fuse,以文件目錄形式對(duì)分布式對(duì)象存儲(chǔ)系統(tǒng)中的對(duì)象進(jìn)行管理和訪問(wèn),從而為用戶提供高效便捷的數(shù)據(jù)訪問(wèn)管理策略。
底層數(shù)據(jù)使用分布式存儲(chǔ)系統(tǒng)。分布式存儲(chǔ)將數(shù)據(jù)對(duì)象分散到多個(gè)存儲(chǔ)服務(wù)器上,并將這些分散的數(shù)據(jù)資源通過(guò)統(tǒng)籌管理合并為一個(gè)虛擬統(tǒng)一的存儲(chǔ)系統(tǒng)。
典型的分布式存儲(chǔ)架構(gòu),如圖1所示。
圖1 分布式存儲(chǔ)架構(gòu)
它通常由3個(gè)部分組成——管理節(jié)點(diǎn)(Manager Node)、數(shù)據(jù)節(jié)點(diǎn)(Data Node)和應(yīng)用客戶端(Client)。其中,管理節(jié)點(diǎn)負(fù)責(zé)管理集群元數(shù)據(jù)、協(xié)調(diào)集群服務(wù)、響應(yīng)客戶端發(fā)來(lái)的數(shù)據(jù)請(qǐng)求等。在整個(gè)集群架構(gòu)中,管理節(jié)點(diǎn)是最核心的部分,通常采用主從、多活等方式增加整個(gè)架構(gòu)的穩(wěn)定性和安全性。數(shù)據(jù)節(jié)點(diǎn)主要負(fù)責(zé)存儲(chǔ)用戶數(shù)據(jù),保證用戶數(shù)據(jù)的可用性和完整性;應(yīng)用客戶端負(fù)責(zé)發(fā)送數(shù)據(jù)的讀寫(xiě)請(qǐng)求,緩存元數(shù)據(jù)和用戶數(shù)據(jù)。
20世紀(jì)末,麻省理工學(xué)院Karger等人提出一致性哈希算法,解決了分布式結(jié)構(gòu)中動(dòng)態(tài)增加和刪除帶來(lái)的雪崩問(wèn)題以及數(shù)據(jù)分布不均衡問(wèn)題,在分布式系統(tǒng)中得到了廣泛應(yīng)用。
本文使用一致性哈希算法作為分布式存儲(chǔ)數(shù)據(jù)節(jié)點(diǎn)的數(shù)據(jù)分布算法。集群中同一個(gè)存儲(chǔ)池中的所有數(shù)據(jù)對(duì)象,經(jīng)過(guò)一致性哈希運(yùn)算后被分散存儲(chǔ)到該存儲(chǔ)池中的所有存儲(chǔ)設(shè)備上。為增強(qiáng)數(shù)據(jù)分布的均衡性,在數(shù)據(jù)和存儲(chǔ)節(jié)點(diǎn)之間再引入一層虛擬節(jié)點(diǎn)(Cube)層。虛擬節(jié)點(diǎn)可以理解為存儲(chǔ)節(jié)點(diǎn)在哈??臻g中的復(fù)制品,其總數(shù)遠(yuǎn)大于存儲(chǔ)節(jié)點(diǎn)的數(shù)量,且按照不同存儲(chǔ)節(jié)點(diǎn)在容量和性能上的差異以及負(fù)載均衡的要求進(jìn)行分布。圖2展示的是系統(tǒng)在查找對(duì)象號(hào)object_id為obj_1的對(duì)象的查找映射過(guò)程。
圖2 數(shù)據(jù)分布查找映射
數(shù)據(jù)存儲(chǔ)采用多副本方式來(lái)提高數(shù)據(jù)的高可用性,各副本將被盡量存儲(chǔ)到不同的數(shù)據(jù)服務(wù)器。初始狀態(tài)下,容器中所有對(duì)象默認(rèn)以雙副本存儲(chǔ),也可在創(chuàng)建每個(gè)容器時(shí)對(duì)容器的副本數(shù)進(jìn)行單獨(dú)配置。對(duì)于相對(duì)重要的文件,通常以三副本保存。系統(tǒng)中每個(gè)對(duì)象對(duì)應(yīng)的文件擴(kuò)展屬性中保存了數(shù)據(jù)版本號(hào)和隨機(jī)序列數(shù),兩者結(jié)合進(jìn)行版本管理和一致性保證。
在讀取數(shù)據(jù)流程中,客戶端首先從三個(gè)副本所在的數(shù)據(jù)服務(wù)器拉取版本號(hào),選擇版本號(hào)最新的副本作為正確數(shù)據(jù)向上層應(yīng)用返回,并將版本號(hào)錯(cuò)誤的副本信息報(bào)告給對(duì)應(yīng)的數(shù)據(jù)服務(wù)器,以便在之后進(jìn)行數(shù)據(jù)修復(fù)。在寫(xiě)入數(shù)據(jù)流程中,客戶端將優(yōu)先寫(xiě)主副本,然后由主副本所在數(shù)據(jù)服務(wù)器采用扇出寫(xiě)的方式向另外兩臺(tái)數(shù)據(jù)服務(wù)器寫(xiě)從副本。為了平衡性能與一致性,底層向上層應(yīng)用保證最終一致性,即只有主副本落盤(pán)且確認(rèn)另外兩個(gè)從副本均已成功推送至對(duì)應(yīng)數(shù)據(jù)服務(wù)器后向客戶端返回?cái)?shù)據(jù)寫(xiě)入成功。
元數(shù)據(jù)的管理是分布式文件系統(tǒng)的核心,也是分布式存儲(chǔ)系統(tǒng)架構(gòu)和保障的重中之重。
為了提高文件元數(shù)據(jù)的一致性和可靠性,支持用戶文件系統(tǒng)目錄操作,本文使用MongoDB數(shù)據(jù)庫(kù)對(duì)分布式存儲(chǔ)系統(tǒng)存儲(chǔ)的文件元數(shù)據(jù)進(jìn)行集成管理。文件元數(shù)據(jù)最基本的作用在于數(shù)據(jù)對(duì)象的定位,客戶端只有先訪問(wèn)存儲(chǔ)元數(shù)據(jù)的管理節(jié)點(diǎn),得到數(shù)據(jù)對(duì)象的inode號(hào)以及相關(guān)的訪問(wèn)權(quán)限,才能進(jìn)行下一步的數(shù)據(jù)讀寫(xiě)訪問(wèn)。元數(shù)據(jù)服務(wù)模塊架構(gòu)如圖3所示。
圖3 元數(shù)據(jù)服務(wù)模塊架構(gòu)
為了提高系統(tǒng)的訪問(wèn)效率,將文件系統(tǒng)中所有目錄和文件用一張統(tǒng)一的表(fs_object)來(lái)管理,即用戶空間里的所有文件和目錄都被映射為存儲(chǔ)系統(tǒng)里面的一個(gè)個(gè)對(duì)象,通過(guò)關(guān)鍵字(is_dir)是否為0來(lái)區(qū)分文件和目錄。每個(gè)對(duì)象的元數(shù)據(jù)信息包括對(duì)象ID、對(duì)象名、父節(jié)點(diǎn)ID、是否是目錄、對(duì)象大小、創(chuàng)建時(shí)間、修改時(shí)間以及父inode號(hào)等。在訪問(wèn)請(qǐng)求中,客戶端只需要訪問(wèn)一張表就可以獲得文件對(duì)象的所有元數(shù)據(jù)信息,從而減少不必要的開(kāi)銷(xiāo),提高元數(shù)據(jù)的管理效率。
分布式存儲(chǔ)系統(tǒng)通常使用Linux系統(tǒng)作為硬件操作系統(tǒng),但Linux中文件系統(tǒng)中文件系統(tǒng)都在內(nèi)核態(tài)實(shí)現(xiàn),文件系統(tǒng)功能的增加和修改在內(nèi)核中需要做很大的工作量,且調(diào)試起來(lái)非常復(fù)雜,而fuse的出現(xiàn)改善了這一情況。
fuse(用戶態(tài)文件系統(tǒng))是一個(gè)在用戶空間實(shí)現(xiàn)的文件系統(tǒng)框架,通過(guò)fuse內(nèi)核模塊給予支持?;趂use提供的接口,本文設(shè)計(jì)實(shí)現(xiàn)了支持對(duì)象與文件映射和文件操作的文件訪問(wèn)系統(tǒng)bfs-fuse。
在bfs-fuse中,由內(nèi)核模塊創(chuàng)建塊設(shè)備/dev/fuse,作用是溝通用戶空間進(jìn)程的fuse進(jìn)程和系統(tǒng)內(nèi)核。來(lái)自/dev/fuse的所有請(qǐng)求都是通過(guò)file requests請(qǐng)求隊(duì)列發(fā)送到內(nèi)核,bfs-fuse從/dev/fuse中讀取請(qǐng)求并進(jìn)行處理。
當(dāng)用戶態(tài)應(yīng)用程序(如ls、cp、mv、rm等)發(fā)起具體請(qǐng)求時(shí),應(yīng)用程序?qū)⑽募到y(tǒng)操作請(qǐng)求發(fā)送給內(nèi)核,內(nèi)核讀取來(lái)自該設(shè)備的請(qǐng)求。內(nèi)核中,每一個(gè)具體的請(qǐng)求都包含具體文件的inode,內(nèi)核需要解析文件路徑中每一層路徑的inode號(hào)進(jìn)行拼接,得到文件具體的inode號(hào),再根據(jù)文件的inode號(hào)從MongoDB數(shù)據(jù)庫(kù)中得到文件映射在存儲(chǔ)系統(tǒng)中對(duì)象的object_id,進(jìn)而通過(guò)一致性哈希運(yùn)算得到對(duì)象在分布式儲(chǔ)存中的location地址,最后從分布式系統(tǒng)中取出數(shù)據(jù)對(duì)象,返回給用戶空間的應(yīng)用程序。它的內(nèi)核調(diào)用流程如圖4所示。
在原有的分布式集群中增加fuse組件和元數(shù)據(jù)信息的管理,必然會(huì)降低文件系統(tǒng)增刪查改對(duì)象的效率。為了減少系統(tǒng)性能的損失,在設(shè)計(jì)bfs-fuse時(shí),本文針對(duì)分布式存儲(chǔ)的特性,對(duì)fuse掛載組件的部分參數(shù)配置進(jìn)行了如下改進(jìn)。
(1)提高頁(yè)面空間大小。在fuse中,默認(rèn)請(qǐng)求被分配的page大小是4 kB,但實(shí)際中存儲(chǔ)的文件大小通常遠(yuǎn)大于4 kB,使得文件寫(xiě)入時(shí)上下文切換頻率增加,降低文件讀寫(xiě)效率,故bfs-fuse中將頁(yè)面空間大小修改為128 kB。
(2)緩存文件的元數(shù)據(jù)信息。對(duì)于只讀和查詢的文件,對(duì)文件的inode和dentry結(jié)構(gòu)進(jìn)行緩存。
(3)數(shù)據(jù)直接I/O讀寫(xiě)。對(duì)于數(shù)據(jù)需要直接落盤(pán)的應(yīng)用,允許應(yīng)用程序跳過(guò)緩存,直接將數(shù)據(jù)寫(xiě)入存儲(chǔ)設(shè)備中。
本文的測(cè)試方案通過(guò)海量數(shù)量小文件讀寫(xiě)測(cè)試和大文件讀寫(xiě)測(cè)試兩個(gè)角度模擬實(shí)際應(yīng)用中的I/O需求。通過(guò)海量小文件的讀寫(xiě),測(cè)試系統(tǒng)的性能瓶頸;通過(guò)大文件的讀寫(xiě),測(cè)試系統(tǒng)的吞吐量性能。部署3節(jié)點(diǎn)分布式存儲(chǔ)集群作為測(cè)試環(huán)境,所有硬件服務(wù)器均為DELL服務(wù)器,內(nèi)存32 GB,16核CPU,千兆以太網(wǎng)。測(cè)試腳本通過(guò)調(diào)用linux讀寫(xiě)接口,在磁盤(pán)中創(chuàng)建和讀寫(xiě)文件,并返回讀寫(xiě)時(shí)間和帶寬。
圖4 bfs-fuse內(nèi)核調(diào)用流程
在小文件測(cè)試中,分別使用1~1 024個(gè)線程。每個(gè)線程分別在掛載目錄寫(xiě)入、讀取100個(gè)16 kB大小的文件,用來(lái)模擬現(xiàn)實(shí)網(wǎng)絡(luò)中常見(jiàn)的小文件讀寫(xiě),測(cè)試結(jié)果如圖5所示。
圖5 小文件讀寫(xiě)測(cè)試
從圖5可以看出,由于使用分布式存儲(chǔ),小文件讀寫(xiě)的性能隨著線程數(shù)的增加而增加;當(dāng)線程并發(fā)數(shù)超過(guò)256時(shí),讀寫(xiě)性能趨于穩(wěn)定,分別是35 MB/s和80 MB/s左右。它的帶寬低于千兆以太網(wǎng)理論帶寬的峰值,這是因?yàn)閷?duì)于海量的小文件,讀寫(xiě)過(guò)程中產(chǎn)生的額外開(kāi)銷(xiāo)不可忽視,如MongoDB元數(shù)據(jù)讀寫(xiě)、文件查詢和定位等。從讀寫(xiě)整體性能對(duì)比來(lái)看,相同線程數(shù)寫(xiě)入的帶寬速率要遠(yuǎn)高于讀取速率,這是因?yàn)樾∥募繉?xiě)入時(shí)采取的是順序?qū)懙姆绞?,但讀取時(shí)因?yàn)槲募笮”容^小、數(shù)量多,其讀取方式相當(dāng)于隨機(jī)讀取,所以讀取帶寬速率會(huì)小于寫(xiě)入的帶寬速率。
在大文件測(cè)試中,分別使用1~1 024個(gè)線程。每個(gè)線程分別在掛載目錄寫(xiě)入、讀取4個(gè)1 GB大小的文件,用來(lái)模擬現(xiàn)實(shí)網(wǎng)絡(luò)中常見(jiàn)的大文件讀寫(xiě),測(cè)試結(jié)果如圖6所示。其中,隨著線程并發(fā)數(shù)的增加,讀寫(xiě)帶寬隨之增加,最終趨近于各自的峰值140 MB/s和120 MB/s。這與千兆以太網(wǎng)理論帶寬相近。
圖6 大文件讀寫(xiě)測(cè)試
從整體來(lái)看,系統(tǒng)在吞吐量性能方面有著不錯(cuò)的表現(xiàn),但在小文件讀取性能方面有一定的提升空間,因?yàn)槲募到y(tǒng)通過(guò)MongDB訪問(wèn)元數(shù)據(jù)帶來(lái)的性能開(kāi)銷(xiāo)在小文件讀寫(xiě)中無(wú)法忽視,建議對(duì)MongoDB服務(wù)器配置SSD固態(tài)磁盤(pán)存儲(chǔ)元數(shù)據(jù),同時(shí)開(kāi)啟MongoDB緩存提高元數(shù)據(jù)訪問(wèn)速率,進(jìn)而提高海量小文件讀取時(shí)的性能。
本文的創(chuàng)新點(diǎn)是在分布式存儲(chǔ)系統(tǒng)的基礎(chǔ)上,結(jié)合MongoDB,使用fuse框架設(shè)計(jì),實(shí)現(xiàn)了面向海量數(shù)據(jù)的用戶態(tài)分布式文件系統(tǒng),既具有很高的靈活性和可擴(kuò)展性,又使得用戶對(duì)分布式存儲(chǔ)系統(tǒng)的訪問(wèn)更加便捷,管理更加方便。經(jīng)過(guò)小文件讀寫(xiě)和大文件吞吐量測(cè)試可以發(fā)現(xiàn),本文設(shè)計(jì)的文件系統(tǒng)在吞吐量性能和小文件創(chuàng)建方面有著優(yōu)良的性能表現(xiàn),但在小文件讀取性能方面有進(jìn)一步的提高空間。