去年第四季度開始,XSKY團隊[3]開始研究英特爾向社區(qū)開源的SPDK。福叔在學(xué)習(xí)之中發(fā)現(xiàn),就像軟件定義網(wǎng)絡(luò)(SDN)和網(wǎng)絡(luò)功能虛擬化(NFV)中的性能利器DPDK,SPDK也極有機會給SDS領(lǐng)域帶來革命性的影響。如果朋友們不知道DPDK是干什么的,沒有關(guān)系,我將在以后抽時間給大家分享下DPDK的學(xué)習(xí)心得,以及我們把它用在存儲領(lǐng)域的一些想法,今天先看看SPDK。(這篇文章的圖和大部分內(nèi)容來自英特爾官方網(wǎng)站公開的技術(shù)資料[1][2],加上自己的理解,原英文部分內(nèi)容的著作權(quán)歸英特爾公司所有……)
技術(shù)背景
固態(tài)硬盤正在迅速擴展它在數(shù)據(jù)中心中的份額,相較于傳統(tǒng)存儲介質(zhì),新的閃存介質(zhì)具有性能,耗電,機架空間等等方面的優(yōu)勢。隨著更新的閃存介質(zhì)投入市場(如3D NAND),這些優(yōu)勢還在不斷擴大。
用戶在集成新一代的NVMe設(shè)備,如英特爾P3700這樣的“性能怪獸”時,會碰到很大的挑戰(zhàn)。因為NVMe硬盤的吞吐量和時延表現(xiàn)太好了(2GB/s左右的讀寫帶寬,45萬的每秒隨機讀和17萬的每秒隨機寫,20μm級別的時延)——就IOPS而言,比傳統(tǒng)SAS或SATA溫氏磁盤快上千倍,也比之前的SATA SSD快5~10倍。一般存儲軟件的表現(xiàn),相對于NVMe來說,在整個IO事務(wù)中消耗的時間百分比就顯得太多了。換言之,存儲軟件協(xié)議棧的性能和效率在存儲整體系統(tǒng)中的地位就顯得越來越關(guān)鍵了。舉個類似的例子,我們從北京乘飛機到美國三藩,按照現(xiàn)在的飛行速度,在天上需要13個小時。這種情況下,你安檢的時間,過海關(guān)的時間,候機的時間,加起來3個小時,相對于總共的13+3=16個小時也不算長。設(shè)想現(xiàn)在飛機的飛行速度提高了100倍,從首都機場T3起飛后,不到10分鐘的飛行時間,就可在加州落地,這時3個小時的地面手續(xù)就顯得很沒有效率了。存儲系統(tǒng)中軟硬件的協(xié)作關(guān)系,以及網(wǎng)絡(luò)、數(shù)據(jù)庫等其他計算機領(lǐng)域都有類似的情況或命題。我們可以把NVMe看做一個硬件進步推動軟件革新需求的例子,隨著后續(xù)比它更快的存儲介質(zhì)投入市場,這種推動力將更為急迫。
為幫助存儲OEM和軟件定義存儲開發(fā)商充分利用好新的硬件,英特爾開發(fā)了SPDK(Storage Performance Development Kit),包含一套驅(qū)動程序,以及一整套端到端的存儲參考架構(gòu)。SPDK的目標(biāo)是能夠把硬件平臺的計算、網(wǎng)絡(luò)、存儲的最新性能進展充分發(fā)揮出來。自芯片而上進行設(shè)計優(yōu)化,SPDK已展示出超高的性能指標(biāo)。在僅僅幾個CPU核參與下,配上一定數(shù)量的NVMe硬盤,并沒使用任何附加的offload硬件(如FPGA),使用SPDK的存儲系統(tǒng)能輕松達到數(shù)百萬IOPS。英特爾計劃將基于Linux的整個SPDK參考架構(gòu)源代碼免費提供,其中,用戶空間的NVMe驅(qū)動源代碼部分已經(jīng)通過01.org[2]向社區(qū)開放,SPDK中的其他部分組件也將在2016年逐步開源。
軟件架構(gòu)概覽
SPDK是如何工作的?它超高的性能實際上來自于兩項核心技術(shù):第一個是用戶態(tài)運行,第二個是輪詢模式驅(qū)動。下面,讓我們分析一下各自細(xì)節(jié)。
首先,將設(shè)備驅(qū)動代碼運行在用戶態(tài),是和運行在“內(nèi)核態(tài)”相對而言的。把設(shè)備驅(qū)動移出內(nèi)核空間避免了內(nèi)核上下文切換與中斷處理,從而節(jié)省了大量的CPU負(fù)擔(dān),允許更多的指令周期用在實際處理數(shù)據(jù)存儲的工作上。無論存儲算法復(fù)雜還是簡單,也無論進行去重(deduplication),加密(encryption),壓縮(compression),還是簡單的塊讀寫,更少的指令周期浪費意味著更好的整體性能。
其次,傳統(tǒng)的中斷式IO處理模式,采用的是被動的派發(fā)式工作,有IO需要處理時就請求一個中斷,CPU收到中斷后才進行資源調(diào)度來處理IO。舉一個出租車的例子做類比,傳統(tǒng)磁盤設(shè)備的IO任務(wù)就像出租車乘客,CPU資源被調(diào)度用來處理IO中斷就像出租車。當(dāng)磁盤速度遠慢于CPU時,CPU中斷處理資源充沛,中斷機制是能對這些IO任務(wù)應(yīng)對自如的。這就好比是非高峰時段,出租車供大于求,路上總是有空車在掃馬路,乘客隨時都能叫到車。然而,在高峰時段,比如周五傍晚在鬧市區(qū)叫車(不用滴滴或者專車),常常是看到一輛車溜溜的近前來,而后卻發(fā)現(xiàn)后座已經(jīng)有乘客了。需要等待多久,往往是不可預(yù)知的。相信你一定見過在路邊滯留,招手?jǐn)r車的人群。同樣,當(dāng)硬盤速度上千倍的提高后,將隨之產(chǎn)生大量IO中斷,Linux內(nèi)核的中斷驅(qū)動式IO處理(Interrupt Driven IO Process)就顯得效率不高了。
操作系統(tǒng)的世界里,除了中斷式IO處理的方式(即上面提到的被動的派發(fā)式工作),還有一種IO處理方式叫做定點輪詢(polling)。還是用出租車的例子,試想在機場外出租車排隊接客是怎么工作的——有一個或者多個專門的出租車道,排著一隊隊等候的出租車,當(dāng)乘客從航站樓中一涌而出時,一輛輛出租車能夠用少于十來秒的時間高效的接走一位乘客,后面的車緊接著跟上處理下一位客人。
PMD就是按照類似的機制工作的,SPDK中其他所有的組件也是按照這個理念設(shè)計的。專門的計算資源(特定的CPU核)用來主導(dǎo)存儲設(shè)備的輪詢式處理——就像專門的出租車道和車流用來處理乘客任務(wù),數(shù)據(jù)包和塊得到迅速派發(fā),等待時間最小化,從而達到低延時、更一致的延時(抖動變少)、更好的吞吐量的效果。
那么,輪詢模式驅(qū)動是否在所有的情況下都是最高效的處理IO的方式呢?答案是“也不盡然”。設(shè)想一下,如果航站樓里沒有什么旅客出來,乘車的人稀稀拉拉的時候,我們可以看到出租車候車區(qū)等候派工的車輛長龍,這些等待的車子完全可以到市區(qū)去掃活兒,做些更有意義的事情。同樣的道理,對于低速的SATA HDD,PMD的處理機制不但給IO性能帶來的提升不明顯,反而浪費了CPU資源。
這就是為什么我們在學(xué)習(xí)計算機課程時,老師會講所謂“中斷驅(qū)動IO處理”是比其他大部分IO處理機制更好的調(diào)度方式。因為在那個年代,CPU的速度遠大于磁盤等存儲設(shè)備,CPU也沒有很多核或線程交給操作系統(tǒng)用來做更特殊的事情。無論如何,是終端驅(qū)動處理還是輪詢驅(qū)動處理,取決于系統(tǒng)硬件的搭配方式,不同的條件會匹配不同的優(yōu)化策略。
SPDK中包含了多個子組件,通過用戶態(tài)處理機制和輪詢驅(qū)動模式相互聯(lián)系。每個子組件都是為了解決整個存儲系統(tǒng)中的某一部分瓶頸問題而存在的。當(dāng)然,用戶可以選擇只將這些子組件單獨拆出來,用到非SPDK的框架中,去優(yōu)化他們自己的存儲處理堆棧。舉例來說,SPDK中有個組件叫用戶態(tài)網(wǎng)絡(luò)服務(wù)(UNS,UserSpace Network Services)庫,這是一個Linux內(nèi)核TCP/IP協(xié)議棧的替代品,能夠突破通用TCP/IP協(xié)議棧的種種性能限制瓶頸。通過使用用戶態(tài)的,輪詢方式的TCP/IP協(xié)議棧,SPDK能夠在更少的CPU指令周期條件下處理TCP/IP數(shù)據(jù)包排序和計算,達到極高的IOPS性能。
SPDK中大概有三類子組件:網(wǎng)絡(luò)前端、處理框架、后端。
網(wǎng)絡(luò)前端子組件包括DPDK網(wǎng)卡驅(qū)動和上面提到的用戶態(tài)網(wǎng)絡(luò)服務(wù)(UNS)。DPDK在網(wǎng)卡側(cè)提供了一個高性能的發(fā)包收包處理框架,在數(shù)據(jù)從網(wǎng)卡到操作系統(tǒng)用戶態(tài)之間提供了一條快速通道。UNS代碼則接續(xù)這一部分處理,“crack”了TCP/IP數(shù)據(jù)包的標(biāo)準(zhǔn)處理方式,并形成iSCSI命令。
從這個環(huán)節(jié)開始,“處理框架”部分拿到了數(shù)據(jù)包內(nèi)容,將iSCSI命令轉(zhuǎn)換為SCSI塊級命令。然而,在它將這些命令發(fā)到“后端”驅(qū)動之前,SPDK提供了一套API框架,讓廠商能夠插入自己定義的處理邏輯(架構(gòu)圖中綠色的方框)。通過這種機制,存儲廠商可在這里實現(xiàn)例如緩存、去重、壓縮、加密、RAID計算,或擦除碼(Erasure Coding)計算等功能,使這些功能包含在SPDK的處理流程中。在SPDK的開源軟件包里,會有這些功能的實現(xiàn)樣例——雖然不建議用戶直接在為生產(chǎn)環(huán)境準(zhǔn)備的產(chǎn)品代碼里照搬。
最后,數(shù)據(jù)到達了“后端”驅(qū)動層,在這里SPDK和物理塊設(shè)備交互(讀和寫操作)。如前所述,SPDK提供了用戶態(tài)的PMD,支持NVMe設(shè)備、Linux AIO設(shè)備(傳統(tǒng)spinning硬盤)、RAMDISK設(shè)備,以及利用到英特爾I/O加速技術(shù)的新設(shè)備(CBDMA=3D XPoint?)。這一系列后端設(shè)備驅(qū)動涵蓋了不同性能的存儲分層,保證SPDK幾乎與每種存儲應(yīng)用形成關(guān)聯(lián)。事實上,英特爾在2015年9月首先開源的SPDK部分就主要包含支持NVMe的用戶態(tài)輪詢模式驅(qū)動。
當(dāng)然,SPDK并不適用于所有的存儲架構(gòu),這里是官方給出的一些Q&A,幫助存儲開發(fā)人員迅速找到這項技術(shù)的定位:
Q:SPDK包是基于Linux的嗎?
A:SPDK僅僅在Linux平臺上得到測試和支持。
Q:SPDK的IO路徑是運行在用戶態(tài)嗎?
A:SPDK能將IO路徑從網(wǎng)卡到硬盤排他化的運行在用戶態(tài),提高整體性能和效率。
Q:SPDK的系統(tǒng)架構(gòu)中的線程模型包含無鎖化的PMD嗎?
A:事實上,PMD連續(xù)的在它所占用的物理線程上運行(在沒有IO時并不休眠或放棄處理器資源),因此PMD有自己的線程模型,可以認(rèn)為是無鎖的。
Q:SPDK中使用了與DPDK相似的機制處理網(wǎng)絡(luò)數(shù)據(jù)包流量嗎?
A:SPDK包含了對DPDK的支持框架,因此熟悉DPDK的開發(fā)人員能發(fā)現(xiàn)SPDK很容易集成。
Q:SPDK的源代碼使用什么開源許可,是否禁止代碼再分發(fā)?
A:SPDK的一部分源代碼是BSD許可的,例如NVMe和CBDMA用戶態(tài)驅(qū)動。其他部分以Intel License許可開源(UNS和用戶態(tài)iSCSI Target)。但這樣的安排也許在將來會改變。無論如何,SPDK的所有源代碼都將向社區(qū)免費提供。
[1] https://software.intel.com/en-us/articles/introduction-to-the-storage-performance-development-kit-spdk
[2] http://www.01.org/spdk