• <tr id="yyy80"></tr>
  • <sup id="yyy80"></sup>
  • <tfoot id="yyy80"><noscript id="yyy80"></noscript></tfoot>
  • 99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

    純用戶態(tài)的網(wǎng)絡(luò)文件系統(tǒng)
    ——RUFS

    2020-09-29 06:56:22董豪宇
    計算機應(yīng)用 2020年9期
    關(guān)鍵詞:句柄鍵值服務(wù)器端

    董豪宇,陳 康

    (清華大學計算機科學與技術(shù)系,北京 100084)

    0 引言

    傳統(tǒng)的文件系統(tǒng),例如Ext4[1],都實現(xiàn)在內(nèi)核態(tài);但內(nèi)核態(tài)的編程需要具備內(nèi)核相關(guān)的知識,有很高的開發(fā)門檻。內(nèi)核態(tài)程序的錯誤常常會影響到整個操作系統(tǒng)穩(wěn)定運行。如果程序使用到了內(nèi)核的內(nèi)部接口,整個程序會變得難以維護和移植。由于這些原因,將文件系統(tǒng)實現(xiàn)在用戶態(tài)成為了新的趨勢。分布式的文件系統(tǒng),例如GlusterFS(Gluster File System)[2]、GFS(Google File System)[3],由于涉及到復雜的容錯策略和網(wǎng)絡(luò)通信,本身的邏輯很復雜,幾乎都實現(xiàn)在用戶態(tài)。本地文件系統(tǒng)添加某些功能(例如加密[4-5],檢查點(checkpoint)設(shè)置優(yōu)化[6]等),也會優(yōu)先考慮使用FUSE(File system in USErspace)[7]搭建堆棧文件系統(tǒng),將額外的功能實現(xiàn)在用戶態(tài),而不是直接在內(nèi)核的文件系統(tǒng)上作改動。許多出于研究目的搭建的文件系統(tǒng)[8-10],也都通過FUSE 實現(xiàn)在了用戶態(tài)。

    許多用戶態(tài)的文件系統(tǒng),存儲過程基于本地的文件系統(tǒng),在存儲的過程當中,會發(fā)生用戶態(tài)與內(nèi)核態(tài)的切換。這種切換會引發(fā)系統(tǒng)調(diào)用、上下文切換、用戶態(tài)與內(nèi)核之間內(nèi)存的拷貝,這些過程為系統(tǒng)帶來了額外的軟件開銷。

    新一代的存儲硬件——NVMe(Non-Volatile Memory express)固態(tài)硬盤(Solid State Drive,SSD),能夠提供10 μs 以下的延遲和高達3 GB/s 的帶寬。硬件速度的提高,使得存儲系統(tǒng)的軟件開銷成為了不可忽視的一部分[11]。如果將整個存儲過程遷移到用戶態(tài),消除系統(tǒng)因為進入內(nèi)核而產(chǎn)生的開銷,整個系統(tǒng)的性能就可能得到改善。

    出于這樣的目的,Intel 開發(fā)了一套高性能的存儲性能開發(fā) 套 件(Storage Performance Development Kit,SPDK)[12]。SPDK 誕生于2015年,目前學術(shù)界已經(jīng)有了一些基于SPDK 的研究[13-15]。由于繞過了內(nèi)核,并采用了輪詢的事件處理方式,相較于內(nèi)核驅(qū)動,SPDK 的NVMe 驅(qū)動能夠提供更低且更穩(wěn)定的延遲。在用戶態(tài)驅(qū)動之上,SPDK還提供了具有不同語義的存儲服務(wù),開發(fā)者可以在此基礎(chǔ)上進行存儲系統(tǒng)的開發(fā),而無需關(guān)注驅(qū)動的實現(xiàn)細節(jié)。

    在另外一個方面,隨著InfiniBand 等新硬件的成本下降[16],以及RoCE(RDMA over Converged Ethernet)[17]技術(shù)的成熟,RDMA(Remote Direct Memory Access)技術(shù)逐漸在數(shù)據(jù)中心中普及,學術(shù)界也誕生了許多基于RDMA 構(gòu)建的系統(tǒng)[18-21]和相關(guān)的研究[22-24]。RDMA 技術(shù)允許機器在目標機器CPU 不參與的情況下,遠程地讀寫目標機器中的內(nèi)存。相較于傳統(tǒng)的TCP/IP 網(wǎng)絡(luò)棧,RDMA 技術(shù)不僅能提供更低的延遲和更高的帶寬[25],還減少了CPU 的開銷。由于RDMA 協(xié)議工作在用戶態(tài),使用RDMA進行數(shù)據(jù)傳輸,還能避免內(nèi)核-用戶態(tài)切換、內(nèi)存拷貝等過程帶來的開銷。

    當前的用戶態(tài)文件系統(tǒng),都依賴于本地文件系統(tǒng)進行實際存儲。由于內(nèi)核-用戶態(tài)切換的開銷,無法充分地利用NVMe SSD 的性能。另外一方面,多數(shù)文件系統(tǒng)為了實現(xiàn)較高的性能,默認不保證數(shù)據(jù)實時保存到磁盤介質(zhì)上。本文希望設(shè)計一個純用戶態(tài)的網(wǎng)絡(luò)文件系統(tǒng),減少存儲過程中的軟件開銷,充分發(fā)揮NVMe SSD 的硬件性能,并提供同步語義,保證數(shù)據(jù)實時持久化。同時,利用RDMA進行網(wǎng)絡(luò)通信,對外提供一個高吞吐和低延遲的文件系統(tǒng)服務(wù)。

    本文設(shè)計并實現(xiàn)了一個基于高速網(wǎng)絡(luò)與SSD的網(wǎng)絡(luò)文件系統(tǒng)——RUFS(Remote Userspace File System)。RUFS 遵循客戶端/服務(wù)器端架構(gòu),采用RDMA 協(xié)議進行通信。用戶可以利用客戶端提供的API,使用由服務(wù)器端提供的文件系統(tǒng)服務(wù)。服務(wù)器端是一個單機的文件系統(tǒng),元數(shù)據(jù)管理基于鍵值存 儲RocksDB(Rocks DataBase),數(shù)據(jù)管理基于SPDK Blobstore,所有存儲過程都通過SPDK 提供的NVMe 驅(qū)動運行在用戶態(tài)。通常遵循POSIX(Portable Operating System Interface X)語義的文件系統(tǒng),只能保證元數(shù)據(jù)操作的原子性。而RUFS 具備同步語義,能夠在遵循POSIX 語義基礎(chǔ)之上,保證已經(jīng)完成的數(shù)據(jù)和元數(shù)據(jù)操作,在服務(wù)器掉電之后不丟失,而無需使用fsync進行持久化。

    僅使用一塊SSD 作為數(shù)據(jù)盤,RUFS:在4KB 隨機訪問上,讀、寫操作就能獲得超過400 MB/s的性能,較默認配置下NFS+ext4 的性能提升了202.2%和738.9%;對于4MB 順序訪問,RUFS相較于NFS+ext4也有至少40%的性能提升。在元數(shù)據(jù)性能上,RUFS的文件夾創(chuàng)建性能,相較于NFS+ext4,有5 693.8%的性能提升,其他大部分元數(shù)據(jù)操作也有顯著的性能優(yōu)勢。

    本文主要有三個方面的貢獻:第一,為如何在用戶態(tài)完成文件系統(tǒng)所有存儲過程給出了詳細的方案;第二,在此基礎(chǔ)上,實現(xiàn)了一個網(wǎng)絡(luò)文件系統(tǒng)原型RUFS,并報告了數(shù)據(jù)和元數(shù)據(jù)性能;第三,改進了BlobFS 的緩存策略,使得工作在BlobFS 之上的鍵值存儲的讀性能有了非常明顯的提升,也間接提升了RUFS的元數(shù)據(jù)性能。

    1 相關(guān)研究

    1.1 基于鍵值存儲的文件系統(tǒng)元數(shù)據(jù)管理

    鍵值存儲是一種NoSQL 存儲,一般基于LSM Tree(Log Structured Merged Tree)[26]構(gòu)建,提供有序鍵到任意長度值的持久化存儲和查詢。通過將隨機寫入轉(zhuǎn)化為順序?qū)懭?,這種鍵值存儲通常能夠取得更好的性能。

    2013 年,Ren 等[8]提出了TableFS(Table File System)。TableFS 利用LevelDB(Level DataBase)[27]構(gòu)建了一個文件系統(tǒng)元數(shù)據(jù)模塊,以鍵值對的鍵描述父節(jié)點到子節(jié)點的關(guān)系,并將文件的元數(shù)據(jù)作為鍵值對的值存在LevelDB 中。在此基礎(chǔ)上,利用Ext4 作為對象存儲,為TableFS 提供數(shù)據(jù)的存儲服務(wù)。為了減少對下層Ext4 的訪問,TableFS 還將小于4 KB 的文件也放在了LevelDB當中。

    在此基礎(chǔ)上,2014年,Ren等[28]提出了TableFS的分布式版本——IndexFS(Index File System),并在此基礎(chǔ)上做了一些相關(guān)的工作[29-30]。2017年,Li等[31]提出了LocoFS(Loco File System)。LocoFS改進了用鍵值存儲模擬目錄樹的方式,減少了元數(shù)據(jù)操作需要的網(wǎng)絡(luò)請求數(shù)量,提高了元數(shù)據(jù)操作的性能。

    1.2 SPDK技術(shù)

    存儲服務(wù)的性能由軟件與硬件共同決定。對于傳統(tǒng)存儲硬件(如機械硬盤),由于硬件性能較差,軟件上的開銷只占整個存儲服務(wù)開銷的一小部分。但隨著NVMe SSD 的出現(xiàn),相當一部分存儲硬件,例如Z-SSD、Optane SSD等,已經(jīng)能夠提供小于10 μs 的延遲和高達3 GB/s 的帶寬[11]。硬件性能的大幅提高,使得軟件棧的開銷成為了整個存儲服務(wù)開銷中不可忽視的一部分。

    為了充分利用NVMe SSD的性能,減少存儲過程中的軟件開銷,Intel開發(fā)了SPDK。SPDK提供了一個純用戶態(tài)的NVMe驅(qū)動,消除了內(nèi)核與系統(tǒng)中斷帶來的開銷。SPDK提供的NVMe驅(qū)動采用了無鎖的實現(xiàn),支持多線程同時提交I/O請求。

    根據(jù)SPDK 團隊的論文[12],對于NVMe SSD(實驗所用的SSD 型號為Intel P3700,容量為800 GB)的4 KB 隨機訪問。SPDK 的用戶態(tài)NVMe 驅(qū)動,能用1 塊SSD 提供450 kIOPS(Input/output Operations Per Second)的訪問性能,略高于Linux內(nèi)核中的NVMe 驅(qū)動。得益于無鎖的實現(xiàn)方式,SPDK 提供的性能,能夠隨著SSD 的增多而線性增加,用8 塊SSD 提供約3 600 kIOPS 的訪問性能。而增加SSD 數(shù)量,對內(nèi)核驅(qū)動提供的性能沒有提高。在4 KB 隨機讀的延遲上,SPDK 能夠?qū)?nèi)核驅(qū)動造成的軟件開銷,降低約90%。

    SPDK 為用戶提供了一套事件驅(qū)動的編程框架。在這套框架中,每個線程相互獨立,通過消息傳遞的方式進行線程間同步,線程間不共享任何資源。這種設(shè)計消除了資源共享帶來的數(shù)據(jù)競爭,使框架具有良好的可擴展性。這個編程框架定義了3個重要的概念,分別是reactor、event和poller。reactor是一個常駐的線程,持有一個無鎖的消息隊列;event 代表一個任務(wù),可以通過reactor 的消息隊列在線程間傳遞;poller 與event 類似,也是一種任務(wù),但需要注冊在一個reactor 上,reactor 會周期性地調(diào)用已注冊的poller。用戶可以使用poller在用戶態(tài)模擬系統(tǒng)中斷。

    Blobstore和BlobFS(Blob File System)是SPDK提供的兩個存儲服務(wù),前者提供對象(blob)存儲的語義,后者提供一個簡易的文件系統(tǒng),用戶可以在此基礎(chǔ)上搭建存儲應(yīng)用。Blobstore中最基礎(chǔ)的存儲單元被稱為page,每個page 4 KB大小。Blobstore可以保證每個page寫入的原子性。根據(jù)用戶配置,Blobstore會將連續(xù)的多個page組織在一起(通常大小為1 MB),這一段連續(xù)的空間被稱為一個cluster,而blob則是一個cluster的鏈表。用戶可以在blob上進行隨機、并發(fā)、無緩存的讀寫,還可以將鍵值對以元數(shù)據(jù)的形式存儲在blob當中,但元數(shù)據(jù)需要用戶自己手動調(diào)用sync md(同步元數(shù)據(jù))操作才能持久化。

    BlobFS是在Blobstore的基礎(chǔ)上構(gòu)建的一個簡易的文件系統(tǒng)。每個文件都對應(yīng)著Blobstore中的一個blob,文件的名字和長度,都以鍵值對的形式存儲在blob的元數(shù)據(jù)當中。BlobFS只能支持創(chuàng)建根目錄下的文件,不支持文件夾功能,不支持隨機位置的寫入,只支持增量寫。當前BlobFS 已經(jīng)能夠作為鍵值存儲系統(tǒng)的存儲引擎,但由于不支持隨機位置的寫入,仍然不適合用于管理文件數(shù)據(jù)。BlobFS當中還實現(xiàn)了一個簡單的緩存模塊,可以為文件的順序讀和增量寫帶來一定的性能提升。

    1.3 基于RDMA的RPC技術(shù)

    RDMA 是指一種允許處理器直接讀寫遠程計算機內(nèi)存的技術(shù)。相較于傳統(tǒng)網(wǎng)絡(luò),RDMA 能夠提供極低的延時和很高的帶寬。最新商用的RDMA 網(wǎng)卡可以提供低至600 ns的延時和每端口高達200 Gb/s 的帶寬[25]。RDMA 編程一般使用verbs API,需要開發(fā)者自己控制網(wǎng)絡(luò)連接、任務(wù)輪詢等細節(jié),編程復雜度較高。

    RPC(Remote Procedure Call)技術(shù)[32],是一種允許本地機器透明地調(diào)用遠端函數(shù)或者過程的技術(shù)。RPC技術(shù)向用戶隱藏了數(shù)據(jù)的發(fā)送、接收、序列化、反序列化等細節(jié),大大降低了編程復雜度。Mercury 是面向超算領(lǐng)域的RPC 框架,于2013 年由Soumagne等[33]提出。Mercury包含了一個網(wǎng)絡(luò)抽象層,可以通過不同的通信插件,在不同網(wǎng)絡(luò)硬件下進行數(shù)據(jù)傳輸。當前,Mercury 采用了OFI(Open Fabric Interface)[34]作為支持RDMA傳輸?shù)耐ㄐ挪寮?。Mercury在常規(guī)的RPC接口之外,還提供了一組塊(bulk)傳輸接口。Bulk接口能夠充分利用RDMA單邊通信的性能,消除不必要的內(nèi)存拷貝。用戶可以把一塊內(nèi)存注冊為一個bulk,并將bulk句柄發(fā)送給其他機器,其他機器就能通過bulk句柄遠程地讀寫被注冊的內(nèi)存。在Mercury的基礎(chǔ)上,Intel正在開發(fā)一套支持組通信的RPC 框架,CaRT(Collective and RPC Transport),作為其在新的存儲系統(tǒng)DAOS(Distributed Asynchronous Object Storage)[35-36]中的傳輸層。CaRT不僅支持傳統(tǒng)的點對點RPC通信,還能支持RPC的組播。

    2 系統(tǒng)架構(gòu)與設(shè)計

    本章主要介紹了RUFS 的設(shè)計與實現(xiàn),包括元數(shù)據(jù)管理的策略、數(shù)據(jù)管理的策略、保證元數(shù)據(jù)與數(shù)據(jù)的一致性策略。

    2.1 系統(tǒng)架構(gòu)

    RUFS 是一個純用戶態(tài)的文件系統(tǒng),采用客戶端/服務(wù)器端架構(gòu),服務(wù)器端是一個單機系統(tǒng),可以同時支持多個客戶端。服務(wù)器端與客戶端通過CaRT進行通信。

    RUFS客戶端為用戶提供了一套類POSIX語義的、并發(fā)安全的文件系統(tǒng)操作API(RUFS-API),支持的操作包括:access、mkdir、rmdir、stat、rename、opendir、readdir、closedir、open、creat、close、ftruncate、unlink、pread、pwrite、read、write,支持文件和文件夾操作。當用戶調(diào)用客戶端API 時,客戶端會將請求通過RPC的形式發(fā)送到RUFS服務(wù)器端,并等待請求返回。

    RUFS 服務(wù)器端實現(xiàn)了一個純用戶態(tài)文件系統(tǒng)(RUFSserver)。系統(tǒng)需要至少兩塊SSD才能工作,其中一塊用來建立BlobFS 實例,用來支持RocksDB[37]的數(shù)據(jù)存儲。RUFS 將利用RocksDB 對元數(shù)據(jù)進行存儲和管理。剩下的每塊SSD 都會創(chuàng)建一個單獨的Blobstore 實例,用來存儲數(shù)據(jù),其中的每個blob都包含著一個文件的數(shù)據(jù)。RUFS能利用多個SSD來提高服務(wù)器端的文件讀寫的吞吐能力。在RUFS服務(wù)啟動時,系統(tǒng)會為每一塊用于存儲數(shù)據(jù)的SSD 建立一個Blobstore 實例,同時,啟動一定數(shù)量的reactor線程,負責處理讀寫請求。reactor線程的數(shù)量可以自行配置,但不能超過Blobstore 的實例數(shù)量,每個Blobstore實例受一個固定的reactor線程的管理。

    圖1 RUFS架構(gòu)Fig.1 RUFS architecture

    2.2 元數(shù)據(jù)管理

    2.2.1 基于鍵值存儲與Blobstore的元數(shù)據(jù)協(xié)同管理

    文件系統(tǒng)的元數(shù)據(jù)通常組織為目錄樹。目錄樹的節(jié)點存儲了文件的元數(shù)據(jù),每一個節(jié)點都有一個唯一的編號(inode number),目錄樹的邊代表目錄對下一級節(jié)點的包含關(guān)系。RUFS利用鍵值存儲模擬目錄樹,同樣模擬了目錄樹的節(jié)點和邊,并為每個節(jié)點賦予了一個唯一的UUID(Universally Unique IDentifier)。目錄樹的節(jié)點和邊用不同的鍵值對模擬,前者稱為N型(node)鍵值對,后者稱為E型(edge)鍵值對。兩者在鍵值存儲中,有不同的前綴,N 型鍵值對模擬節(jié)點,鍵由前綴、節(jié)點UUID 拼接而成,值包含了該節(jié)點的一部分元數(shù)據(jù)(記為Meta-N),E 型鍵值對模擬父節(jié)點到子節(jié)點的邊,鍵由前綴、父節(jié)點UUID、子節(jié)點文件名拼接而成,值中包含子節(jié)點UUID 和子節(jié)點的一部分元數(shù)據(jù)(記為Meta-E)?;阪I值存儲的鍵的有序性,擁有相同父節(jié)點的E 型鍵值對會聚合到一起,這方便了readdir 的實現(xiàn)。RUFS 可以將readdir 對子節(jié)點的遍歷,轉(zhuǎn)化為RocksDB對鍵值對的遍歷。

    圖2 目錄樹與鍵值對的對應(yīng)關(guān)系Fig.2 Relationship between directory tree and key-value pairs

    在RUFS 中,一個文件/文件夾的元數(shù)據(jù)包括:mode(其中包含了節(jié)點類型、權(quán)限信息)、gid、uid、atime、ctime、mtime。對于文件,還包括文件的長度、文件對應(yīng)的blob的相關(guān)信息。許多元數(shù)據(jù)操作的接口,都是基于路徑名的(例如creat、rmdir等),系統(tǒng)需要從根節(jié)點開始,通過文件名和E型鍵值對,順著目錄樹的樹邊逐層往下查找節(jié)點,直到找到路徑名對應(yīng)的節(jié)點,再做相應(yīng)的操作。在查找目標節(jié)點的過程中,根據(jù)POSIX語義的要求,系統(tǒng)同時要判斷操作對節(jié)點是否有訪問權(quán)限。這需要讀取節(jié)點元數(shù)據(jù)中的mode、gid 和uid。為了消除在權(quán)限判斷過程中,對N 型鍵值對的額外訪問,RUFS 將mode、gid和uid 劃分到了E 型鍵值對中。圖3 展示了節(jié)點元數(shù)據(jù)是如何存儲在不同的鍵值對中的。

    圖3 在鍵值對中存儲元數(shù)據(jù)的方式Fig.3 Method of storing metadata in key-value pairs

    根據(jù)POSIX語義的要求,文件在被進行讀寫時,文件的時間戳需要被相應(yīng)地改變,文件的長度也可能發(fā)生變化。如果要將這些改動同步到RocksDB 當中,當系統(tǒng)需要同時處理大量的讀寫請求時,RocksDB 的寫入性能就會成為整個系統(tǒng)的瓶頸。因此,在RUFS 中,文件的長度和時間戳還會存儲在對應(yīng)的blob 的元數(shù)據(jù)中。當文件被讀寫時,文件長度和時間戳的變化只會存儲到blob的元數(shù)據(jù)中,當文件被關(guān)閉時,長度和時間戳才會被同步回RocksDB中。

    2.2.2 元數(shù)據(jù)操作的原子性和并發(fā)安全性

    某些元數(shù)據(jù)操作(例如rename)需要對目錄樹進行多次改動,為了保證操作的原子性,RUFS 中所有可能涉及目錄樹變化,或是在操作過程中默認目錄樹不發(fā)生結(jié)構(gòu)變化的操作,都利用了RocksDB事務(wù)來保證元數(shù)據(jù)操作的原子性。

    RUFS服務(wù)器端作為一個多線程的系統(tǒng),能夠并發(fā)地更改目錄樹的結(jié)構(gòu),如果不進行并發(fā)控制,就會產(chǎn)生錯誤。而單純使用RocksDB事務(wù),無法避免這樣的錯誤。圖4展示了一種出錯的情況。在目錄樹為初始狀態(tài)時,系統(tǒng)同時收到了creat 操作和rmdir操作,由于RocksDB 事務(wù)只處理寫-寫操作的沖突,因此兩個元數(shù)據(jù)操作事務(wù)得以并發(fā)地執(zhí)行,并進行了事務(wù)提交,結(jié)果造成了creat 操作創(chuàng)建了一個空懸的節(jié)點。為了解決這一問題,RUFS 利用了RocksDB 事務(wù)中的get_for_update 操作。這一操作會促使RocksDB為目標鍵值對加上一個讀寫鎖,通過為目錄樹上的節(jié)點和邊上讀寫鎖,就能避免元數(shù)據(jù)的并發(fā)操作破壞目錄樹結(jié)構(gòu)。在加鎖的順序上,RUFS總是遵循這樣的規(guī)則:對于兩個待加鎖的節(jié)點A 和B,若兩者在目錄樹中深度不同,那么RUFS會從較淺的節(jié)點到較深的節(jié)點加鎖。若兩者在目錄樹中的深度相同,RUFS會從UUID較小者到UUID較大者加鎖。RUFS通過有順序的加鎖,來避免死鎖問題。

    圖4 并發(fā)的元數(shù)據(jù)操作導致的錯誤Fig.4 Error caused by concurrent metadata operations

    2.3 數(shù)據(jù)管理

    SPDK 提供3 個存儲服務(wù),分別是BDev(Block Device)、Blobstore 和BlobFS。其中:BDev 只提供塊設(shè)備的語義,過于簡單,不適合用作管理文件數(shù)據(jù);BlobFS不支持對文件的隨機寫入;而Blobstore則能提供對象存儲的語義,提供針對blob的創(chuàng)建、刪除、隨機讀寫、長度變更等操作。RUFS容易將針對文件內(nèi)容的操作,映射到Blobstore 中針對blob 的操作。因此,RUFS選擇將數(shù)據(jù)存儲在Blobstore中。

    每創(chuàng)建一個文件,RUFS就在Blobstore中創(chuàng)建一個相應(yīng)的blob。目錄樹中的文件節(jié)點與Blobstore 中的blob 一一對應(yīng)。blob 的位置信息(blob 所屬的Blobstore 和blob ID),會成為文件元數(shù)據(jù)的一部分,存儲在RocksDB 當中。每一個Blobstore實例都由一個固定的reactor管理,對Blobstore的任何操作,包括blob 的創(chuàng)建、刪除、讀寫,都需要提交給對應(yīng)的reactor,由reactor完成。

    2.3.1 元數(shù)據(jù)與數(shù)據(jù)的一致性策略

    當用戶創(chuàng)建或刪除一個文件時,RUFS不僅需要改變目錄樹的結(jié)構(gòu),還需要在Blobstore 上創(chuàng)建或者刪除相應(yīng)的blob,維持文件節(jié)點與blob的一一對應(yīng)。宕機會導致文件的創(chuàng)建或刪除執(zhí)行不完整,破壞文件節(jié)點與blob一一對應(yīng)的關(guān)系。如果產(chǎn)生了游離的blob(沒有對應(yīng)文件節(jié)點的blob),則造成存儲空間的泄漏,如果文件節(jié)點沒有對應(yīng)的blob,則意味著數(shù)據(jù)丟失。

    RUFS利用了一種基于blob標記的手段來解決這個問題?;镜乃悸肥牵瑢]有和元數(shù)據(jù)建立聯(lián)系的blob 標記為已解耦(detached),并將位置信息記錄到RocksDB 中,這樣即使服務(wù)器宕機,重啟RUFS之后,系統(tǒng)也能夠回收這些blob。

    圖5(a)展示了文件的creat 過程,新創(chuàng)建的blob 會被標記為detached,并記錄在RocksDB 當中,只有在blob 元數(shù)據(jù)設(shè)置成功,并且將位置信息記錄在目錄樹上后,RocksDB 中的detached 記錄才會被刪除。如果因為宕機導致操作沒有完全執(zhí)行,RUFS 在重新啟動時,通過檢查blob 的元數(shù)據(jù)和RocksDB中的記錄,就能回收游離的blob。Detached記錄的刪除過程與目錄樹的操作處于同一個RocksDB 事務(wù)中,能保證creat 成功后,被創(chuàng)建出的blob 不會被錯誤地回收。圖5(b)展示了文件的unlink 操作,標記blob 為detached 的過程會和刪除文件節(jié)點的過程放在同一個RocksDB 事務(wù)中。這能保證只要元數(shù)據(jù)的刪除操作成功,即使出現(xiàn)意外宕機,游離的blob也總能被回收。

    圖5 創(chuàng)建和刪除文件的流程Fig.5 Processes of file creation and deletion

    2.3.2 句柄與讀寫狀態(tài)管理

    根據(jù)POSIX 標準的要求,open、creat、opendir等操作,需要向調(diào)用者返回一個句柄。通過句柄,用戶可以進一步地對文件或文件夾進行其他操作,而不用再進行從路徑到文件節(jié)點的搜索和權(quán)限判斷。在RUFS 中,通過句柄,用戶可以讀寫文件(read、write、pread、pwrite),遍歷文件夾下的子項目(readdir)。

    RUFS 的句柄包含兩個字段:一個字段是被打開節(jié)點的UUID,用來標示被打開的節(jié)點;另一個字段是一個唯一的64位無符號數(shù)(fd ID),用來標示打開同一個文件的不同句柄。通過句柄,RUFS-server能夠查找當前句柄對應(yīng)的讀寫狀態(tài)。

    RUFS-server采用了圖6中的數(shù)據(jù)結(jié)構(gòu)來管理句柄的讀寫狀態(tài),這個數(shù)據(jù)結(jié)構(gòu)用了一個以UUID 為鍵的哈系表,來維持被打開文件/文件夾的內(nèi)存節(jié)點。內(nèi)存節(jié)點中包含了對其進行操作所需要的數(shù)據(jù);文件內(nèi)存節(jié)點中包含了文件對應(yīng)的blob的位置信息,緩存了文件的長度和時間戳;文件夾內(nèi)存節(jié)點,存儲了以該文件夾為父節(jié)點的E 型鍵值對的鍵的公共前綴(前綴E+文件夾UUID),這個前綴用來在遍歷E 型鍵值對時,判斷被訪問的鍵值對是否指向該文件夾的子節(jié)點。每個內(nèi)存節(jié)點中包含了一條鏈表,鏈表上的每一個元素,都記錄了某個句柄對應(yīng)的讀寫狀態(tài),如果句柄屬于一個文件,那么讀寫狀態(tài)就是當前偏移(offset)的位置,如果句柄屬于一個文件夾,那么讀寫狀態(tài)就是readdir 操作所需的RocksDB 迭代器。利用圖6 中的數(shù)據(jù)結(jié)構(gòu),RUFS 還能通過哈希表快速地判斷某個節(jié)點是否被打開,阻止被打開的節(jié)點被刪除。

    圖6 RUFS對句柄的管理Fig.6 Management of handles in RUFS

    3 系統(tǒng)實現(xiàn)與優(yōu)化

    3.1 網(wǎng)絡(luò)傳輸優(yōu)化

    RUFS 采用了CaRT 作為客戶端與服務(wù)器端通信的手段。CaRT 為用戶提供了RPC 接口和bulk接口,bulk接口能夠充分利用RDMA 的單邊通信性能,避免不必要的內(nèi)存拷貝。元數(shù)據(jù)操作需要傳輸?shù)臄?shù)據(jù)量通常很少,因此RUFS 只使用CaRT提供的RPC 接口來發(fā)送元數(shù)據(jù)操作。但讀寫操作,可能需要傳輸較多的數(shù)據(jù),為了充分利用RDMA的單邊通信原語,提高傳輸性能,RUFS利用bulk接口來傳輸讀寫緩沖區(qū)中的內(nèi)容。

    但使用bulk接口,需要用戶自己申請內(nèi)存,并將內(nèi)存注冊為一個塊(bulk)。注冊bulk非常耗時,將一塊僅1 B的內(nèi)存注冊為bulk,需要耗費大約60 μs,如果在客戶端和服務(wù)器端都進行內(nèi)存的注冊,一次通信會產(chǎn)生額外的120 μs的開銷,隨著被注冊內(nèi)存的增大,耗時還會增大。圖7 展示了發(fā)送不同大小的負載時復用bulk(記為reuse-bulk)和每次注冊新的bulk(記為register-bulk)在傳輸延遲上的性能差距。

    圖7 不同負載下bulk傳輸?shù)难舆tFig.7 Bulk transfer latency with different payload sizes

    為了解決這一問題,RUFS 設(shè)計了一個內(nèi)存池,Bulk-Mempool。Bulk-Mempool 會提前將一些大塊的內(nèi)存注冊為一個bulk,并在這塊內(nèi)存上進行進一步的分配。在讀寫操作的過程中,服務(wù)器和客戶端用到的讀寫緩沖區(qū)就從這個內(nèi)存池中分配,這就消除了RUFS 在每次讀寫操作時,將讀寫緩沖區(qū)所在的內(nèi)存注冊為bulk而帶來的開銷。

    Bulk-Mempool 并不是一個單一策略的內(nèi)存池,而是由兩個不同策略的內(nèi)存池BM-small 和BM-mid 組成的。BM-small實現(xiàn)比較簡單,分配開銷較小,只分配4 KB 大小的內(nèi)存;BM-mid內(nèi)部實現(xiàn)了一個buddy system 內(nèi)存池,開銷相對較大。小文件讀寫通常觸發(fā)小于等于4 KB 的內(nèi)存分配請求,此時由開銷較小的BM-small 進行內(nèi)存分配,能夠保證小文件讀寫的性能;大于4 KB、小于等于4 MB 的內(nèi)存分配請求,則由BMmid 負責。BM-mid 能夠分配不同大小的內(nèi)存,提高內(nèi)存的利用率。

    圖8 Bulk-Mempool的架構(gòu)Fig.8 Architecture of Bulk-Mempool

    Bulk-Mempool 沒有對大于4 MB 的內(nèi)存分配進行優(yōu)化,是因為以4 MB 為單位的數(shù)據(jù)傳輸,已經(jīng)能夠充分地利用InfiniBand 的高帶寬,使數(shù)據(jù)傳輸不會成為整個系統(tǒng)的瓶頸,本文的實驗也說明了這一點(見4.3 節(jié))。如果用戶需要傳輸大文件,將每次讀寫請求分割為4 MB大小即可。

    Bulk-Mempool 提供get 和put接口。通過get 接口,調(diào)用者能夠獲得一個胖指針,其中包括了指向被分配內(nèi)存的指針、被分配內(nèi)存的大小、被分配內(nèi)存在bulk 中的偏移,以及bulk 句柄。前兩者使得調(diào)用者可以在本地讀寫分配到的內(nèi)存,后兩者使得遠端機器能夠正確在分配到的內(nèi)存上進行讀寫。

    3.2 讀寫吞吐能力優(yōu)化

    按照POSIX 語義的要求,文件的讀寫會導致文件的大小和時間戳發(fā)生變化,導致元數(shù)據(jù)的改動。這在Blobstore 中就表現(xiàn)為需要通過sync md(同步元數(shù)據(jù))操作同步blob 的元數(shù)據(jù),但sync md 操作非常耗時,甚至超過了一次4 KB 的讀或?qū)?。如果每次文件讀寫都要更新時間戳或是文件長度,頻繁觸發(fā)sync md 操作,會讓整個系統(tǒng)的吞吐能力受到極大的影響。為此,RUFS提供了兩個優(yōu)化策略,以減小sync md的觸發(fā)頻率。

    第一個策略是,提供了ftruncate 操作,并鼓勵用戶盡可能在寫入數(shù)據(jù)前,將文件擴展到合適的大小,這樣能夠避免寫入操作“撐大”文件大小,進而觸發(fā)sync md。另一個策略是,放寬對時間戳更新的要求,每次進行讀寫時,將系統(tǒng)當前的時間,與文件當前的時間戳進行比較,只有文件需要更新的時間戳,與當前的時間相差多于5 ms 時,才選擇更新時間戳??紤]到系統(tǒng)本身就存在著時間上的誤差,這樣的放松策略是可以接受的。

    3.3 可靠元數(shù)據(jù)性能優(yōu)化

    RocksDB 會將寫入操作記錄到日志里,但并不會立刻將日志寫入到磁盤中。在內(nèi)存中緩存一定數(shù)量的日志之后,RocksDB 才會一次性地將所有內(nèi)存中的日志寫到硬盤上。這個特性被稱作“組提交(group commit)”,組提交特性顯著地減少了向磁盤寫入數(shù)據(jù)的次數(shù),對RocksDB 的寫入性能有很大的提升。但同時,由于寫入的數(shù)據(jù)不能被及時持久化,服務(wù)器斷電就可能導致元數(shù)據(jù)操作的丟失??紤]到Blobstore會保證數(shù)據(jù)持久化后再返回,為了使元數(shù)據(jù)與數(shù)據(jù)保持一致,提供同步的文件系統(tǒng)語義,RUFS 也需要保證元數(shù)據(jù)操作返回后,就已經(jīng)持久化到了硬盤上。

    為了提供這樣的保證,RUFS 打開了RocksDB 的同步模式。同步模式下,每次寫入操作后,RocksDB 都會調(diào)用fsync保證日志寫入硬盤,使數(shù)據(jù)在宕機后不丟失。然而,本地文件系統(tǒng)的fsync 性能很差,這導致了RocksDB 同步模式下的寫入性能也很差,降低了RUFS 整體的元數(shù)據(jù)性能。為了解決這個問題,RUFS采用了由SPDK團隊修改并開源的RocksDB[38]。這個版本的RocksDB 將底層的存儲環(huán)境更換為了BlobFS。BlobFS 有很好的同步寫入性能,能夠顯著提升RocksDB 在同步模式下的寫入性能。

    RocksDB 的讀操作觸發(fā)的都是文件的隨機讀,而BlobFS當前僅針對順序讀進行緩存。緩存的缺失使RocksDB 的讀性能變得很差。為了解決這個問題,在BlobFS 中添加了一個支持緩存的隨機讀方法,當RocksDB 調(diào)用這個方法進行讀操作時,BlobFS 會預取所需數(shù)據(jù)所在的一個256 KB 的數(shù)據(jù)塊,并緩存在內(nèi)存當中。利用緩存,相比以文件系統(tǒng)作為存儲環(huán)境,RocksDB 在BlobFS 上的寫性能能得到顯著提升,且保持讀性能基本相同。

    3.4 統(tǒng)一的SPDK環(huán)境管理模塊

    RUFS 利用一個或多個Blobstore 管理數(shù)據(jù),利用由SPDK團隊提供的RocksDB 管理元數(shù)據(jù)。這兩者都需要工作在SPDK環(huán)境下。當前,由SPDK團隊提供的RocksDB,會在內(nèi)部自行啟動一個SPDK 環(huán)境。由于一個進程只能啟動一個SPDK 環(huán)境,因此RocksDB 啟動的SPDK 環(huán)境,會和RUFS 啟動的SPDK環(huán)境產(chǎn)生沖突,導致整個系統(tǒng)啟動失敗。

    為了解決這一問題,RUFS 去掉了RocksDB 中啟動SPDK環(huán)境的功能,并將這部分功能整合到了RUFS 中,再加上對Blobstore 依賴的SPDK 環(huán)境的管理功能,形成了統(tǒng)一的SPDK環(huán)境管理模塊(SPDK-env-mod)。系統(tǒng)啟動時,SPDK-env-mod會初始化SPDK 環(huán)境,同時創(chuàng)建BlobFS。在RocksDB 初始化時,SPDK-env-mod 會將BlobFS 暴露給RocksDB,使RocksDB順利在BlobFS上初始化和運行。

    除了解決SPDK 環(huán)境沖突的問題,SPDK-env-mod 還方便了系統(tǒng)管理員對Blobstore 的管理。SPDK-env-mod 提供了一個配置文件,系統(tǒng)管理員可以通過該配置文件,指定用來管理數(shù)據(jù)的SSD,以及用于管理數(shù)據(jù)的reactor 線程的數(shù)量。系統(tǒng)啟動后,SPDK-env-mod 會根據(jù)配置文件,在每塊用于管理數(shù)據(jù)的SSD 上,建立Blobstore 實例。同時,根據(jù)配置文件,啟動一定數(shù)量的reactor 線程,并按照平均分配的原則,將Blobstore綁定到不同的reactor線程上。

    除此之外,SPDK-env-mod 會給每一個Blobstore 賦予一個從0 開始的、單調(diào)遞增的唯一編號,同時在內(nèi)存中維持一個計數(shù)器,每次系統(tǒng)需要創(chuàng)建一個blob 時,就將計數(shù)器的值對Blobstore 的數(shù)量取模,以此選出一個Blobstore 實例,在這個實例上創(chuàng)建blob,并將計數(shù)器原子地加1。由于Blobstore實例與用來管理數(shù)據(jù)的SSD 一一對應(yīng),這樣的分配方案,可以保證blob均勻地分布在各個SSD上。

    4 測試與評估

    本章將評估RUFS 在元數(shù)據(jù)、讀寫延遲和讀寫吞吐方面的性能。RUFS的總體性能會和NFS+ext4進行比較;而RUFSserver的性能會和ext4進行比較。本章還會討論SPDK對元數(shù)據(jù)的加速效果和多SSD對吞吐性能的提升。

    4.1 測試配置

    所有的測試都在兩臺服務(wù)器上進行,其中一臺作為RUFS的服務(wù)器,另一臺作為RUFS 的客戶端。RUFS 客戶端裝配了2 塊6 核CPU,128 GB 內(nèi)存;RUFS 服務(wù)器端裝配了4 塊12 核CPU、768 GB 內(nèi)存、8 塊容量為512 GB 的NVMe SSD。兩臺服務(wù)器通過56 Gb/s 帶寬的InfiniBand 網(wǎng)卡相連。表1 是測試環(huán)境的具體參數(shù)。

    在所有測試中,NFS 與ext4 均采用默認配置,ext4 建立在服務(wù)器端,使用1塊SSD,利用NFS掛載到客戶端。RUFS使用2 塊SSD,分別用來管理數(shù)據(jù)和元數(shù)據(jù),使用16 個RPC 處理線程,1 個reactor 線程??蛻舳死肦UFS 客戶端提供的API 訪問RUFS服務(wù)器。

    表1 測試環(huán)境設(shè)置Tab.1 Testing environment configuration

    4.2 元數(shù)據(jù)性能

    本文采用mdtest[39]對元數(shù)據(jù)性能進行測試,用每秒的操作數(shù)量(Operations Per Second,OPS)衡量性能。該測試對比了NFS+ext4 與RUFS 整體的元數(shù)據(jù)性能。在元數(shù)據(jù)性能測試中,客戶端使用8 個mdtest 進程,文件節(jié)點的最大深度為4,文件/文件夾總數(shù)大約為50 萬。如果測試對象為RUFS,需要將mdtest中的文件系統(tǒng)函數(shù)換成RUFS-API。

    4.2.1 需要關(guān)注的元數(shù)據(jù)操作

    在本節(jié)的測試中,主要關(guān)注如下的元數(shù)據(jù)操作:D-creat、D-stat、D-remove、F-creat、F-stat、F-read 和F-remove,表2 展示了它們的意義和在過程中會觸發(fā)的操作。

    表2 元數(shù)據(jù)操作和它們的屬性和含義Tab.2 Metadata operations and their attributions and meanings

    4.2.2 測試結(jié)果

    從圖9 來看:RUFS 在F-creat 和F-remove 兩個操作上,與NFS+ext4 的性能大致相同;在其他元數(shù)據(jù)操作上,RUFS 都具有顯著的優(yōu)勢,取得了至少70%的提升;特別對于D-creat 操作,RUFS 相對于NFS+ext4 有大約5 693.8%的性能提升。橫向?qū)Ρ萊UFS各個元數(shù)據(jù)操作的性能,F(xiàn)-creat和F-remove由于需要在Blobstore 上進行多次操作,因此性能顯著低于其他元數(shù)據(jù)操作。F-read 操作包含了一次open 操作和一次close 操作,且需要訪問Blobstore,因此性能也同樣較差。

    圖9 RUFS與NFS+ext4元數(shù)據(jù)性能的比較Fig.9 Metadata performance comparison of RUFS and NFS+ext4

    4.2.3 SPDK為元數(shù)據(jù)帶來的性能提升

    為了達到同步語義,RUFS在使用RocksDB 時會打開同步模式,這會導致RocksDB的寫入性能大幅下降。SPDK能夠為存儲應(yīng)用帶來更低的延遲、更高的吞吐性能。通過將RocksDB 的存儲環(huán)境替換為優(yōu)化后的BlobFS,RocksDB 的同步寫性能有了很大的提升,并且讀性能沒有受到影響。本節(jié)將展示BlobFS對元數(shù)據(jù)性能的影響。

    圖10 展示了RUFS 元數(shù)據(jù)性能在RocksDB 在不同配置(同步模式或組提交模式,分別記為sync 和group-commit)、不同存儲環(huán)境下(文件系統(tǒng)或BlobFS,分別記為fs和SPDK)的結(jié)果。從非同步模式切換為同步模式,無論存儲環(huán)境是BlobFS還是文件系統(tǒng),涉及到RocksDB寫入的元數(shù)據(jù)操作,都會有明顯的性能下降。在BlobFS 環(huán)境下,creat 操作性能損耗最大,大約為38.8%,但由于原本性能很好,因此性能依然可以接受。存儲環(huán)境為本地文件系統(tǒng)時,元數(shù)據(jù)操作的性能損耗變得不可接受,性能損耗最多的元數(shù)據(jù)操作依然是creat,損耗比例高達98.7%,基本處于不可用的狀態(tài)。其他元數(shù)據(jù)操作,除了D-stat 與F-stat 不發(fā)生RocksDB 寫入,不受同步模式的影響,其他操作的OPS都小于2 500。

    圖10 SPDK對元數(shù)據(jù)操作的性能的影響Fig.10 Impact of SPDK on metadata operation performance

    4.3 數(shù)據(jù)性能

    本節(jié)將討論RUFS、NFS-ext4、RUFS-server 和ext4 在4 KB隨機讀寫延遲、4 KB 隨機讀寫吞吐、4 MB 順序讀寫吞吐幾個場景上的性能。由于當前RUFS 還沒有加入對緩存的支持,因此在對ext4 進行測量時,盡量消除了緩存對ext4 的影響。ext4 的寫入包括兩個項目:ext4-direct 和ext4-sync。前者在打開文件時,使用了O_DIRECT 選項,避免數(shù)據(jù)寫入到緩存;后者在打開文件時使用了O_SYNC 選項,保證寫入數(shù)據(jù)能夠持久化到硬盤。需要說明的是,由于O_SYNC 選項不影響讀操作,因此在測試讀性能時,ext4-sync 與ext4-direct 會使用同一個數(shù)據(jù)。RUFS-server 仍然使用16 個RPC 處理線程,用1 塊SSD管理元數(shù)據(jù),1塊SSD管理數(shù)據(jù)。

    4.3.1 延遲

    測量了RUFS-server、ext4-sync、ext4-direct、RUFS、NFS+ext4的4 KB 隨機讀寫的延遲,圖11展示了測試結(jié)果。從結(jié)果上來看,RUFS-server 的讀延遲,大約只有ext4 的20%。在網(wǎng)絡(luò)環(huán)境下,RUFS 總體的讀延遲,只有NFS+ext4 的26%左右。而對于本地寫性能,RUFS-server 僅略快于ext4-direct,但要注意,ext4-direct 并不保證操作返回時,能將數(shù)據(jù)持久化在硬盤上。提供這一保證的ext4-sync,寫延遲則是RUFS-server 的近60 倍,在網(wǎng)絡(luò)環(huán)境下,RUFS 總體的寫延遲也遠遠小過NFS+ext4。

    圖11 RUFS與NFS+ext4關(guān)于4 KB隨機訪問的延遲Fig.11 4 KB random access latency of RUFS and NFS+ext4

    4.3.2 吞吐

    吞吐性能測試包括了4 KB 隨機讀寫和4 MB 順序讀寫兩個項目。圖12 展示了4 KB 隨機讀寫吞吐性能的結(jié)果。這個結(jié)果和延遲測試類似,RUFS-server 在讀寫性能上,都遠遠地超過了ext4-sync,同時略強于不提供持久化保證的ext4-direct。總體性能上,RUFS 讀性能是NFS+ext4 的3 倍以上,寫性能是NFS+ext4的8倍以上。

    圖12 NFS+ext4與RUFS關(guān)于4 KB隨機訪問的吞吐性能Fig.12 4 KB random access bandwidth of NFS+ext4 and RUFS

    在4 MB 的順序讀寫上,ext4 與RUFS 的差距就相對小了一些。沒有網(wǎng)絡(luò)參與時,無論是讀還是寫,RUFS-server 均快于ext4,但性能提升不超過30%。但值得注意的是,在大文件的順序讀寫中,RUFS 的總體性能與RUFS-server 的吞吐性能幾乎持平,這意味著網(wǎng)絡(luò)傳輸提供了足夠高的帶寬,沒有成為整個系統(tǒng)的瓶頸。

    圖13 RUFS與NFS+ext4關(guān)于4 MB順序訪問的吞吐性能Fig.13 4 MB sequential access bandwidth of RUFS and NFS+ext4

    4.3.3 多SSD帶來的性能提升

    RUFS-server默認只用1個SSD管理數(shù)據(jù),因此也只使用1個reactor 線程管理讀寫請求。如果使用多個SSD 管理數(shù)據(jù),RUFS-server 就能啟動多個reactor 處理讀寫請求,這能夠提升RUFS-server 的吞吐性能。圖14 展示了RUFS-server 在多塊SSD下吞吐性能的提升。當使用6塊SSD管理數(shù)據(jù)時,通過將文件分散到各塊SSD,并用6 個reactor 同時處理讀寫請求,RUFS-server的吞吐性能能獲得246%到450%的提升。

    圖14 多SSD為RUFS-server帶來的加速比Fig.14 Speedup ratio brought by multi-SSD on RUFS-server

    5 結(jié)語

    本文設(shè)計并實現(xiàn)了一個基于高速網(wǎng)絡(luò)和NVMe SSD 的用戶態(tài)網(wǎng)絡(luò)文件系統(tǒng),RUFS。RUFS 利用RocksDB 管理元數(shù)據(jù),利用Blobstore 管理數(shù)據(jù),使用RDMA 技術(shù)對外提供服務(wù)。RUFS 充分地利用了NVMe SSD 的性能,所有的存儲過程都通過SPDK 提供的NVMe 驅(qū)動運行在用戶態(tài)。RUFS 在隨機讀寫、順序讀寫和元數(shù)據(jù)性能上,相較于NFS+ext4 都有十分明顯的優(yōu)勢。除此之外,RUFS 還具備同步語義,能夠保證用戶請求返回后,數(shù)據(jù)就已經(jīng)被持久化到硬盤當中。

    通過RUFS 的開發(fā)和測試,也充分證明了SPDK 在存儲領(lǐng)域的潛力,尤其是保證數(shù)據(jù)可靠寫入、并持久化在硬盤的性能,明顯地好于本地文件系統(tǒng)。因此SPDK 也十分適合于開發(fā)對存儲持久性要求較高的應(yīng)用,例如關(guān)系型數(shù)據(jù)庫的存儲引擎。

    猜你喜歡
    句柄鍵值服務(wù)器端
    非請勿進 為注冊表的重要鍵值上把“鎖”
    淺析異步通信層的架構(gòu)在ASP.NET 程序中的應(yīng)用
    成功(2018年10期)2018-03-26 02:56:14
    高校圖書館持久標識符應(yīng)用研究
    一鍵直達 Windows 10注冊表編輯高招
    電腦愛好者(2017年9期)2017-06-01 21:38:08
    編譯程序語法分析句柄問題分析與探討
    在Windows中安裝OpenVPN
    MFC應(yīng)用程序多線程混合顯示界面方法研究
    基于SPY++的軟件功能擴展的研究
    網(wǎng)頁防篡改中分布式文件同步復制系統(tǒng)
    注冊表值被刪除導致文件夾選項成空白
    国产黄片美女视频| 国产亚洲精品久久久com| 三级毛片av免费| 国产乱人视频| 国产伦理片在线播放av一区 | 日本在线视频免费播放| 国产又黄又爽又无遮挡在线| 国产精品嫩草影院av在线观看| 国产日本99.免费观看| 精品日产1卡2卡| 成人综合一区亚洲| 国产伦一二天堂av在线观看| 国产精品一区二区性色av| 2021天堂中文幕一二区在线观| 亚洲欧洲国产日韩| 成人国产麻豆网| 久久人人爽人人爽人人片va| 我要搜黄色片| 国产精品久久久久久精品电影小说 | 亚洲美女搞黄在线观看| av又黄又爽大尺度在线免费看 | 日本成人三级电影网站| 日韩欧美 国产精品| 久久久午夜欧美精品| 久久久午夜欧美精品| 久久精品综合一区二区三区| 亚洲av免费在线观看| 国产成人精品久久久久久| 亚洲国产精品成人久久小说 | 久久99热这里只有精品18| 亚洲人成网站在线播| 禁无遮挡网站| 成年免费大片在线观看| 国产高清三级在线| 久久久久久久久久成人| 女同久久另类99精品国产91| 免费观看a级毛片全部| avwww免费| 亚洲欧美日韩东京热| 欧美成人一区二区免费高清观看| 国产一区二区亚洲精品在线观看| 日本黄大片高清| 联通29元200g的流量卡| 国产精品久久视频播放| 国内精品一区二区在线观看| 久久久a久久爽久久v久久| 联通29元200g的流量卡| 在线天堂最新版资源| 自拍偷自拍亚洲精品老妇| 看非洲黑人一级黄片| 波多野结衣高清作品| 偷拍熟女少妇极品色| 亚洲欧美清纯卡通| 欧美高清性xxxxhd video| 国产午夜精品一二区理论片| 久久精品夜色国产| 成人一区二区视频在线观看| 久久久久久久久久久免费av| 网址你懂的国产日韩在线| 三级国产精品欧美在线观看| 波野结衣二区三区在线| 成人国产麻豆网| a级毛片免费高清观看在线播放| 国产精品久久久久久av不卡| 婷婷色av中文字幕| 精品久久久噜噜| 99视频精品全部免费 在线| 国产极品天堂在线| 国产精品国产三级国产av玫瑰| 成人漫画全彩无遮挡| 毛片女人毛片| 亚洲av成人精品一区久久| 搞女人的毛片| 午夜福利在线在线| 亚洲av男天堂| av女优亚洲男人天堂| 国产91av在线免费观看| 伦精品一区二区三区| 国产极品精品免费视频能看的| 日日啪夜夜撸| 亚洲aⅴ乱码一区二区在线播放| 非洲黑人性xxxx精品又粗又长| 久久精品国产鲁丝片午夜精品| 亚洲av中文字字幕乱码综合| 黄色欧美视频在线观看| 成人高潮视频无遮挡免费网站| 在线天堂最新版资源| 久久人人精品亚洲av| 亚洲av免费在线观看| 欧美在线一区亚洲| 久久久久性生活片| 久久久久久久亚洲中文字幕| 亚洲精品456在线播放app| 成人漫画全彩无遮挡| 日韩欧美精品v在线| 麻豆一二三区av精品| 欧美xxxx性猛交bbbb| 国产黄片视频在线免费观看| 亚洲欧美精品专区久久| av在线观看视频网站免费| 丰满人妻一区二区三区视频av| 女人十人毛片免费观看3o分钟| 精品人妻熟女av久视频| 青春草视频在线免费观看| 欧美精品一区二区大全| 久久久久久伊人网av| 一级二级三级毛片免费看| 亚洲欧美中文字幕日韩二区| 级片在线观看| 精品不卡国产一区二区三区| 91麻豆精品激情在线观看国产| а√天堂www在线а√下载| 欧美色欧美亚洲另类二区| 国内精品久久久久精免费| 国产精品乱码一区二三区的特点| 成人毛片60女人毛片免费| 国产精品av视频在线免费观看| 超碰av人人做人人爽久久| 非洲黑人性xxxx精品又粗又长| 久久久久久久亚洲中文字幕| 午夜福利在线观看免费完整高清在 | 国产一区二区三区在线臀色熟女| 乱系列少妇在线播放| 老女人水多毛片| 黄色一级大片看看| 在线观看66精品国产| 国产蜜桃级精品一区二区三区| 一个人免费在线观看电影| 国产人妻一区二区三区在| 亚洲第一电影网av| 大又大粗又爽又黄少妇毛片口| 精品一区二区三区人妻视频| 国产亚洲91精品色在线| 中国美女看黄片| 日本撒尿小便嘘嘘汇集6| 国产av麻豆久久久久久久| 在线天堂最新版资源| 国产高清激情床上av| 国产精品一区二区三区四区久久| 日本撒尿小便嘘嘘汇集6| 国产伦精品一区二区三区四那| 国产熟女欧美一区二区| 99热网站在线观看| 99热全是精品| 免费av观看视频| 永久网站在线| 99九九线精品视频在线观看视频| 久久人人爽人人片av| 大又大粗又爽又黄少妇毛片口| 国产高清不卡午夜福利| 久久人人爽人人爽人人片va| 国产美女午夜福利| av在线老鸭窝| 国产亚洲精品久久久久久毛片| 精品午夜福利在线看| 能在线免费看毛片的网站| 九九爱精品视频在线观看| 麻豆成人av视频| 国内揄拍国产精品人妻在线| 99久久无色码亚洲精品果冻| 日本三级黄在线观看| 波多野结衣巨乳人妻| 91久久精品电影网| 国产一区二区三区在线臀色熟女| 中国美女看黄片| 成人欧美大片| 午夜福利在线在线| 99九九线精品视频在线观看视频| 国产大屁股一区二区在线视频| 免费av不卡在线播放| 成人国产麻豆网| 99国产精品一区二区蜜桃av| 色尼玛亚洲综合影院| 黄色一级大片看看| 国产精品久久久久久精品电影| 给我免费播放毛片高清在线观看| 国产成人午夜福利电影在线观看| 国内少妇人妻偷人精品xxx网站| 国产蜜桃级精品一区二区三区| 国产成人a∨麻豆精品| 老女人水多毛片| 在线观看免费视频日本深夜| 一区福利在线观看| 黄片wwwwww| 蜜臀久久99精品久久宅男| 成人亚洲欧美一区二区av| 婷婷亚洲欧美| 尾随美女入室| 少妇熟女aⅴ在线视频| 国产熟女欧美一区二区| 欧美+日韩+精品| 国产日韩欧美在线精品| 日韩欧美国产在线观看| 精品熟女少妇av免费看| 国产av不卡久久| 国产精品日韩av在线免费观看| 在线观看一区二区三区| 亚洲一级一片aⅴ在线观看| 国产一区二区激情短视频| 成人无遮挡网站| 亚洲国产精品久久男人天堂| 天堂中文最新版在线下载 | 日本成人三级电影网站| 丰满人妻一区二区三区视频av| 亚洲av熟女| 又爽又黄a免费视频| 精品不卡国产一区二区三区| 国产高清视频在线观看网站| 51国产日韩欧美| 精品少妇黑人巨大在线播放 | 国内揄拍国产精品人妻在线| 亚洲精品影视一区二区三区av| 免费黄网站久久成人精品| 老熟妇乱子伦视频在线观看| 91麻豆精品激情在线观看国产| 久久人人爽人人片av| 91狼人影院| 亚洲成人精品中文字幕电影| 日日摸夜夜添夜夜爱| 又黄又爽又刺激的免费视频.| 亚洲中文字幕一区二区三区有码在线看| 精品午夜福利在线看| 亚洲国产精品成人久久小说 | 波多野结衣高清作品| 亚洲最大成人手机在线| 麻豆一二三区av精品| 日韩制服骚丝袜av| 久久精品夜色国产| 少妇高潮的动态图| 97在线视频观看| 久久久久性生活片| 色综合色国产| 亚洲av免费在线观看| 99riav亚洲国产免费| 精品久久久噜噜| 日韩人妻高清精品专区| 欧美性感艳星| 熟女人妻精品中文字幕| 中文亚洲av片在线观看爽| 五月玫瑰六月丁香| 青春草国产在线视频 | 亚洲精品亚洲一区二区| 99国产极品粉嫩在线观看| 三级经典国产精品| 亚洲人成网站在线播放欧美日韩| 久久久久久久久久久免费av| 在线观看66精品国产| 亚洲激情五月婷婷啪啪| 亚洲av.av天堂| а√天堂www在线а√下载| 少妇熟女欧美另类| 老熟妇乱子伦视频在线观看| 国产亚洲91精品色在线| 日韩亚洲欧美综合| 看十八女毛片水多多多| 少妇的逼好多水| 精品人妻熟女av久视频| 国产精品国产高清国产av| 成年女人永久免费观看视频| 亚洲欧美精品综合久久99| 国产黄片美女视频| 国产亚洲91精品色在线| 亚洲不卡免费看| 中文亚洲av片在线观看爽| 婷婷六月久久综合丁香| 99热只有精品国产| 麻豆国产97在线/欧美| 日产精品乱码卡一卡2卡三| 亚洲中文字幕一区二区三区有码在线看| 小说图片视频综合网站| 中文精品一卡2卡3卡4更新| 国产精品美女特级片免费视频播放器| 亚洲在久久综合| 精品久久久久久久久av| 中出人妻视频一区二区| 你懂的网址亚洲精品在线观看 | 99热精品在线国产| 欧美日韩一区二区视频在线观看视频在线 | 国产成人a区在线观看| 黄色配什么色好看| 中文字幕熟女人妻在线| 亚洲av电影不卡..在线观看| 国内精品美女久久久久久| 夜夜爽天天搞| 亚洲av中文字字幕乱码综合| 男女做爰动态图高潮gif福利片| 亚洲欧美清纯卡通| 一个人看的www免费观看视频| 免费电影在线观看免费观看| 成年免费大片在线观看| 久99久视频精品免费| 亚洲在久久综合| 少妇被粗大猛烈的视频| 亚洲成人久久爱视频| 久久亚洲国产成人精品v| 村上凉子中文字幕在线| 日日摸夜夜添夜夜爱| 男女那种视频在线观看| 2022亚洲国产成人精品| 日韩成人av中文字幕在线观看| 国产成人精品一,二区 | 岛国在线免费视频观看| 国产69精品久久久久777片| 黄色日韩在线| 精品午夜福利在线看| 一进一出抽搐动态| 久久久久久久久中文| 我的女老师完整版在线观看| 欧美xxxx性猛交bbbb| 亚洲欧美成人精品一区二区| www.色视频.com| 能在线免费观看的黄片| 日本熟妇午夜| 在线观看一区二区三区| 乱系列少妇在线播放| 国产午夜精品论理片| 成人三级黄色视频| 色视频www国产| 黄色日韩在线| 欧美性猛交╳xxx乱大交人| 啦啦啦观看免费观看视频高清| 国产不卡一卡二| 精品一区二区三区视频在线| 欧美潮喷喷水| 99热网站在线观看| 啦啦啦啦在线视频资源| ponron亚洲| 高清毛片免费观看视频网站| 国产伦一二天堂av在线观看| 又粗又硬又长又爽又黄的视频 | 日本一本二区三区精品| 黄片无遮挡物在线观看| 能在线免费看毛片的网站| 日韩视频在线欧美| 日韩精品有码人妻一区| 久久精品夜色国产| 伦理电影大哥的女人| 亚洲国产欧洲综合997久久,| 乱码一卡2卡4卡精品| 成年版毛片免费区| 日本免费a在线| 亚洲无线观看免费| 天美传媒精品一区二区| 九草在线视频观看| 69av精品久久久久久| 国产精品99久久久久久久久| 青青草视频在线视频观看| 欧美日本视频| 嫩草影院精品99| 精品久久久久久久人妻蜜臀av| 国产精品一区二区三区四区久久| 99热精品在线国产| 久久人人爽人人爽人人片va| 免费一级毛片在线播放高清视频| 国产一区二区激情短视频| 成人欧美大片| 狂野欧美激情性xxxx在线观看| 国产在线男女| 一级二级三级毛片免费看| 精品久久久久久成人av| 久久人人精品亚洲av| 久久国内精品自在自线图片| 美女脱内裤让男人舔精品视频 | 亚洲熟妇中文字幕五十中出| 国产精品无大码| 午夜a级毛片| 免费观看人在逋| 简卡轻食公司| 亚洲精华国产精华液的使用体验 | av国产免费在线观看| 变态另类丝袜制服| 人妻系列 视频| 全区人妻精品视频| 亚洲七黄色美女视频| 国产成人精品一,二区 | 亚洲国产精品久久男人天堂| 久久精品国产亚洲av涩爱 | 在线观看免费视频日本深夜| 婷婷色综合大香蕉| 国产精品嫩草影院av在线观看| 久久鲁丝午夜福利片| 床上黄色一级片| 国产成人a∨麻豆精品| 少妇熟女欧美另类| 校园春色视频在线观看| 国产亚洲精品av在线| 色综合亚洲欧美另类图片| 桃色一区二区三区在线观看| 麻豆久久精品国产亚洲av| 亚洲va在线va天堂va国产| 亚洲欧美日韩东京热| 综合色av麻豆| 免费黄网站久久成人精品| 亚洲美女视频黄频| 国产精品伦人一区二区| 国产免费一级a男人的天堂| 国产精品久久久久久精品电影小说 | 看黄色毛片网站| 国语自产精品视频在线第100页| 看非洲黑人一级黄片| 九色成人免费人妻av| 免费观看的影片在线观看| 日韩国内少妇激情av| 亚洲国产欧美人成| 成人美女网站在线观看视频| eeuss影院久久| 亚洲美女搞黄在线观看| 97人妻精品一区二区三区麻豆| 亚洲四区av| 三级国产精品欧美在线观看| 禁无遮挡网站| 成人高潮视频无遮挡免费网站| 少妇猛男粗大的猛烈进出视频 | 永久网站在线| 免费搜索国产男女视频| 联通29元200g的流量卡| 亚洲欧洲日产国产| 青春草国产在线视频 | 国产午夜精品一二区理论片| 99久久九九国产精品国产免费| 在线a可以看的网站| 国产伦理片在线播放av一区 | 亚洲自拍偷在线| 日韩欧美三级三区| 日本一二三区视频观看| 久久人妻av系列| 一级黄色大片毛片| 久久久成人免费电影| 人妻系列 视频| 一个人看的www免费观看视频| 精品久久国产蜜桃| 国产乱人偷精品视频| 国产精品无大码| 久久久色成人| 中文亚洲av片在线观看爽| 欧美激情在线99| 国产午夜精品论理片| 九九热线精品视视频播放| 国产成人精品一,二区 | 久久国内精品自在自线图片| 亚洲人成网站高清观看| 亚洲欧美精品自产自拍| 国产成年人精品一区二区| 国产精品一及| 一个人免费在线观看电影| 老司机影院成人| 搞女人的毛片| 一级二级三级毛片免费看| 看黄色毛片网站| 国产精品三级大全| 联通29元200g的流量卡| 国产成年人精品一区二区| 久久草成人影院| 国产精品1区2区在线观看.| 又粗又硬又长又爽又黄的视频 | 精品不卡国产一区二区三区| 最近中文字幕高清免费大全6| 夫妻性生交免费视频一级片| 99久久无色码亚洲精品果冻| 欧美激情久久久久久爽电影| 九九热线精品视视频播放| 免费观看精品视频网站| 91麻豆精品激情在线观看国产| 男人狂女人下面高潮的视频| 99久久精品热视频| 老师上课跳d突然被开到最大视频| 亚洲精品日韩av片在线观看| 九九爱精品视频在线观看| 亚洲成人精品中文字幕电影| 色视频www国产| 此物有八面人人有两片| 又爽又黄无遮挡网站| 日本五十路高清| 国产黄色视频一区二区在线观看 | 国产精品国产高清国产av| 成人午夜高清在线视频| 精品少妇黑人巨大在线播放 | 丝袜美腿在线中文| av在线亚洲专区| 久久6这里有精品| 亚洲在线观看片| 亚洲av.av天堂| 国产精品永久免费网站| 国产伦精品一区二区三区视频9| 亚洲一区高清亚洲精品| 亚洲真实伦在线观看| 熟女人妻精品中文字幕| 天天躁夜夜躁狠狠久久av| 女人被狂操c到高潮| 麻豆成人午夜福利视频| 欧美最新免费一区二区三区| 国产高清有码在线观看视频| 在线天堂最新版资源| 国产成人影院久久av| av福利片在线观看| 成人漫画全彩无遮挡| 亚洲欧美日韩东京热| 天美传媒精品一区二区| 免费人成在线观看视频色| or卡值多少钱| 日韩在线高清观看一区二区三区| or卡值多少钱| 91精品一卡2卡3卡4卡| 18禁在线播放成人免费| 国产精品不卡视频一区二区| АⅤ资源中文在线天堂| 尤物成人国产欧美一区二区三区| 免费av毛片视频| 最近的中文字幕免费完整| 久久精品国产自在天天线| 老司机福利观看| 中文欧美无线码| 久久久久九九精品影院| 女同久久另类99精品国产91| 我要搜黄色片| 久久久久性生活片| 国产精品一区二区三区四区免费观看| 亚洲国产精品sss在线观看| 日韩欧美三级三区| 超碰av人人做人人爽久久| 午夜免费男女啪啪视频观看| 日韩av在线大香蕉| 老熟妇乱子伦视频在线观看| 少妇猛男粗大的猛烈进出视频 | 性插视频无遮挡在线免费观看| 一个人看的www免费观看视频| 变态另类丝袜制服| 99在线视频只有这里精品首页| 欧美日韩一区二区视频在线观看视频在线 | 国产成人精品久久久久久| 少妇猛男粗大的猛烈进出视频 | 草草在线视频免费看| 99热这里只有精品一区| 爱豆传媒免费全集在线观看| 欧美潮喷喷水| 国国产精品蜜臀av免费| 真实男女啪啪啪动态图| 国产精品精品国产色婷婷| 国产探花极品一区二区| 国产精品久久久久久av不卡| 小说图片视频综合网站| 校园人妻丝袜中文字幕| 国产伦在线观看视频一区| 男人的好看免费观看在线视频| 天堂中文最新版在线下载 | 亚洲国产精品成人久久小说 | 中文字幕精品亚洲无线码一区| 一进一出抽搐gif免费好疼| 国产美女午夜福利| 男女啪啪激烈高潮av片| 校园春色视频在线观看| 国产私拍福利视频在线观看| 亚洲人成网站在线观看播放| 国产精品爽爽va在线观看网站| 国产精品爽爽va在线观看网站| 欧美xxxx性猛交bbbb| h日本视频在线播放| 日韩av在线大香蕉| 看十八女毛片水多多多| 欧美日韩乱码在线| 国产伦理片在线播放av一区 | 一区二区三区免费毛片| 精品熟女少妇av免费看| 精品人妻熟女av久视频| av在线观看视频网站免费| 极品教师在线视频| 欧美bdsm另类| 免费黄网站久久成人精品| 欧美+亚洲+日韩+国产| 欧洲精品卡2卡3卡4卡5卡区| 久久久久久久午夜电影| 国产精品一区二区在线观看99 | 有码 亚洲区| 黄色日韩在线| 久久99热6这里只有精品| 亚洲自偷自拍三级| 国产伦在线观看视频一区| 精品欧美国产一区二区三| 3wmmmm亚洲av在线观看| 欧美变态另类bdsm刘玥| 亚洲欧美清纯卡通| eeuss影院久久| 小蜜桃在线观看免费完整版高清| 99久久无色码亚洲精品果冻| av天堂在线播放| 国产日韩欧美在线精品| 亚洲av第一区精品v没综合| ponron亚洲| 又爽又黄a免费视频| 少妇裸体淫交视频免费看高清| 国产极品精品免费视频能看的| 熟女人妻精品中文字幕| 日韩制服骚丝袜av| 欧美+日韩+精品| 日韩亚洲欧美综合| 男女做爰动态图高潮gif福利片| 人人妻人人看人人澡| 99久久精品国产国产毛片| 村上凉子中文字幕在线| 国产精品蜜桃在线观看 | 国产成人福利小说| 人人妻人人看人人澡| 久久精品综合一区二区三区| 日韩在线高清观看一区二区三区| 99九九线精品视频在线观看视频| 少妇熟女aⅴ在线视频| 69人妻影院| 国内精品一区二区在线观看| 男女视频在线观看网站免费| 国产精品一区二区在线观看99 | 久久精品国产亚洲av香蕉五月| 看黄色毛片网站| 日本欧美国产在线视频| 草草在线视频免费看| 久久久久久久久久成人|