魏 征 黎斐南 邢 晶 霍志剛 孫凝暉
(*中國(guó)科學(xué)院大學(xué) 北京 100089)(**計(jì)算機(jī)體系結(jié)構(gòu)國(guó)家重點(diǎn)實(shí)驗(yàn)室 北京 100089)(***中國(guó)科學(xué)院計(jì)算技術(shù)研究所 北京 100089)
存儲(chǔ)設(shè)備在過(guò)去很長(zhǎng)一段時(shí)間都被視為高延遲的慢速設(shè)備,隨著新材料和設(shè)備的研制,存儲(chǔ)設(shè)備的性能有了很大改善,I/O延遲大大下降。然而目前的大部分軟硬件的設(shè)計(jì)還是建立在慢速設(shè)備的假設(shè)上,這種設(shè)計(jì)無(wú)法充分發(fā)揮新式存儲(chǔ)設(shè)備的性能,因而仍存在讀寫(xiě)延遲高的問(wèn)題。
機(jī)械硬盤(pán)(hard disk drive, HDD)[1]作為主要的廉價(jià)存儲(chǔ)設(shè)備,從最初的3.75 MB到現(xiàn)在的14 TB,HDD的容量增加了373萬(wàn)倍。但是,HDD的訪問(wèn)延遲從600 ms下降到了2 ms,只減少到了原來(lái)的1/300。HDD數(shù)據(jù)存儲(chǔ)在盤(pán)片上,受機(jī)械結(jié)構(gòu)的限制,碟片的旋轉(zhuǎn)速度不能無(wú)限提高。HDD的平均延遲基本都是毫秒級(jí)的。固態(tài)硬盤(pán)(solid state drive, SSD)使用集成電路作為存儲(chǔ)介質(zhì),受益于半導(dǎo)體工藝的發(fā)展,延遲可以達(dá)到微秒的量級(jí)[2]?,F(xiàn)在的NVMe SSD可以達(dá)到幾十微秒的延遲?;?D XPoint材料的存儲(chǔ)設(shè)備擁有更低的延遲,填補(bǔ)了SSD和內(nèi)存之間的差距,其延遲達(dá)到微秒級(jí)[2]。
傳統(tǒng)的跨節(jié)點(diǎn)數(shù)據(jù)通路中,數(shù)據(jù)傳輸都要經(jīng)過(guò)內(nèi)存。數(shù)據(jù)一開(kāi)始在遠(yuǎn)程主機(jī)的內(nèi)存中,中央處理器(central processing unit, CPU)設(shè)置網(wǎng)絡(luò)接口控制器(network interface controller, NIC)的直接存儲(chǔ)器訪問(wèn)(direct memory access, DMA),由DMA把數(shù)據(jù)發(fā)送到網(wǎng)絡(luò)上。本地的NIC從網(wǎng)絡(luò)收到數(shù)據(jù),數(shù)據(jù)經(jīng)過(guò)DMA的搬運(yùn),保存到內(nèi)存中。然后CPU再控制存儲(chǔ)設(shè)備的DMA,把數(shù)據(jù)寫(xiě)入本地的存儲(chǔ)設(shè)備。隨著存儲(chǔ)技術(shù)的發(fā)展,存儲(chǔ)設(shè)備的延遲已經(jīng)從原來(lái)的毫秒級(jí)變?yōu)榱爽F(xiàn)在的微秒級(jí),數(shù)據(jù)在數(shù)據(jù)通路上延遲在整個(gè)傳輸延遲中的占比會(huì)大大增加,原來(lái)的傳輸路徑可能會(huì)導(dǎo)致額外的傳輸開(kāi)銷(xiāo)。
NoR技術(shù)(NVMe over RDMA)[3]通過(guò)改變傳統(tǒng)的數(shù)據(jù)傳輸通路優(yōu)化延遲。本地網(wǎng)卡從遠(yuǎn)程主機(jī)接收到的數(shù)據(jù)不再寫(xiě)入內(nèi)存,直接通過(guò)PCIe[4]總線寫(xiě)入本地的PCIe SSD。通信路徑的改變使得傳輸延遲從12 μs縮減到了7 μs??s短后的通信路徑繞過(guò)了CPU,但也失去了對(duì)數(shù)據(jù)的處理能力。數(shù)據(jù)直接寫(xiě)入存儲(chǔ)只能滿(mǎn)足應(yīng)用,很多其他應(yīng)用都需要對(duì)數(shù)據(jù)進(jìn)行一些處理,NoR技術(shù)即使是很簡(jiǎn)單的處理都無(wú)法完成。而且,只有存儲(chǔ)設(shè)備是非易失性隨機(jī)訪問(wèn)存儲(chǔ)器(non-volatile random access memory, NVRAM)或隨機(jī)存取存儲(chǔ)器(random access memory, RAM)時(shí),遠(yuǎn)程直接數(shù)據(jù)存取(remote direct memory access, RDMA)網(wǎng)卡才能直接給存儲(chǔ)設(shè)備寫(xiě)入數(shù)據(jù)。NVRAM存儲(chǔ)設(shè)備雖然擁有接近RAM的性能,同時(shí)造價(jià)成本也很高,而性?xún)r(jià)比較高的且真正大量使用的SSD采用的是NAND Flash介質(zhì),屬于塊設(shè)備,無(wú)法通過(guò)RDMA協(xié)議直接寫(xiě)入數(shù)據(jù)。如果希望能寫(xiě)入塊設(shè)備,那么數(shù)據(jù)就需要經(jīng)過(guò)閃存轉(zhuǎn)換層(flash translation layer, FTL)的處理。
由于機(jī)械硬盤(pán)的高性?xún)r(jià)比,目前依然作為主流的存儲(chǔ)設(shè)備使用。然而機(jī)械硬盤(pán)的隨機(jī)延遲很高,為了充分發(fā)揮機(jī)械硬盤(pán)的性能,將隨機(jī)讀寫(xiě)組織成順序讀寫(xiě)作為主要優(yōu)化方式。但是大數(shù)據(jù)的數(shù)據(jù)形式多樣,數(shù)據(jù)的組織有可能很復(fù)雜,難以組織成順序的讀寫(xiě)。RAMCloud[5](內(nèi)存云存儲(chǔ))把大數(shù)據(jù)應(yīng)用所需求的數(shù)據(jù)全部存放在內(nèi)存中,完全可以滿(mǎn)足大數(shù)據(jù)分析的需求。但是RAMCloud的成本高昂,且由于持久化問(wèn)題,還需要額外的成本和機(jī)制用于保障可靠性。機(jī)械硬盤(pán)和RAMCloud之間的性能和成本落差太大,SSD具有介于內(nèi)存和機(jī)械硬盤(pán)之間的性能和成本。隨著3D XPoint技術(shù)的推出,SSD擁有更高的存儲(chǔ)密度和對(duì)隨機(jī)高并發(fā)的支持。如果SSD的性能可以滿(mǎn)足大數(shù)據(jù)分析的要求,可以有遠(yuǎn)小于RAMCloud的成本以及集群規(guī)模。
NoSQL數(shù)據(jù)庫(kù)在大數(shù)據(jù)應(yīng)用中有著很重要的地位,根據(jù)用戶(hù)需求,弱化了SQL數(shù)據(jù)庫(kù)的一些要求以滿(mǎn)足大數(shù)據(jù)應(yīng)用的場(chǎng)景。key-value存儲(chǔ)是NoSQL數(shù)據(jù)庫(kù)的一種典型案例,只保存最簡(jiǎn)單的key和value之間的映射。Redis[6]和Amazon的Dynamo[7]都是key-value存儲(chǔ)系統(tǒng)的著名實(shí)例。本文的另一個(gè)重點(diǎn)就是嘗試將SSD應(yīng)用于大數(shù)據(jù)應(yīng)用,為大數(shù)據(jù)應(yīng)用提供一種存儲(chǔ)解決方案。
本文設(shè)計(jì)了面向網(wǎng)絡(luò)與存儲(chǔ)的融合設(shè)備模型用戶(hù)級(jí)融合I/O(unity I/O in user space, UIO),并加入輔助計(jì)算功能擴(kuò)展其適用場(chǎng)景。本文的主要工作和貢獻(xiàn)包括:
(1) 提出了一種融合存儲(chǔ)和網(wǎng)絡(luò)功能的UIO設(shè)備模型。UIO設(shè)備在同一種設(shè)備中融合了存儲(chǔ)和網(wǎng)絡(luò)功能,通過(guò)讓多個(gè)功能模塊共享設(shè)備中的內(nèi)存和數(shù)據(jù)通路以簡(jiǎn)化數(shù)據(jù)的傳輸路徑,降低數(shù)據(jù)的傳輸延遲。
(2) 設(shè)計(jì)了基于UIO設(shè)備模型的輔助計(jì)算模塊。通過(guò)在設(shè)備中加入輔助計(jì)算功能實(shí)現(xiàn)數(shù)據(jù)處理,并把輔助計(jì)算模塊分為處理設(shè)備間數(shù)據(jù)分布和存儲(chǔ)介質(zhì)格式轉(zhuǎn)換2個(gè)部分。通過(guò)與可編程硬件的結(jié)合,可以讓用戶(hù)定制輔助計(jì)算模塊,提高UIO設(shè)備的處理效率,擴(kuò)展其應(yīng)用場(chǎng)景。
(3) 實(shí)現(xiàn)了與key-value存儲(chǔ)系統(tǒng)相結(jié)合的UIO設(shè)備模擬器。參照key-value存儲(chǔ)系統(tǒng)設(shè)計(jì)了UTL和GME等各個(gè)模塊,讓用戶(hù)可以通過(guò)put、get指令操作設(shè)備。在最終測(cè)試中與傳統(tǒng)數(shù)據(jù)通路相比,遠(yuǎn)程put減少8.2%延遲,遠(yuǎn)程get減少11%延遲,本地put增加0.9%延遲,本地get增加2.7%延遲的效果。
隨著硬件技術(shù)的發(fā)展,已經(jīng)有了高速低延遲的存儲(chǔ)設(shè)備N(xiāo)VMe SSD。這種具有低延遲特性的存儲(chǔ)設(shè)備的出現(xiàn),使得傳統(tǒng)的硬件結(jié)構(gòu)不再適合所有場(chǎng)景,反而成為了系統(tǒng)性能進(jìn)步提升的瓶頸。
1.1.1 SSD
SSD使用半導(dǎo)體作為存儲(chǔ)介質(zhì),包括DRAM、NOR Flash、NAND Flash等。現(xiàn)在比較常用的是NAND Flash作為存儲(chǔ)介質(zhì)的SSD。NAND Flash的數(shù)據(jù)由浮柵單元存儲(chǔ),每個(gè)單元根據(jù)存儲(chǔ)介質(zhì)的不同(SLC, MLC, TLC)可以存儲(chǔ)1、2或3個(gè)bits。由浮柵單元組成邏輯頁(yè),邏輯頁(yè)組成邏輯塊。一個(gè)頁(yè)由4 kB數(shù)據(jù)存儲(chǔ)空間和128BECC校驗(yàn)數(shù)據(jù)的存儲(chǔ)空間組成,64個(gè)頁(yè)又組成了一個(gè)塊。頁(yè)是NAND Flash中最小的讀寫(xiě)尋址單元,塊是NANDFlash中最小的可擦除單元??梢噪S意讀取頁(yè)中的數(shù)據(jù)或者向空白的頁(yè)寫(xiě)入數(shù)據(jù),但是不能改寫(xiě)已經(jīng)寫(xiě)入頁(yè)中的數(shù)據(jù),如果改寫(xiě)需要將整個(gè)塊的數(shù)據(jù)擦除,然后才能重新寫(xiě)入新的數(shù)據(jù)。
NAND Flash[8]的這種讀寫(xiě)機(jī)制導(dǎo)致其讀寫(xiě)接口不能使用常見(jiàn)的讀(Read)和寫(xiě)(Write)接口,在讀、寫(xiě)之外還需要加入擦除(Erase)功能。在Flash和傳統(tǒng)接口之間需要添加一個(gè)轉(zhuǎn)換層FTL[9,10],位于SSD的Host Interface和NAND Interface之間,負(fù)責(zé)2種接口之間的轉(zhuǎn)換。FTL主要負(fù)責(zé)的功能有地址映射、磨損均衡、垃圾回收、壞塊管理等。地址映射為主機(jī)使用邏輯地址定位數(shù)據(jù),由FTL完成從邏輯地址到物理地址的映射。當(dāng)數(shù)據(jù)修改時(shí),把數(shù)據(jù)寫(xiě)到一個(gè)新的頁(yè)上并修改FTL中記錄的地址映射,以避免多余的數(shù)據(jù)讀寫(xiě)。磨損均衡為Flash中每個(gè)存儲(chǔ)單元的可寫(xiě)入次數(shù)是有限的,為了延長(zhǎng)整個(gè)設(shè)備的使用壽命,盡量保證每個(gè)單元的寫(xiě)入次數(shù)均勻。FTL記錄各個(gè)塊的剩余壽命,盡量使用壽命長(zhǎng)的塊。同時(shí),也會(huì)把一些存儲(chǔ)在剩余壽命比較長(zhǎng)的塊中但是不經(jīng)常改動(dòng)的數(shù)據(jù)搬移到剩余壽命較短的塊中。垃圾回收是在NAND Flash中,以塊為單位擦除,失效的頁(yè)空間不會(huì)立刻釋放。而垃圾回收負(fù)責(zé)釋放失效的頁(yè),保證空間利用率。它會(huì)把一個(gè)塊中還有效的頁(yè)復(fù)制到其他塊中,然后擦除整個(gè)塊。壞塊管理會(huì)記錄下已經(jīng)無(wú)法使用的塊,在寫(xiě)入數(shù)據(jù)時(shí)避開(kāi)。
1.1.2 NVMe協(xié)議
SSD中除了存儲(chǔ)介質(zhì)和控制器還有一個(gè)關(guān)鍵的組成部分就是主機(jī)接口。以Intel為代表的廠商聯(lián)合推出了專(zhuān)為PCIe SSD設(shè)計(jì)的協(xié)議NVMe[11]。NVMe協(xié)議專(zhuān)為SSD設(shè)計(jì),最大支持64 k個(gè)隊(duì)列,每個(gè)隊(duì)列可以容納64 k條指令,使用多隊(duì)列和doorbell的方式讀寫(xiě)指令,不需要對(duì)隊(duì)列加鎖,可以充分發(fā)揮高性能SSD設(shè)備的性能。PCIe接口解決了SSD主機(jī)接口的硬件通路瓶頸問(wèn)題,NVMe協(xié)議解決了SSD主機(jī)接口的軟件協(xié)議瓶頸問(wèn)題。
NVMe協(xié)議中的隊(duì)列分為Admin Queue和I/O Queue。每類(lèi)隊(duì)列又分為提交隊(duì)列(submission queue,SQ)和完成隊(duì)列(completion queue,CQ)。Admin Queue負(fù)責(zé)對(duì)設(shè)備的管理,完成創(chuàng)建刪除隊(duì)列、設(shè)置參數(shù)、查詢(xún)?nèi)罩镜裙ぷ?,I/O Queue負(fù)責(zé)具體的傳輸指令,完成Read、Write、刷回(Flush)等操作。SQ用于主機(jī)向設(shè)備發(fā)送指令,CQ用于設(shè)備向主機(jī)發(fā)送指令的返回結(jié)果。一個(gè)CQ可以匹配多個(gè)SQ,通過(guò)SQ和CQ的配合完成對(duì)設(shè)備的操作。
1.1.3 RDMA網(wǎng)卡
以太網(wǎng)網(wǎng)卡在接收數(shù)據(jù)時(shí),數(shù)據(jù)必須經(jīng)過(guò)系統(tǒng)的處理才能提供給需要這個(gè)數(shù)據(jù)的應(yīng)用。這種處理增加數(shù)據(jù)傳輸延遲的同時(shí)也增加了CPU的負(fù)擔(dān),在網(wǎng)卡的性能越來(lái)越高的同時(shí),對(duì)CPU的性能也提出了挑戰(zhàn)。
基于解決數(shù)據(jù)在內(nèi)存和設(shè)備之間的數(shù)據(jù)傳輸,并減輕CPU負(fù)擔(dān)的DMA機(jī)制,RDMA被提出并用于解決網(wǎng)絡(luò)傳輸?shù)膯?wèn)題[12-17]。RDMA通過(guò)網(wǎng)絡(luò)直接把數(shù)據(jù)傳入主機(jī)的用戶(hù)空間,不再需要內(nèi)核參與,提高了網(wǎng)絡(luò)傳輸性能,降低了CPU的處理負(fù)擔(dān)。在RDMA的Infiniband網(wǎng)卡中,具有和NVMe協(xié)議中類(lèi)似的隊(duì)列結(jié)構(gòu),其中有Send Queue,Receive Queue和Completion Queue。Infiniband網(wǎng)卡的設(shè)計(jì)目的就是為了提高網(wǎng)絡(luò)性能降低傳輸延遲,使用的場(chǎng)景通常也是對(duì)網(wǎng)絡(luò)有著很高要求的應(yīng)用,同時(shí)也需要高性能的隊(duì)列結(jié)構(gòu)避免在處理I/O請(qǐng)求時(shí)成為瓶頸。
數(shù)據(jù)在不同設(shè)備之間傳輸所消耗的時(shí)間一直是研究者們盡力減少的,如果一種設(shè)備可以同時(shí)完成2種工作,那么數(shù)據(jù)只要在設(shè)備內(nèi)部流動(dòng),不需要跨設(shè)備的傳輸。針對(duì)不同的設(shè)備類(lèi)型和不同的使用場(chǎng)景,已經(jīng)有了一些通過(guò)設(shè)備融合優(yōu)化系統(tǒng)性能的研究。
1.2.1 存儲(chǔ)和計(jì)算的融合
XSD(accelerator SSD)[18]通過(guò)在SSD中加入嵌入式圖形處理器(graphics processing unit, GPU)以提供計(jì)算功能,并為用戶(hù)提供了易用的Map-Reduce[19]接口。XSD在SSD中插入了嵌入式GPU,和SSD原有的嵌入式CPU共享內(nèi)存空間。XSD通過(guò)流水化來(lái)避免數(shù)據(jù)拷貝時(shí)間的浪費(fèi)。由于Flash控制器和GPU是共享內(nèi)存的,F(xiàn)lash向動(dòng)態(tài)隨機(jī)存取存儲(chǔ)器(dynamic random access memory, DRAM)寫(xiě)入數(shù)據(jù)的同時(shí)GPU也在從DRAM中復(fù)制數(shù)據(jù)進(jìn)行計(jì)算再把數(shù)據(jù)寫(xiě)回DRAM。XSD通過(guò)流水化避免了GPU對(duì)數(shù)據(jù)的等待問(wèn)題,充分利用了GPU。XSD通過(guò)在SSD內(nèi)使用嵌入式GPU加速計(jì)算,通過(guò)計(jì)算的流水化充分利用了SSD和GPU的性能,通過(guò)采用Map-Reduce編程框架提供簡(jiǎn)單高效的設(shè)備使用接口。雖然在SSD中加入計(jì)算設(shè)備可以有效減少設(shè)備等待數(shù)據(jù)傳輸?shù)拈_(kāi)銷(xiāo),但是因?yàn)榍度胧皆O(shè)備自身性能問(wèn)題,其性能提升能力還是有所不足的。
1.2.2 存儲(chǔ)、網(wǎng)絡(luò)和計(jì)算設(shè)備的融合
BlueDBM[20]是具有Flash存儲(chǔ)系統(tǒng)、存儲(chǔ)端計(jì)算引擎和網(wǎng)絡(luò)功能的PCIe設(shè)備。其中,F(xiàn)lash存儲(chǔ)系統(tǒng)直接開(kāi)放原始的flash接口(也就是不使用FTL層),由系統(tǒng)層管理數(shù)據(jù)。BlueDBM通過(guò)提供多種軟件接口(文件系統(tǒng)接口、塊設(shè)備接口和加速器接口)以方便用戶(hù)對(duì)設(shè)備的使用。BlueDBM在圖遍歷測(cè)試的性能(ISP-F)雖然比使用DRAM的方案(H-DRAM)要差,但是當(dāng)數(shù)據(jù)只能部分裝入內(nèi)存時(shí)(50%F,30%F),BlueDBM的性能已經(jīng)足以替代DRAM。BlueDBM通過(guò)對(duì)Flash存儲(chǔ)介質(zhì)的直接控制和存儲(chǔ)端的計(jì)算能力在多個(gè)測(cè)試中取得了優(yōu)秀的結(jié)果。但是BlueDBM采用了使用固定配置文件的方式,不具有擴(kuò)展能力。雖然提供了多種Flash存儲(chǔ)的操作接口,但沒(méi)有提供操作設(shè)備的存儲(chǔ)、網(wǎng)絡(luò)和計(jì)算功能的統(tǒng)一接口,用戶(hù)需要十分了解BlueDBM的結(jié)構(gòu)才能使用。
1.2.3 存儲(chǔ)和網(wǎng)絡(luò)的融合
NVMe over Fabric[3]就是一種在共享NVMe SSD資源的同時(shí)盡量減少額外開(kāi)銷(xiāo)的方案。資源池化,可以讓多臺(tái)計(jì)算機(jī)共享存儲(chǔ)資源,提升擴(kuò)展性和資源的利用率,降低成本。NVMe over Fabric分離了NVMe設(shè)備的前后端,前后端之間通過(guò)RDMA網(wǎng)絡(luò)傳輸。前端可以把internet小型計(jì)算機(jī)接口(internet small computer interface, iSCSI)協(xié)議轉(zhuǎn)換為NVMe的協(xié)議,讓系統(tǒng)統(tǒng)一可以使用NVMe over Fabric。通過(guò)網(wǎng)絡(luò)可以很容易地?cái)U(kuò)展存儲(chǔ),想要更大存儲(chǔ)容量時(shí)只要添加存儲(chǔ)設(shè)備,不需要擴(kuò)展機(jī)群規(guī)模。同時(shí),因?yàn)镽DMA網(wǎng)絡(luò)有著低延遲,NVMe over Fabric對(duì)數(shù)據(jù)傳輸延遲的影響很小。測(cè)試表明,通過(guò)NVMe over Fabirc使用遠(yuǎn)程N(yùn)VMe設(shè)備時(shí),讀寫(xiě)的IOPS(input/output operations per second)幾乎不受影響,傳輸延遲的增加也低于8 μs。但是NVMe over Fabric只是對(duì)NVMe存儲(chǔ)的擴(kuò)展,缺少計(jì)算能力。NVMe over Fabric雖然可以改善主機(jī)讀寫(xiě)遠(yuǎn)程存儲(chǔ)時(shí)的延遲,但是在數(shù)據(jù)需要處理時(shí)仍然無(wú)法改善數(shù)據(jù)路徑冗余導(dǎo)致的浪費(fèi)。
在傳統(tǒng)計(jì)算機(jī)硬件中,存儲(chǔ)和網(wǎng)絡(luò)設(shè)備往往是獨(dú)立的2種設(shè)備,而且數(shù)據(jù)無(wú)法直接在這2種設(shè)備之間傳輸,必須經(jīng)過(guò)CPU和內(nèi)存。隨著硬件技術(shù)的發(fā)展,存儲(chǔ)設(shè)備和網(wǎng)絡(luò)設(shè)備的延遲越來(lái)越低,數(shù)據(jù)無(wú)法在設(shè)備之間直接傳輸導(dǎo)致的額外延遲在傳輸延遲中的占比也越來(lái)越高,這導(dǎo)致新式I/O設(shè)備無(wú)法充分發(fā)揮其性能。通過(guò)設(shè)備融合,讓同一設(shè)備具有存儲(chǔ)和網(wǎng)絡(luò)功能,設(shè)備內(nèi)部的存儲(chǔ)和網(wǎng)絡(luò)模塊可以直接通信,避免數(shù)據(jù)在通路上的性能損失,減少通信的延遲開(kāi)銷(xiāo),改善系統(tǒng)整體性能。
如圖1所示,UIO設(shè)備是插于PCIe卡槽的I/O設(shè)備,同時(shí)具有存儲(chǔ)設(shè)備和網(wǎng)絡(luò)設(shè)備的功能,為了提供一定的數(shù)據(jù)處理能力,UIO設(shè)備還具有輔助計(jì)算功能。與SSD和網(wǎng)卡一樣,UIO設(shè)備需要系統(tǒng)中的驅(qū)動(dòng)程序支持,由驅(qū)動(dòng)程序負(fù)責(zé)與設(shè)備的通信。
圖1 UIO設(shè)備在系統(tǒng)中的位置
如圖2所示,UIO設(shè)備中具有指令隊(duì)列、指令處理、DMA、DRAM、存儲(chǔ)模塊、輔助計(jì)算模塊和網(wǎng)絡(luò)模塊。
圖2 UIO設(shè)備模塊設(shè)計(jì)
指令隊(duì)列結(jié)構(gòu)NVMe SSD和RDMA網(wǎng)卡都是具有高吞吐量和低延遲的高性能I/O設(shè)備,這2種設(shè)備都使用了高性能的I/O指令隊(duì)列作為主機(jī)接口。UIO設(shè)備的設(shè)計(jì)目標(biāo)是解決高性能I/O設(shè)備的傳輸延遲問(wèn)題,為了支撐設(shè)備的高性能,采用了隊(duì)列結(jié)構(gòu)。基于并發(fā)性考慮,管理隊(duì)列為每個(gè)應(yīng)用建立獨(dú)立的指令隊(duì)列。管理隊(duì)列為不同的程序創(chuàng)建完隊(duì)列并分配好權(quán)限后,應(yīng)用有讀寫(xiě)需求時(shí)只需要向自己的隊(duì)列中寫(xiě)入指令即可。設(shè)備會(huì)從指令隊(duì)列的空間讀取指令,因?yàn)镮/O隊(duì)列的權(quán)限已經(jīng)由管理隊(duì)列設(shè)置好,可以由設(shè)備檢查指令是否符合該指令隊(duì)列的權(quán)限,而不需要內(nèi)核的處理。這為用戶(hù)級(jí)I/O和虛擬化提供了方便。
指令處理指令處理要完成2部分工作,一個(gè)是指令仲裁,一個(gè)是指令解析。UIO設(shè)備具有多對(duì)指令隊(duì)列,不同進(jìn)程使用設(shè)備時(shí)不必給隊(duì)列加鎖,每個(gè)進(jìn)程都可以自由地給設(shè)備發(fā)送指令。設(shè)備上有相應(yīng)的模塊來(lái)處理多個(gè)指令隊(duì)列之間的協(xié)調(diào)調(diào)度問(wèn)題,這個(gè)功能就是指令仲裁。指令仲裁會(huì)決定設(shè)備執(zhí)行的下一條指令是什么。執(zhí)行的順序通常由隊(duì)列的優(yōu)先級(jí)決定。指令解析會(huì)把指令翻譯成設(shè)備內(nèi)部模塊的控制信息,而設(shè)備的其余模塊才是真正完成數(shù)據(jù)傳輸工作的部分。
DMA設(shè)備在解析完指令后,執(zhí)行對(duì)應(yīng)的數(shù)據(jù)傳輸,即主機(jī)和設(shè)備之間的數(shù)據(jù)傳輸。UIO中DMA主要負(fù)責(zé)把主機(jī)中數(shù)據(jù)傳輸?shù)紻RAM中,而數(shù)據(jù)從設(shè)備到主機(jī)的傳輸會(huì)根據(jù)實(shí)際情況由不同的模塊完成。
DRAMUIO中的DRAM有2個(gè)作用,一個(gè)是保存設(shè)備運(yùn)行時(shí)必要的信息,一個(gè)是作為數(shù)據(jù)傳輸?shù)木彺婧途彌_。一般的存儲(chǔ)設(shè)備,讀寫(xiě)速度和延遲都是不一致的,F(xiàn)lash介質(zhì)的存儲(chǔ)設(shè)備還存在寫(xiě)放大的問(wèn)題,F(xiàn)TL正在執(zhí)行的一些任務(wù)(例如靜態(tài)磨損均衡和垃圾回收)也會(huì)導(dǎo)致讀寫(xiě)時(shí)間出現(xiàn)較大波動(dòng)。為了提供更好的設(shè)備性能,設(shè)備中的DRAM可以作為讀寫(xiě)的緩存。UIO中網(wǎng)絡(luò)傳輸?shù)皆O(shè)備中的數(shù)據(jù),也需要一些內(nèi)存空間進(jìn)行緩沖,平衡存儲(chǔ)模塊和網(wǎng)絡(luò)模塊讀寫(xiě)速度的差異。
在UIO設(shè)備中,需要具備存儲(chǔ)、網(wǎng)絡(luò)和輔助計(jì)算3種功能,如何使用這3種模塊是提供高性能的關(guān)鍵問(wèn)題。
2.2.1 模型分析
基于獨(dú)立設(shè)備接口的指令接口用戶(hù)需要控制各個(gè)模塊對(duì)數(shù)據(jù)的處理,以及數(shù)據(jù)在各個(gè)模塊之間的傳輸。用戶(hù)使用設(shè)備的自由度高,通過(guò)精心設(shè)計(jì)的指令可以充分發(fā)揮設(shè)備的性能。但是,這種方案在實(shí)際使用中會(huì)有很大的局限。首先,處理器的性能受功耗限制,在I/O設(shè)備中嵌入的處理器性能有限。如果向用戶(hù)提供全功能的通用計(jì)算處理器,處理器的性能可能無(wú)法匹配高速I(mǎi)/O設(shè)備的性能,反而成為性能瓶頸,帶來(lái)過(guò)多的性能損失。其次是I/O設(shè)備的接口復(fù)雜性。對(duì)Flash的讀寫(xiě)不能使用傳統(tǒng)的Read和Write原語(yǔ),而要使用編程(Program)、Read和Erase的原語(yǔ)進(jìn)行讀寫(xiě)。SSD中通常用FTL層進(jìn)行這2種接口的轉(zhuǎn)換。如果向用戶(hù)開(kāi)放Flash的原始接口,那么FTL負(fù)責(zé)的功能都需要用戶(hù)來(lái)完成。這會(huì)極大提高用戶(hù)的使用難度,用戶(hù)除了要熟悉Flash的接口還要進(jìn)行復(fù)雜的性能優(yōu)化,難以發(fā)揮高性能存儲(chǔ)的能力[21-27]。
基于需求抽象分析的統(tǒng)一指令接口UIO設(shè)備采用的方案是抽象出用戶(hù)需求,根據(jù)用戶(hù)需求設(shè)計(jì)專(zhuān)用設(shè)備,向用戶(hù)提供統(tǒng)一的指令接口,用戶(hù)通過(guò)使用統(tǒng)一的指令就可以完成對(duì)設(shè)備全部功能的操作。這種方案的缺點(diǎn)顯而易見(jiàn),設(shè)備的功能受限,只能在特定場(chǎng)景下使用。但是這一缺點(diǎn)可以通過(guò)抽象用戶(hù)需求彌補(bǔ)??梢酝ㄟ^(guò)分析用戶(hù)使用較多的場(chǎng)景,把某一類(lèi)用戶(hù)的需求提取出來(lái),然后制作設(shè)備專(zhuān)門(mén)用于滿(mǎn)足這類(lèi)用戶(hù)的需求。雖然無(wú)法滿(mǎn)足所有用戶(hù)的需求,但是通過(guò)抽象出多種用戶(hù)的需求也足以覆蓋大部分用戶(hù)。
統(tǒng)一的用戶(hù)指令使用簡(jiǎn)單,通過(guò)抽象用戶(hù)需求,可以向用戶(hù)提供具有高級(jí)語(yǔ)義的接口,完全屏蔽設(shè)備實(shí)現(xiàn)的具體細(xì)節(jié)。甚至可以根據(jù)為用戶(hù)提供的功能深度定制底層模塊的邏輯。如圖3所示,移除了原有設(shè)計(jì)中的輔助計(jì)算模塊,改為統(tǒng)一轉(zhuǎn)換層(unity translation layer, UTL)模塊和全局信息管理引擎(global management engine, GME)模塊。UTL模塊和GME模塊都是可編程模塊,可以根據(jù)用戶(hù)需求寫(xiě)入不同的處理邏輯。其中,UTL模塊負(fù)責(zé)讀寫(xiě)存儲(chǔ)介質(zhì),GME負(fù)責(zé)分離本地和遠(yuǎn)程的傳輸。
圖3 UIO模塊設(shè)計(jì)專(zhuān)用方案
2.2.2 UTL模塊
UTL模塊用于取代SSD中的FTL模塊,負(fù)責(zé)實(shí)際的存儲(chǔ)介質(zhì)的讀寫(xiě)。UTL把用戶(hù)對(duì)設(shè)備的操作接口轉(zhuǎn)換為對(duì)Flash介質(zhì)的Program、Read和Erase接口,UTL提供可編程的接口。UIO針對(duì)抽象出來(lái)的用戶(hù)需求,完成特定類(lèi)型的操作,針對(duì)Flash存儲(chǔ)介質(zhì)的特點(diǎn),完成用戶(hù)定義接口到flash介質(zhì)接口的高效轉(zhuǎn)換。
2.2.3 GME模塊
GME模塊負(fù)責(zé)多個(gè)設(shè)備之間的通信,通過(guò)增加設(shè)備的數(shù)量進(jìn)行擴(kuò)展,通過(guò)多個(gè)UIO設(shè)備的協(xié)同工作,共享存儲(chǔ)空間,擴(kuò)展各UIO設(shè)備的性能。
如圖4所示,把多個(gè)設(shè)備映射到一個(gè)全局空間中。用戶(hù)通過(guò)本地設(shè)備的接口就可以透明地操作全局空間,而不必感知到其他設(shè)備的存在。當(dāng)系統(tǒng)中增加設(shè)備時(shí),用戶(hù)看到的是全局空間的擴(kuò)展。GME控制數(shù)據(jù)的分布,并根據(jù)數(shù)據(jù)的分布規(guī)則把數(shù)據(jù)發(fā)送到相應(yīng)的設(shè)備。如果是本地的數(shù)據(jù)就交給UTL模塊處理,由UTL模塊寫(xiě)入本地的存儲(chǔ)介質(zhì);如果是遠(yuǎn)程的數(shù)據(jù)就通過(guò)網(wǎng)絡(luò)模塊發(fā)送到目標(biāo)設(shè)備,由目標(biāo)設(shè)備寫(xiě)入存儲(chǔ)。
圖4 UIO設(shè)備多機(jī)模型
2.3.1 key-value存儲(chǔ)
在key-value數(shù)據(jù)庫(kù)中,哈希存儲(chǔ)方式把KV對(duì)組成的記錄順序?qū)懭氪鎯?chǔ)介質(zhì),在內(nèi)存中建立從key到記錄地址的映射。在讀取時(shí)就根據(jù)映射地址讀??;修改時(shí)寫(xiě)入一條新的記錄,然后修改內(nèi)存中映射的地址;刪除時(shí)并不刪除實(shí)際的記錄,而是寫(xiě)入一條代表已刪除的記錄。為了支持更好的擴(kuò)展性和并發(fā)性,在UIO中,可以進(jìn)行2次哈希存儲(chǔ),一次由GME進(jìn)行,把數(shù)據(jù)分布到不同的設(shè)備上,一次由UTL快速定位數(shù)據(jù)在存儲(chǔ)介質(zhì)中的位置。哈希存儲(chǔ)雖然實(shí)現(xiàn)簡(jiǎn)單,查找效率高,但是只能查找單條記錄,如果想查找一個(gè)范圍內(nèi)的數(shù)據(jù)效果比較差,此時(shí)需要考慮順序分布的存儲(chǔ)方式。
如圖5所示,順序分布把key分為多個(gè)范圍,不同范圍的數(shù)據(jù)組成不同的子表,Root表記錄每個(gè)子表存儲(chǔ)在哪個(gè)節(jié)點(diǎn)中。在UIO設(shè)備中,可以由GME記錄每個(gè)子表的數(shù)據(jù)范圍和節(jié)點(diǎn)信息,在查找范圍時(shí)由GME把大的范圍轉(zhuǎn)換為對(duì)多個(gè)子表的查詢(xún),UTL則負(fù)責(zé)一個(gè)子表,根據(jù)查詢(xún)返回結(jié)果。
圖5 順序分布
2.3.2 圖片檢索
圖片檢索功能就是向UIO設(shè)備發(fā)送圖片后,UIO設(shè)備從存儲(chǔ)中檢索出相似的圖片并發(fā)送給主機(jī)。其中,GME模塊負(fù)責(zé)把圖片分發(fā)給本地UTL模塊和其他遠(yuǎn)程設(shè)備。所有UIO設(shè)備中的UTL模塊收到圖片后就會(huì)讀出存儲(chǔ)中的圖片,并進(jìn)行比對(duì),并把相似的圖片發(fā)送給源設(shè)備。源設(shè)備收到圖片后會(huì)發(fā)送到主機(jī)。與傳統(tǒng)方案中數(shù)據(jù)需要在存儲(chǔ)設(shè)備和CPU或GPU通信相比,由專(zhuān)用的硬件模塊處理圖像可以取得更高的運(yùn)算效率。在存儲(chǔ)設(shè)備中的比對(duì)使得大部分?jǐn)?shù)據(jù)都不需要從設(shè)備傳輸?shù)街鳈C(jī),只需要傳輸比對(duì)后相似度高的圖片,設(shè)備和主機(jī)間的帶寬可以用來(lái)傳輸遠(yuǎn)程設(shè)備傳輸過(guò)來(lái)的圖片,避免了帶寬的浪費(fèi)。
2.3.3 kNN算法
最鄰近結(jié)點(diǎn)(k-nearest neighbor,kNN)算法是一種常用的機(jī)器學(xué)習(xí)算法,通過(guò)計(jì)算未知數(shù)據(jù)和已知數(shù)據(jù)的“距離”來(lái)預(yù)測(cè)未知數(shù)據(jù)的類(lèi)別。kNN算法在預(yù)測(cè)時(shí)會(huì)取出已知數(shù)據(jù)中和待預(yù)測(cè)數(shù)據(jù)最接近的前k項(xiàng)數(shù)據(jù)作為預(yù)測(cè)的樣本,這也是kNN算法中k的含義。UIO在處理kNN算法時(shí),存儲(chǔ)介質(zhì)中存儲(chǔ)所有的樣本。在主機(jī)向設(shè)備發(fā)送待預(yù)測(cè)樣本后,GME模塊把樣本發(fā)送給所有設(shè)備。所有設(shè)備的UTL模塊接收到樣本后,會(huì)讀出存儲(chǔ)介質(zhì)中的樣本并計(jì)算距離值,在計(jì)算的過(guò)程中保存最接近的前k個(gè)值。全部的值比對(duì)完成后設(shè)備會(huì)把前k個(gè)最接近的結(jié)果發(fā)送給源設(shè)備,源設(shè)備的GME模塊在收集到所有設(shè)備的返回結(jié)果后會(huì)進(jìn)行排序并選出其中的前k個(gè)值預(yù)測(cè)分類(lèi),再把分類(lèi)結(jié)果發(fā)送給主機(jī)。
為了驗(yàn)證UIO設(shè)備的設(shè)計(jì)是否有效,并為將來(lái)UIO設(shè)備的相關(guān)研究提供驗(yàn)證平臺(tái),本文將實(shí)現(xiàn)UIO設(shè)備的模擬器。
如圖6所示,UIO設(shè)備模擬器的結(jié)構(gòu)依照UIO設(shè)備的基本結(jié)構(gòu)而設(shè)計(jì)。由指令隊(duì)列和控制寄存器共同組成設(shè)備接口。其中指令隊(duì)列分為Admin Queue和I/O Queue,每種Queue又由SQ和CQ組成。除了指令隊(duì)列,主機(jī)還需要一些寄存器為設(shè)備進(jìn)行初始化以及保持狀態(tài)信息。在實(shí)際UIO設(shè)備模擬器的實(shí)現(xiàn)中,本文選擇的目標(biāo)是實(shí)現(xiàn)采用key-value接口,使用put/get指令,GME模塊和FTL模塊都采用哈希分布。
圖6 UIO設(shè)備結(jié)構(gòu)圖
UIO設(shè)備模擬器是用戶(hù)態(tài)功能級(jí)的模擬器,目標(biāo)是驗(yàn)證UIO設(shè)備的模型是否有效。在UIO模擬器的設(shè)計(jì)中,首先進(jìn)行初始化工作,然后創(chuàng)建2個(gè)線程,一個(gè)模擬主機(jī)端,一個(gè)模擬設(shè)備端。主機(jī)端會(huì)接收來(lái)自控制臺(tái)的命令,并把用戶(hù)的命令轉(zhuǎn)換為相應(yīng)指令寫(xiě)入設(shè)備端的控制結(jié)構(gòu)。設(shè)備端則是根據(jù)控制結(jié)構(gòu)中的指令執(zhí)行實(shí)際的操作,從主機(jī)端復(fù)制數(shù)據(jù)或者向主機(jī)端寫(xiě)入數(shù)據(jù)并根據(jù)指令執(zhí)行情況提供返回結(jié)果。設(shè)備端啟動(dòng)后會(huì)創(chuàng)建出指令處理、DMA、GME、UTL和網(wǎng)絡(luò)通信(network communication, NET)一系列線程用于模擬UIO設(shè)備中的各個(gè)模塊??紤]各個(gè)模塊的運(yùn)行都是并行的,采用多線程來(lái)盡量接近真實(shí)的設(shè)備特性。
UIO的設(shè)備結(jié)構(gòu)主要借鑒了NVMe的設(shè)備接口設(shè)計(jì),并根據(jù)UIO設(shè)備的特性進(jìn)行了修改。
3.2.1 指令設(shè)計(jì)
在UIO中,本文設(shè)計(jì)了2種指令,Admin Command和IO Command。出于簡(jiǎn)化設(shè)計(jì)突出原理的目的,只設(shè)計(jì)了實(shí)現(xiàn)UIO最核心功能的指令。Admin Queue的4種操作就是創(chuàng)建和刪除SQ和CQ。需要注意的是,在創(chuàng)建SQ前應(yīng)該先創(chuàng)建SQ所對(duì)應(yīng)的CQ。如果先創(chuàng)建了SQ又向隊(duì)列中寫(xiě)入了指令,設(shè)備在處理完指令后找不到應(yīng)該寫(xiě)入返回結(jié)果的CQ就會(huì)導(dǎo)致未知的結(jié)果。IO Command只有put和get 2條。put提供key和value,表示把key的值更新為value。get提供key,表示讀出key存儲(chǔ)的值。
如表1所示,每一條指令有64個(gè)字節(jié)組成。其中,opcode用于指明要執(zhí)行的是哪條指令;cid是指令的表示,使用隊(duì)列的id加cid可以確定唯一的一條指令;nsid用于指明該條指令用于操作哪個(gè)namespace,為不同用戶(hù)和應(yīng)用的操作系統(tǒng)硬件級(jí)的隔離(在改版UIO中尚未實(shí)現(xiàn),只是預(yù)留接口);其余部分會(huì)根據(jù)指令的不同有不同含義或者是保留字段。
表1 指令格式
例如在Create IO Submission Queue的指令中,adr2用于保存隊(duì)列的起始地址;cdw10用于保存隊(duì)列大小和隊(duì)列id;cdw11中保存SQ對(duì)應(yīng)的用于放置返回結(jié)果的CQ的隊(duì)列id以及該SQ的優(yōu)先級(jí)。
而在put和get指令中,adr1用于存放key的地址,len1存放key的長(zhǎng)度,adr2用于存放value的地址,len2用于存放value的長(zhǎng)度(get指令中實(shí)際上是主機(jī)為get的返回值創(chuàng)建的緩沖區(qū)的地址以及緩沖區(qū)長(zhǎng)度)。
表2所示是CQ中返回項(xiàng)的格式。Command Specific是指令的返回結(jié)果,根據(jù)指令的不同也有所不同;SQ Identifier是發(fā)送該指令的SQ的id,SQ Head Pointer指明返回該指令時(shí),設(shè)備中維護(hù)的SQ的Head Doorbell指向的位置(在主機(jī)讀取到時(shí)設(shè)備中該值可能已被更新);Status Field返回指令執(zhí)行的基本信息,例如是否成功,是否可以繼續(xù)嘗試;P是Phase Tag,Phase Tag只有1位,用于指明該返回項(xiàng)是否已經(jīng)填寫(xiě)完成;Command Identifier就是該返回項(xiàng)對(duì)應(yīng)的指令的id,前面提到隊(duì)列id加指令id的
表2 CQ返回項(xiàng)格式
組合可以確定一條指令,也就是說(shuō),主機(jī)根據(jù)這2個(gè)id就可以知道完成的是哪條指令了。
3.2.2 BAR寄存器
基地址寄存器(base address register, BAR)解決的是最基本的主機(jī)與設(shè)備通信的問(wèn)題。主機(jī)所看到的BAR寄存器是內(nèi)存中的一段空間,主機(jī)通過(guò)讀寫(xiě)其中的數(shù)據(jù)實(shí)現(xiàn)對(duì)設(shè)備的控制。UIO設(shè)備的BAR寄存器參照了NVMe的設(shè)計(jì),主要使用了其中關(guān)于Admin Queue的AQA、ASQ、ACQ以及Doorbell部分的寄存器,如表3所示。
雖然主機(jī)和UIO設(shè)備的主要通信方式是通過(guò)指令隊(duì)列,但是這就需要知道指令隊(duì)列的地址。IO Queue的地址空間是由主機(jī)在內(nèi)存中申請(qǐng)并通過(guò)Admin Queue指令把地址提供給設(shè)備,由設(shè)備自行從主機(jī)內(nèi)存中獲取指令。這就需要主機(jī)和設(shè)備都統(tǒng)一預(yù)先知道Admin Queue的地址。而這個(gè)地址就是由BAR寄存器提供的。BAR寄存器中的ASQ和ACQ分別提供了Admin Submission Queue和Admin Completion Queue的起始地址。AQA則提供了Admin Queue的大小。之后的CQ0TDBL和CQ0HDBL等寄存器則分別提供了SQ的Tail Doorbell和CQ的Head Doorbell。Head和Tail Doorbell是2個(gè)指針,分別指出了指令隊(duì)列中存放有數(shù)據(jù)部分的起始和結(jié)束。
基于Queue的起始地址(Admin Queue的在BAR寄存器指出,IO Queue的由主機(jī)和設(shè)備分別自己維護(hù))和Doorbell,主機(jī)就可以完成對(duì)設(shè)備的控制,設(shè)備就可以獲得主機(jī)的指令,完成自己的工作了。
表3 Bar寄存器定義
3.3.1 指令仲裁
由于指令優(yōu)先級(jí)和UIO模擬器要驗(yàn)證的原理關(guān)聯(lián)不大,UIO模擬器中的指令隊(duì)列只使用了1級(jí)優(yōu)先級(jí),指令仲裁使用輪詢(xún)的方式從隊(duì)列中取指。
UIO中會(huì)為所有隊(duì)列建立一個(gè)鏈表,維護(hù)每個(gè)隊(duì)列的Head和Tail,每當(dāng)隊(duì)列創(chuàng)建時(shí)就加入該鏈表,隊(duì)列刪除時(shí)就從中釋放。指令仲裁通過(guò)檢查Head和Tail判斷隊(duì)列是否為空,如果隊(duì)列不為空就從隊(duì)列中取出Head所指向的指令并交給指令解釋器執(zhí)行。在取出一定條數(shù)的指令后,或者隊(duì)列為空時(shí),就通過(guò)next指針找到下一個(gè)隊(duì)列。
3.3.2 指令解釋器
指令解釋器首先根據(jù)取指的隊(duì)列id判斷是Admin Command還是IO Command。然后從指令中取出opcode字段,根據(jù)opcode判斷是哪條指令并根據(jù)該指令的字段解析其中有用的信息,并把這些信息發(fā)送給數(shù)據(jù)處理模塊。
在處理Admin Command的時(shí)候,因?yàn)椴簧婕皵?shù)據(jù)的傳輸,由指令解釋器執(zhí)行具體的指令。在創(chuàng)建隊(duì)列時(shí),指令解釋器會(huì)創(chuàng)建圖7中的隊(duì)列輪詢(xún)控制結(jié)構(gòu),并指向指令中給出的地址;而在刪除隊(duì)列時(shí),指令解釋器會(huì)釋放隊(duì)列的控制結(jié)構(gòu)。
圖7 UIO隊(duì)列輪詢(xún)結(jié)構(gòu)
UIO模擬器采用消息隊(duì)列模擬模塊間的通信,包括指令解釋器模塊向數(shù)據(jù)處理模塊發(fā)送的請(qǐng)求和數(shù)據(jù)處理模塊之間發(fā)送的請(qǐng)求。模塊間消息隊(duì)列只有請(qǐng)求項(xiàng)不設(shè)返回值,當(dāng)模塊處理指令成功或者失敗時(shí),會(huì)根據(jù)處理情況向Completion Queue填寫(xiě)返回信息以完成對(duì)指令的處理。
3.4.1 DMA模塊
在UIO模擬器中,DMA負(fù)責(zé)把數(shù)據(jù)從主機(jī)內(nèi)存中復(fù)制到設(shè)備的內(nèi)存中,以供后續(xù)其他模塊處理。當(dāng)指令是put時(shí),DMA會(huì)復(fù)制key和value;當(dāng)指令是get時(shí),DMA會(huì)復(fù)制key。
DMA將數(shù)據(jù)組織成如表4所示的記錄形式,以方便傳輸或者寫(xiě)入Flash顆粒。校驗(yàn)碼是由數(shù)據(jù)內(nèi)容計(jì)算出來(lái)的固定長(zhǎng)度的字段。因?yàn)镕lash存儲(chǔ)技術(shù)自身的缺陷,存儲(chǔ)單元中的數(shù)據(jù)過(guò)一段時(shí)間后可能會(huì)失效或者改變,通過(guò)錯(cuò)誤檢查和糾正(error correcting code, ECC)保證數(shù)據(jù)可以完整正確地讀出。在網(wǎng)絡(luò)傳輸和key-value數(shù)據(jù)庫(kù)中,一般也會(huì)加入校驗(yàn)字段來(lái)驗(yàn)證數(shù)據(jù)的有效性。
表4 記錄結(jié)構(gòu)示意圖
UIO模擬器中的DMA只負(fù)責(zé)從主機(jī)端讀取數(shù)據(jù)到設(shè)備DRAM中,從設(shè)備中讀取數(shù)據(jù)到主機(jī)端的工作則交給其他模塊完成。存儲(chǔ)介質(zhì)的寫(xiě)入速度或者向遠(yuǎn)程設(shè)備發(fā)送數(shù)據(jù)的速度都低于寫(xiě)入DRAM的速度,用DRAM作為緩存提高效率。但是從設(shè)備中讀取數(shù)據(jù)時(shí),可以由設(shè)備內(nèi)模塊直接向主機(jī)內(nèi)存?zhèn)鬏敗?/p>
3.4.2 GME模塊
GME負(fù)責(zé)把數(shù)據(jù)的讀寫(xiě)請(qǐng)求根據(jù)key把指令分配到不同的設(shè)備上。如圖8所示,GME模塊收到請(qǐng)求后會(huì)讀出其中的key,然后計(jì)算key的哈希值,并在映射表中查找該哈希值對(duì)應(yīng)的目標(biāo)服務(wù)器id。如果指令目標(biāo)是本地設(shè)備,就交給UTL模塊處理,如果指令目標(biāo)是遠(yuǎn)程設(shè)備就交給NET模塊處理。GME模塊中的映射表可以通過(guò)分布式協(xié)議獲取,也可以通過(guò)配置文件寫(xiě)入,UIO模擬器中是通過(guò)函數(shù)計(jì)算哈希值和目標(biāo)設(shè)備id之間的關(guān)系。
圖8 GME模塊原理示意圖
3.4.3 UTL模塊
在UIO模擬器中通過(guò)建立Flash顆粒的塊和頁(yè)2級(jí)來(lái)模擬Flash介質(zhì)的基本性質(zhì)。Flash顆粒中,頁(yè)只能被寫(xiě)入不能改寫(xiě),修改引起的拷貝復(fù)制導(dǎo)致寫(xiě)放大問(wèn)題。如圖9所示, UIO模擬器借鑒了鍵值存儲(chǔ)系統(tǒng)的處理方式,創(chuàng)建1條新的記錄,順序?qū)懙浆F(xiàn)在記錄的尾端把原有記錄視為失效。當(dāng)1個(gè)頁(yè)完整寫(xiě)入后只讀取不再改動(dòng)。塊是由頁(yè)組成的,當(dāng)1個(gè)塊中所有頁(yè)都被寫(xiě)入后會(huì)成為固定塊,不再發(fā)生改動(dòng)。
UIO提供key-value接口,UIO接收的指令不包含地址,UIO仿照FTL實(shí)現(xiàn)key到物理地址的映射。UTL會(huì)在DRAM中建立哈希映射表,哈希表通過(guò)key來(lái)索引value保存的具體位置,其中包括block id、page id、value位置和長(zhǎng)度。當(dāng)發(fā)生寫(xiě)請(qǐng)求時(shí),UTL就把記錄順序?qū)懭隖lash中,然后根據(jù)寫(xiě)入時(shí)的地址更新內(nèi)存中的哈希表;當(dāng)發(fā)生讀請(qǐng)求時(shí),先從哈希表中查詢(xún)到value的地址,然后再?gòu)腇lash中定位并讀出數(shù)據(jù)。當(dāng)請(qǐng)求是來(lái)自本地時(shí),UTL就可以直接把返回結(jié)果寫(xiě)入本地設(shè)備的Completion Queue并把數(shù)據(jù)寫(xiě)入主機(jī)內(nèi)存。當(dāng)請(qǐng)求是來(lái)自遠(yuǎn)程時(shí),UTL就把數(shù)據(jù)暫存在設(shè)備的內(nèi)存中,并給NET模塊發(fā)送請(qǐng)求,由NET模塊處理。
UTL對(duì)塊進(jìn)行定期掃描,進(jìn)行垃圾回收,提高空間利用率。UTL從頭到尾掃描塊,從中讀出每一條記錄的key,并把記錄地址和該key在哈希表中指向的地址進(jìn)行對(duì)比。如果是同一個(gè)地址說(shuō)明該記錄是有效的,UTL就把該記錄寫(xiě)入到活動(dòng)塊中繼續(xù)保留;如果該記錄的地址和哈希表中的不一致,說(shuō)明該記錄已經(jīng)失效,直接跳過(guò)即可,掃描完整個(gè)塊,該塊就可以擦除回收了。
圖9 UTL哈希表示意圖
3.4.4 NET模塊
NET模塊由2部分組成,分別負(fù)責(zé)發(fā)送、接收網(wǎng)絡(luò)請(qǐng)求。Send流程中會(huì)有4種情況,遠(yuǎn)程put請(qǐng)求、遠(yuǎn)程get請(qǐng)求、遠(yuǎn)程put回復(fù)、遠(yuǎn)程get回復(fù)。其中,遠(yuǎn)程put和get請(qǐng)求是來(lái)自GME的指令,GME根據(jù)key判斷指令目標(biāo)是遠(yuǎn)程設(shè)備時(shí),會(huì)向NET模塊發(fā)送指令并告知目標(biāo)設(shè)備id,由NET模塊負(fù)責(zé)發(fā)送。其中,put請(qǐng)求需要向遠(yuǎn)程設(shè)備發(fā)送key和value,get請(qǐng)求需要發(fā)送key。
遠(yuǎn)程put、get請(qǐng)求的接收,都接收到設(shè)備內(nèi)存中,由UTL模塊處理。遠(yuǎn)程設(shè)備把put和get請(qǐng)求處理完后會(huì)發(fā)送回復(fù),對(duì)于put的回復(fù)只要知道put指令執(zhí)行的狀態(tài)即可,獲得結(jié)果后向CQ填寫(xiě)返回結(jié)果這條指令就完成了。而遠(yuǎn)程get指令是有查詢(xún)結(jié)果的,設(shè)備接收到結(jié)果后還要復(fù)制給主機(jī),等復(fù)制結(jié)束后就可以填寫(xiě)返回結(jié)果了。
在主機(jī)寫(xiě)入指令后,指令仲裁把指令從指令隊(duì)列中取出并送入指令解釋器,指令解釋器解析指令后給DMA發(fā)送控制信號(hào),然后就由數(shù)據(jù)通路模塊執(zhí)行。
3.5.1 put指令
put指令,主機(jī)會(huì)提供key和value的地址和長(zhǎng)度,DMA根據(jù)地址和長(zhǎng)度分別從主機(jī)內(nèi)存中復(fù)制key和value的值到設(shè)備內(nèi)存中,并存儲(chǔ)成記錄的格式,然后向GME模塊發(fā)送信號(hào)。GME模塊會(huì)從設(shè)備內(nèi)存中讀出key,并計(jì)算key的哈希值,根據(jù)哈希值在內(nèi)存中的映射表查找目標(biāo)設(shè)備的id。
如果目標(biāo)設(shè)備是本地設(shè)備,那么GME模塊就向UTL模塊發(fā)送請(qǐng)求,UTL在收到請(qǐng)求后從設(shè)備內(nèi)存中讀出記錄并寫(xiě)入介質(zhì),并把寫(xiě)入到介質(zhì)中的地址存到設(shè)備內(nèi)存中的映射表。完成寫(xiě)入后,UTL模塊會(huì)向CQ填寫(xiě)完成信息。如果目標(biāo)設(shè)備是遠(yuǎn)程設(shè)備,則由NET模塊負(fù)責(zé)處理。NET模塊收到控制信號(hào)后會(huì)把內(nèi)存中的記錄分解為多個(gè)包并填寫(xiě)元數(shù)據(jù)以便于傳輸,然后向目標(biāo)設(shè)備依次發(fā)送數(shù)據(jù)包。目標(biāo)設(shè)備的NET模塊收到數(shù)據(jù)包會(huì)讀取數(shù)據(jù)包的opcode,如果判斷出是put請(qǐng)求就會(huì)依次接收包并重新組成記錄的格式,然后向UTL模塊發(fā)送信號(hào)。UTL模塊接收到信號(hào)后會(huì)把內(nèi)存中的記錄寫(xiě)入存儲(chǔ)介質(zhì)并修改內(nèi)存中的映射表,然后向NET模塊返回完成信息。NET收到完成信息后會(huì)發(fā)送到源設(shè)備,源設(shè)備的NET模塊收到完成信息后會(huì)向CQ填寫(xiě)完成信息。
3.5.2 get指令
get指令的過(guò)程和put指令的過(guò)程大體相似,這里只介紹其中有區(qū)別的部分。DMA在執(zhí)行g(shù)et指令時(shí)只會(huì)從內(nèi)存中復(fù)制key(因?yàn)橹噶钪袀鬟f的value地址是應(yīng)用申請(qǐng)好的緩沖區(qū)地址和長(zhǎng)度)。
UTL在收到信號(hào)后會(huì)先從映射表中查找key所對(duì)應(yīng)value在存儲(chǔ)介質(zhì)中的地址,根據(jù)這個(gè)地址找到value并復(fù)制到主機(jī)內(nèi)存(因?yàn)橹鳈C(jī)內(nèi)存的帶寬和延遲一般都優(yōu)于存儲(chǔ)設(shè)備,所以直接復(fù)制也不會(huì)有性能問(wèn)題還可以減少開(kāi)銷(xiāo)),然后填寫(xiě)返回信息。NET模塊在向遠(yuǎn)程設(shè)備發(fā)送信息時(shí)發(fā)送的只有key,遠(yuǎn)程設(shè)備在返回完成信息時(shí)還要發(fā)送查詢(xún)到的value的值。同樣,本地設(shè)備的NET模塊在接收到value的值后會(huì)直接復(fù)制到主機(jī)內(nèi)存中。
4.1.1 測(cè)試環(huán)境
UIO模擬器的測(cè)試是在一臺(tái)服務(wù)器上完成。服務(wù)器的配置如表5所示。UIO的測(cè)試采用在單臺(tái)服務(wù)器上運(yùn)行多個(gè)模擬器程序。由于程序之間通過(guò)Linux系統(tǒng)提供的消息隊(duì)列進(jìn)行通信,使用內(nèi)存模擬存儲(chǔ)介質(zhì),硬件只用到了CPU和內(nèi)存。
表5 測(cè)試環(huán)境參數(shù)表
4.1.2 測(cè)試方案
UIO的設(shè)計(jì)目的是減少遠(yuǎn)程數(shù)據(jù)傳輸在設(shè)備和內(nèi)存之間傳輸導(dǎo)致的額外延遲。為了進(jìn)行對(duì)比測(cè)試,在UIO模擬器添加了一種模式,讓UIO模擬器模擬傳統(tǒng)的數(shù)據(jù)通路,在接收到數(shù)據(jù)后復(fù)制到主機(jī)內(nèi)存中,再?gòu)闹鳈C(jī)內(nèi)存重新讀入設(shè)備,寫(xiě)入存儲(chǔ)介質(zhì)。除此之外,UIO模擬器在處理指令時(shí)會(huì)有一些額外開(kāi)銷(xiāo)。例如GME模塊會(huì)驗(yàn)證指令是發(fā)往本地還是遠(yuǎn)程,傳統(tǒng)存儲(chǔ)設(shè)備中所有指令都是寫(xiě)入本地存儲(chǔ),并沒(méi)有此項(xiàng)開(kāi)銷(xiāo)。所以用UIO模擬器模擬數(shù)據(jù)無(wú)需經(jīng)過(guò)GME模塊直接讀寫(xiě)UTL模塊的場(chǎng)景,測(cè)試UIO模擬器在本地模式下的額外開(kāi)銷(xiāo)。
在具體的測(cè)試中,會(huì)使用多種value長(zhǎng)度(從4B到16 kB)的指令,其中的key和value都會(huì)使用英文字母填充。
4.2.1 UIO模擬器與傳統(tǒng)數(shù)據(jù)通路對(duì)比
在圖10和圖11中,可以看出傳統(tǒng)通路的指令執(zhí)行延遲都高于UIO設(shè)備,根據(jù)指令長(zhǎng)度的不同會(huì)多出10~30 μs。延遲的增加主要是因?yàn)閿?shù)據(jù)復(fù)制和設(shè)備間的數(shù)據(jù)包導(dǎo)致,而傳統(tǒng)通路的數(shù)據(jù)復(fù)制次數(shù)多于UIO設(shè)備,所增加的延遲也高于UIO設(shè)備。put指令中,value的長(zhǎng)度越長(zhǎng)執(zhí)行延遲越長(zhǎng)與UIO模擬器的實(shí)現(xiàn)方式有關(guān),在使用put指令時(shí)因?yàn)樾枰蛟O(shè)備寫(xiě)入數(shù)據(jù),模擬器在實(shí)際運(yùn)行時(shí)需要向系統(tǒng)申請(qǐng)空間,所以越長(zhǎng)的指令執(zhí)行時(shí)間也越長(zhǎng)。但是這部分時(shí)間的增量在2種通路都是存在的,并不會(huì)影響結(jié)論。測(cè)試結(jié)果表明,UIO設(shè)備路徑與傳統(tǒng)數(shù)據(jù)通路相比,遠(yuǎn)程put減少8.2%延遲,遠(yuǎn)程get減少11%延遲。
圖10 UIO設(shè)備與傳統(tǒng)通路遠(yuǎn)程put指令延遲對(duì)比
圖11 UIO設(shè)備與傳統(tǒng)通路遠(yuǎn)程get指令延遲對(duì)比
4.2.2 UIO模擬器與本地?cái)?shù)據(jù)通路對(duì)比
對(duì)于本地put指令,可以看到有的指令是UIO的延遲更長(zhǎng),有的是UIO的延遲更短。大多數(shù)的數(shù)據(jù)差距都在2~3 μs內(nèi),差距在于UIO設(shè)備中需要額外經(jīng)過(guò)GME模塊計(jì)算目標(biāo)設(shè)備id,對(duì)于3 μs左右的延遲這種隨機(jī)波動(dòng)影響很大,因此UIO設(shè)備和傳統(tǒng)設(shè)備在運(yùn)行本地put指令時(shí)開(kāi)銷(xiāo)基本相當(dāng)。對(duì)于本地get指令,可以看到UIO設(shè)備的執(zhí)行延遲基本超過(guò)傳統(tǒng)通路,但是超過(guò)的幅度很小,基本在10 μs左右。如圖12和圖13所示,測(cè)試結(jié)果表明,UIO設(shè)備路徑與傳統(tǒng)數(shù)據(jù)通路相比,本地指令的差距基本不隨value的長(zhǎng)度變化,這是因?yàn)镚ME的操作是從設(shè)備內(nèi)存中讀取key,并計(jì)算key的Hash值,沒(méi)有復(fù)制數(shù)據(jù)的操作。在實(shí)際使用中key的長(zhǎng)度較小,所以Hash值的計(jì)算開(kāi)銷(xiāo)也不高,開(kāi)銷(xiāo)的變化通常也不大。
從4.2節(jié)中可以看出,UIO設(shè)備在執(zhí)行遠(yuǎn)程指令時(shí)延遲小于傳統(tǒng)通路,而在執(zhí)行本地指令時(shí)略微高于傳統(tǒng)通路。
圖12 UIO設(shè)備與傳統(tǒng)通路本地put指令延遲對(duì)比
對(duì)于遠(yuǎn)程指令,傳統(tǒng)通路中需要把指令從設(shè)備復(fù)制到主機(jī)中再?gòu)闹鳈C(jī)復(fù)制到設(shè)備中,相比UIO設(shè)備各個(gè)模塊可以共用內(nèi)存相比,增加了數(shù)據(jù)復(fù)制的開(kāi)銷(xiāo),這部分開(kāi)銷(xiāo)造成了傳統(tǒng)通路的額外延遲。而對(duì)于本地指令,UIO設(shè)備相比傳統(tǒng)通路增加了GME計(jì)算指令的目標(biāo)設(shè)備是本地設(shè)備還是遠(yuǎn)程設(shè)備的開(kāi)銷(xiāo),這部分計(jì)算主要是使用哈希函數(shù)計(jì)算哈希值,再根據(jù)哈希值查表,都是開(kāi)銷(xiāo)比較小的計(jì)算,所以相比傳統(tǒng)通路時(shí)間延遲增加并不顯著。
如果設(shè)UIO設(shè)備減少的遠(yuǎn)程指令開(kāi)銷(xiāo)比例是a,增加的本地指令開(kāi)銷(xiāo)比例是b,UIO設(shè)備有N塊,設(shè)備的能力都是相同的,哈希函數(shù)可以把數(shù)據(jù)均勻分布到N塊設(shè)備上,那么用戶(hù)的數(shù)據(jù)會(huì)有1/N在本地設(shè)備,(N-1)/N在遠(yuǎn)程設(shè)備,UIO設(shè)備相比傳統(tǒng)通路的開(kāi)銷(xiāo)比值是
(1)
現(xiàn)有系統(tǒng)中,數(shù)據(jù)發(fā)往遠(yuǎn)程計(jì)算機(jī)存儲(chǔ)設(shè)備的數(shù)據(jù)通路經(jīng)過(guò)本地網(wǎng)卡、遠(yuǎn)程網(wǎng)卡、遠(yuǎn)程內(nèi)存最終到達(dá)遠(yuǎn)程存儲(chǔ)。數(shù)據(jù)無(wú)法直接在網(wǎng)卡和存儲(chǔ)設(shè)備之間傳輸,導(dǎo)致了額外的傳輸延遲。新型高速存儲(chǔ)介質(zhì)的出現(xiàn),存儲(chǔ)設(shè)備的訪問(wèn)延遲大幅下降,使得這段延遲在整個(gè)傳輸過(guò)程的延遲中占比大大增加。為了降低數(shù)據(jù)傳輸延遲,充分利用新式存儲(chǔ)設(shè)備的性能,本文設(shè)計(jì)了面向網(wǎng)絡(luò)與存儲(chǔ)的融合設(shè)備模型,提出了融合存儲(chǔ)、網(wǎng)絡(luò)和輔助計(jì)算功能的融合I/O設(shè)備。通過(guò)在同一設(shè)備中融合存儲(chǔ)和網(wǎng)絡(luò)功能,使得設(shè)備內(nèi)的網(wǎng)絡(luò)模塊可以直接與設(shè)備內(nèi)的存儲(chǔ)模塊通信,簡(jiǎn)化了數(shù)據(jù)的傳輸路徑,降低了數(shù)據(jù)的傳輸延遲。實(shí)現(xiàn)了與key-value存儲(chǔ)系統(tǒng)相結(jié)合的UIO設(shè)備模擬器。在最終測(cè)試中與傳統(tǒng)數(shù)據(jù)通路相比,遠(yuǎn)程put減少8.2%延遲,遠(yuǎn)程get減少11%延遲,本地put增加0.9%延遲,本地get增加2.7%延遲的效果。