日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

PolarFS :一个用于共享存储云数据库的超低延迟和容错分布式文件系统

發布時間:2024/2/28 windows 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PolarFS :一个用于共享存储云数据库的超低延迟和容错分布式文件系统 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

1.?簡介

2.?背景

3.?架構?

4. I/O 執行模型

5.?一致性模型

6. FS中層的實現

7. 設計選擇和經驗教訓

8. 價值評估

9. 相關工作

10. 結論


PolarFS : An Ultra-low Latency and Failure Resilient?Distributed File System for Shared Storage Cloud Database

PolarFS :一個用于共享存儲云數據庫的超低延遲和容錯分布式文件系統

?

摘要

PolarFS 是一個具有超低延遲和高可用性的分布式文件系統,專為?POLARDB 數據庫服務而設計,目前已在阿里云上提供。?PolarFS 在用戶空間中利用了輕量級網絡堆棧和?I/O 堆棧,充分利用了?RDMA、NVMe??SPDK?等新興技術。通過這種方式,PolarFS 的端到端延遲大大降低,實驗表明?PolarFS 的寫入延遲與?SSD 上本地文件系統的寫入延遲非常接近。為了在保證?PolarFS 的副本一致性的同時最大限度地提高?I/O 吞吐量,我們開發了?ParallelRaft?協議,它利用數據庫的無序?I/O 完成容能力,打破了?Raft 的嚴格串行化。ParallelRaft 繼承了?Raft 的可理解性和易于實現,同時為?PolarFS 提供了更好的?I/O 可伸縮性。我們還描述了?PolarFS 的共享存儲體系結構,它為?POLARDB 提供了強大的支持。

?

?

1.?簡介

近年來存儲與計算的分離已成為云計算產業的發展趨勢。這種設計使得體系結構更加靈活,有助于開發共享存儲能力:(1)?計算和存儲節點可以使用不同類型的服務器硬件,并且可以單獨定制。例如,計算節點不再需要考慮內存大小與磁盤容量的比率,這是高度依賴于應用場景的,并且很難預測。(2)?群集中存儲節點上的磁盤可以形成單個存儲池,這樣可以降低碎片化、節點間磁盤使用不平衡和空間浪費的風險。存儲集群的容量和吞吐量可以很容易地透明地擴展。(3)?由于數據都存儲在存儲集群上,所以計算節點上沒有本地持久狀態,這使得執行數據庫遷移更容易、更快。分布式存儲系統的高可靠性和其他特性也可以提高數據的可靠性。

云數據庫服務也受益于此架構。首先,數據庫可以基于虛擬化技術(如 Xen[4]、KVM[19] 或 Docker[26])構建一個更安全、更易于擴展的環境。其次,在后端存儲集群的支持下,可以增強數據庫的一些關鍵特性,如多個只讀實例和檢查點,后端存儲集群提供快速?I/O 、數據共享和快照。

然而,數據存儲技術仍在快速變化,因此當前的云平臺很難充分利用?RDMA??NVMe?SSD?等新興硬件標準。例如,一些廣泛使用的開源分布式文件系統,如?HDFS[5] 和?Ceph[35],被發現比本地磁盤有更高的延遲。當使用最新的 PCIe?SSD 時,性能差距甚至可能達到數量級。直接在這些存儲系統上運行的關系數據庫(如MySQL)的性能明顯低于具有相同CPU和內存配置的本地?PCIe-SSD

為了解決這個問題,AWS、Google 云平臺和阿里云等云計算廠商提供了實例存儲( instance store )。實例存儲使用本地?SSD?和高?I/O 虛擬機實例來滿足客戶對高性能數據庫的需求。不幸的是,在實例存儲上運行云數據庫有幾個缺點。首先,實例存儲容量有限,不適合大型數據庫服務。其次,它無法在磁盤驅動器故障中生存。為了保證數據的可靠性,數據庫必須自己管理數據復制。第三,實例存儲使用通用文件系統,如?ext4??XFS。當使用低?I/O 延遲硬件(如RDMA或PCIe?SSD)時,內核空間和用戶空間之間的消息傳遞成本會影響?I/O 吞吐量。更糟糕的是,實例存儲不能支持共享一切數據庫集群架構,這是高級云數據庫服務的一個關鍵特性。

在本文中,我們描述了我們的分布式文件系統?PolarFS 的設計和實現,它通過以下機制提供超低延遲、高吞吐量和高可用性。首先,PolarFS 會完全利用?RDMA??NVMe ?SSD ?等新興硬件的優勢,在用戶空間實現了一個輕量級的網絡堆棧和?I/O 堆棧,以避免陷入內核和處理內核鎖。第二,PolarFS 提供了一個類似?POSIX 的文件系統?API,目的是編譯到數據庫進程中,替換操作系統提供的文件系統接口,使整個?I/O 路徑都能保存在用戶空間中。第三,PolarFS 數據層面的?I/O 模型也被設計用來消除鎖和避免關鍵數據路徑上的上下文切換:所有不必要的內存副本也被消除,同時?DMA?被大量用于在主內存和?RDMA NIC/NVMe?磁盤之間傳輸數據。有了這些特性,PolarFS 的端到端延遲大大降低,與?SSD?上的本地文件系統非常接近。

部署在云生產環境中的分布式文件系統通常有數千臺計算機。在這樣的規模內,由硬件或軟件缺陷引起的故障是常見的。因此,需要一個一致協議來確保所有已提交的修改不會丟失,并且副本始終可以達到位相同一致的級別

Paxos?家族[23,22,7,18,38]的協議是公認的能用于解決問題的共識機制Raft[28],Paxos?的一個變種,更容易理解和實現。許多分布式系統都是基于?Raft 開發的。然而,一旦?Raft 應用于?PolarFS ,我們發現?Raft 嚴重阻礙了?PolarFS 在使用超低延遲硬件時的?I/O 可擴展性(例如延遲在幾十微秒量級的?NVMe?SSD??RDMA)。因此,我們開發了基于?Raft 的增強一致性協議?ParallelRaft,它允許無序的日志確認、提交和應用,同時允許?PolarFS 遵循傳統的?I/O 語義。通過該協議,?PolarFS 的并行?I/O 并發性得到了顯著提高。

最后,在?PolarFS 的基礎上,我們實現了?POLARDB ,這是一個由?AliSQL(MySQL/InnoDB的分支)[2]修改而來的關系型數據庫系統,最近在阿里云計算平臺上作為一個數據庫服務提供。POLARDB 遵循共享存儲體系結構,支持多個只讀實例。?圖1?所示,POLARDB 的數據庫節點分為兩種類型:主節點? 只讀(RO)節點。主節點可以同時處理讀和寫查詢,而?RO?節點只提供讀查詢。主節點?RO?節點共享?PolarFS 中同一數據庫目錄下的?redo?日志文件和數據文件。

PolarFS 支持?POLARDB,具有以下特點:(1) PolarFS 可以將文件元數據的修改(如文件截斷或擴展、文件創建或刪除)從主節點同步到?RO?節點,使?RO?節點可以看到所有的更改。(2)?PolarFS 確保對文件元數據的并發修改被序列化,以便文件系統本身在所有數據庫節點上保持一致。(3)?在一個網絡分區的情況下,可能有兩個或多個節點作為主節點因為分區所以可能有多個主節點的情況下同時在?PolarFS 中寫入共享文件,PolarFS 可以確保只有真正的主節點被成功服務,防止數據損壞

本文的貢獻包括:

??我們描述了如何利用新興的硬件和軟件優化來構建?PolarFS,這是一種具有超低延遲的最先進分布式文件系統。(第3、4和7節)

??我們提?ParallelRaft,一個新的協議,以達成共識。ParallelRaft 是為大規模、容錯和分布式文件系統而設計的。在?Raft 的基礎上對其進行了修改,以適應存儲語義。與?Raft 相比,ParallelRaft ?PolarFS 中的高并發?I/O 提供了更好的支持。(第5節)

??我們介紹了?PolarFS 的關鍵特性,這些特性為?POLARDB 的共享存儲架構提供了強有力的支持。(第6節)

論文的其他部分結構如下。第 2 節介紹了?PolarFS 使用的新興硬件的背景信息。第 8 節介紹并討論了我們的實驗評估。第 9 節回顧相關工作,第 10 節總結全文。

?

?

2.?背景

本節簡要介紹?NVMe?SSD 、RDMA?及其相應的編程模型。

NVMe?SSDSSD?正在從?SAS、SATA?等傳統協議發展到具有高帶寬和低速率?I/O 互連的?NVMe。NVMe?SSD?可以以低于 100μs的延遲提供每秒?500K??I/O 操作(IOPS),最新的?3D XPoint?SSD?甚至將?I/O 延遲降低到 10μs 左右,同時提供比?NAND?SSD 更好的?QoS。隨著?SSD 越來越快,遺留內核?I/O 堆棧的開銷成為瓶頸[37,36,31]。正如之前的研究[6]所揭示的,僅完成一個?4KB??I/O 請求,就需要執行大約?20000?條指令。最近,Intel發布了存儲性能開發工具包(SPDKStorage Performance Development Kit)[12],這是一套工具和庫,用于構建基于?NVMe?設備的高性能、可擴展的用戶模式存儲應用程序。它通過將所有必需的驅動程序移入用戶空間并以輪詢模式操作而不是依賴中斷來獲得高性能,這避免了內核上下文切換并消除了中斷處理開銷。

RDMA?公司。RDMA?技術為數據中心內部服務器之間提供了一種低延遲的網絡通信機制。例如,在連接到同一交換機的兩個節點之間傳輸?4KB?的數據包大約需要?7μs,這比傳統的?TCP/IP?網絡棧要快得多。大量文獻[9,14,15,17,24,25,30]表明,RDMA?可以提高系統性能。應用程序通過?Verbs API?訪問隊列對(QP,Queue Pair)與?RDMA NIC?交互。QP?發送隊列接收隊列 組成,并且每個?QP?與另一個完成隊列(CQ,Completion Queue)相關聯。CQ?通常用作完成 事件/信號 的輪詢目標。

Send/Recv?操作通常稱為雙邊操作,因為每個?Send?操作都需要遠程進程調用匹配?Recv操作,而讀/寫操作稱為單邊操作,因為遠程內存由?NIC?操作,而不涉及任何遠程?CPU。

PolarFS 使用?Send/Recv??Read/Write?操作的混合體。小的有效載荷通過?Send/Recv?操作直接傳遞。對于大數據塊或一批數據,節點使用?Send/Recv?操作協商遠程節點上的目標內存地址,然后通過讀/寫操作完成實際的數據傳輸。PolarFS 通過在用戶空間中輪詢?CQ?而不是依賴中斷來消除上下文切換。

?

?

3.?架構?

PolarFS 由兩個主要層組成。下層是存儲管理,上層是文件系統元數據管理,提供文件系統API。存儲層負責存儲節點的所有磁盤資源,并為每個數據庫實例提供一個數據庫?volume。文件系統層支持?volume?中的文件管理,負責文件系統元數據并發訪問的互斥和同步。對于數據庫實例,PolarFS 將文件系統元數據存儲在其?volume?中。

這里我們展示?PolarFS 集群中的主要組件,如?圖2?所示。libpfs?是一個用戶空間文件系統實現庫,具有一組類似?POSIX 的文件系統?API,鏈接到?POLARDB 進程中;PolarSwitch?駐留在計算節點上,用于將?I/O 請求從應用程序重定向到?ChunkServer;ChunkServer 部署在存儲節點上以服務于?I/O 請求;PolarCtrl?是控制面板,它包括一組在微服務中實現的主節點,以及部署在所有計算和存儲節點上的代理。PolarCtrl?使用?MySQL?實例作為元數據存儲庫。

?

?

3.1 文件系統層

文件系統層提供了一個共享并行文件系統,設計為能夠由多個數據庫節點同時訪問。例如,在?POLARDB 的場景中,當主數據庫節點執行?create table DDL?語句時,將在?PolarFS 中創建一個新文件,使選擇在?RO?節點上執行的語句以訪問該文件。因此,需要跨節點同步對文件系統元數據的修改以保持一致性,同時序列化并發修改以避免元數據被破壞。

?

3.1.1?libpfs

libpfs?是一個完全在用戶空間中運行的輕量級文件系統實現。?圖3?所示,libpfs?提供了一個類似于?POSIX 的文件系統的 API。移植一個數據庫在?PolarFS 上運行非常容易。

當數據庫節點啟動時,pfs_mount?會連接到其?volume?并初始化文件系統狀態。volname?是分配給?POLARDB 實例的?volume?的全局標識符,hostid?是數據庫節點的索引,在磁盤?Paxos 投票算法中用作標識符(見6.2節)。在裝載過程中,libpfs??volume?中加載文件系統元數據,并在內存中構造數據結構,如目錄樹、文件映射表和 block 映射表(見第6.1節)。pfs_umount 在數據庫銷毀期間分離?volume?并釋放資源。在?volume?空間增長后,應該調用?pfs_mount_growfs?來識別新分配的 block 并將它們標記為可用。Rest?函數是相當于?POSIX API 中對應的文件和目錄操作。有關文件系統元數據管理的詳細信息,請參見第?6?節。

?

?

3.2 儲存層

存儲層為文件系統層提供管理和訪問?volume?的接口。為每個數據庫實例分配一個?volume,并由一組 chunk 組成。一個?volume?的容量從?10GB ?100TB?不等,可以滿足絕大多數數據庫的需求,并且可以根據需要在?volume?中添加 chunk 來擴展容量。一個?volume?可以像傳統的存儲設備一樣以?512B?的方式隨機訪問(讀、寫)。對單個?I/O 請求中攜帶的相同 chunk 的修改是原子性的。

Chunk。一個?volume?被分成?chunks,這些?chunk 分布在塊服務器之間。chunk 是數據分布的最小單位。一個?chunk 不會跨越?ChunkServer 上的多個磁盤,默認情況下,它的副本復制到三個不同的?ChunkServer (總是位于不同的機架中)。當存在熱點時,可以在?ChunkServer 之間遷移?chunk

?PolarFS 中,chunk 的大小被設置為10GB,這明顯大于其他系統中的單位大小,例如?GFS 使用的?64MB 塊大小[11]。這種選擇在數量級上減少了元數據數據庫中維護的元數據量,并且簡化了元數據管理。例如,100TB??volume?只包含?10000??chunk。在元數據數據庫中存儲?10000?條記錄的成本相對較小。此外,所有這些元數據都可以緩存在?PolarSwitch?的主內存中,從而避免了關鍵?I/O 路徑上額外的元數據訪問開銷。

這種設計的缺點是一個?chunk 上的熱點不能進一步分離。但是由于?chunk 與服務器的比率很高(現在大約是1000:1),通常有大量的數據庫實例(數千個或更多),以及服務器間的塊遷移能力,PolarFS 可以在整個系統級別實現負載平衡。

Block。chunk 在?ChunkServer 中進一步劃分為?block,每個?block?被設置為?64KB。block?按需分配并映射到?chunk,以實現精簡資源調配。一個?10GB 的數據?chunk 包含?163840?個數據?block。Chunk ?LBA (邏輯塊地址,線性地址范圍從?0??10GB )到?blocks 的映射表存儲在?ChunkServer 中,同時存儲每個磁盤上空閑?blocks 的位圖。單個?Chunk 的映射表占用?640KB 內存,非常小,可以緩存在?ChunkServer 的內存中。

?

3.2.1 PolarSwitch

PolarSwitch?是一個部署在數據庫服務器上的守護進程,以及一個或多個數據庫實例。在每個數據庫進程中,libpfs?將?I/O 請求轉發給?PolarSwitch?守護進程。每個請求都包含諸如?volume?標識符、偏移量和長度等尋址信息,從中可以識別出相關的 chunk。一個?I/O 請求可能跨越多個 chunk,在這種情況下,請求被進一步劃分為多個子請求。最后,一個基本請求被發送到?ChunkServer ,該?ChunkServer 位于 chunk 的頭所在的位置。

PolarSwitch?通過查找與?PolarCtrl?同步的本地元數據緩存來找出屬于一個 chunk 的所有副本的位置。一個群體的副本形成了一個共識體,一個是?Leader ,另一些是??Followers。只有?Leader?能響應?I/O 請求。共識小組的領導層變動也同步進行,并緩存在?PolarSwitch?的本地緩存中。如果發生響應超時,PolarSwitch?將繼續以指數后退方式重試,同時檢測是否發生?Leader 選舉,切換到新的?Leader,如果發生,立即重新傳輸。

?

3.2.2?ChunkServer

ChunkServers?部署在存儲服務器上。有多個?ChunkServer 進程運行在一個存儲服務器上,每個?ChunkServer 擁有一個獨立的?NVMe SSD 磁盤,并綁定到一個專用的?CPU?核心,因此兩個?ChunkServer 之間沒有資源爭用。ChunkServer 負責存儲 chunk 并提供對?chunk 的隨機訪問。每個?chunk 包含一個預寫日志Write-Ahead Log,WAL),對?chunk 的修改在更新 chunk blocks 之前附加到日志中,以確保原子性和持久性。ChunkServer 使用一塊固定大小的?3D?XPoint?SSD 緩沖區作為?WAL?的寫緩存,日志最好放在?3D?XPoint?緩沖區中。如果緩沖區已滿,ChunkServer 將嘗試回收已過期的日志。如果?3D?XPoint?緩沖區中仍然沒有足夠的空間,則將日志寫入?NVMe?SSD 。chunk blocks?最終會寫入?NVMe?SSD

ChunkServer 使用?ParallelRaft 協議相互復制?I/O 請求,并形成一個共識組。?ChunkServer 由于各種原因離開了它的共識組,可能會有不同的處理方式。有時是偶然的、暫時的故障造成的,比如網絡暫時不可用,或者服務器升級重啟。在這種情況下,最好等待斷開連接的?ChunkServer 恢復聯機,再次加入組并趕上其他組。在其他情況下,故障是永久性的或往往會持續很長時間,例如服務器損壞或離線。然后,丟失的?ChunkServer 上的所有塊都應該遷移到其他塊,以便重新獲得足夠數量的副本。

斷開連接的?ChunkServer 總是努力自動重新加入共識組,以縮短不可用時間。然而,PolarCtrl?可以做出補充決定。PolarCtrl?定期收集以前斷開連接的?ChunkServer 的列表,并從?ChunkServers 中挑選出似乎存在永久性故障的?ChunkServer。有時很難做出決定。例如,一個具有慢速磁盤的?ChunkServer 可能比其他服務器有更長的延遲,但它總是能夠響應存活探測。基于機器學習性能指標的機器學習算法是有用的。

?

3.2.3?PolarCtrl

PolarCtrl??PolarFS 集群控制面板。它部署在一組專用計算機(至少三臺)上,以提供高可用性服務。PolarCtrl?提供集群控制服務,如節點管理、volume 管理、資源分配、元數據同步、監控等。PolarCtrl?負責:(1)?跟蹤所有在群集中?ChunkServer 的成員和活躍度,如果?ChunkServer 過載或不可用的時間超過閾值,則開始將塊副本從一個服務器遷移到另一個服務器。(2)?維護元數據數據庫中所有?volume ?chunk 位置的狀態。(3)?創建?volume 并將?chunk 分配給?ChunkServers。(4) 同時使用?push??pull 方法將元數據同步到?PolarSwitch。(5) 監視每個?volume ?chunk 的延遲、IOPS?指標,沿?I/O 路徑收集跟蹤數據。(6) 定期安排內部副本和副本間的?CRC?檢查。

PolarCtrl?通過控制面板命令定期與?PolarSwitch?同步集群元數據(例如卷的塊位置)。PolarSwitch?將元數據保存在其本地緩存中。當收到來自?libpfs??I/O 請求時,PolarSwitch?根據本地緩存將請求路由到相應的?ChunkServer。偶爾,如果本地緩存落后于中心元數據存儲庫,PolarSwitch?會從?PolarCtrl?獲取元數據。

作為一個控制面板,PolarCtrl?不在關鍵?I/O 路徑上,它的服務連續性可以通過傳統的高可用性技術來實現。即使在?PolarCtrl?崩潰和恢復之間的短時間內,由于?PolarSwith?上緩存的元數據和?ChunkServer 的自我管理,PolarFS 中的?I/O 流也不太可能受到影響。

?

?

4. I/O 執行模型

?POLARDB 訪問其數據時,它將通過?PFS?接口(通常通過 pfs_pread?或 pfs_pwrite)將文件?I/O 請求委托給?libpfs。對于寫請求,幾乎不需要修改文件系統元數據,因為設備塊(device blocks)是通過?pfs_fallocate() 預先分配給文件的,從而避免了讀寫節點之間昂貴的元數據同步。這是數據庫系統的常規優化。

在大多數常見的情況下,libpfs 只是根據裝載時已經構建的索引表將文件偏移量映射到 block 偏移量中,并將文件 I/O 請求切割成一個或多個較小的固定大小?block?I/O 請求。在轉換之后,block I/O 請求通過它們之間的共享內存由 libpfs 發送到 PolarSwitch。

共享內存被構造成多個環形緩沖區。在共享內存的一端,libpfs??block I/O 請求排隊到以循環方式入隊到環形緩沖區中,然后等待其完成。在另一端,PolarSwitch?不斷地輪詢所有的環形緩沖區,其中一個線程專用于一個環形緩沖區。一旦找到新的請求,PolarSwitch?會將來自環形緩沖區的請求取消排隊,并使用從?PolarCtrl?傳播的路由信息將其轉發到?ChunkServer

ChunkServer 使用預寫日志(Write-Ahead Logging,WAL)技術來確保原子性和持久性,在提交和應用?I/O 請求之前,將它們寫入日志。日志被復制到一個副本集合中,并使用一個名為?ParallelRaft 的共識協議(將在下一節中詳細介紹)來保證副本之間的數據一致性。在將?I/O 請求持久地記錄到大多數副本的日志中之前,它不會被識別為已提交。只有在這之后,這個請求才能被響應到客戶端并應用于數據塊。

圖4?顯示了如何在?PolarFS 中執行寫?I/O 請求。(1) POLARDB 通過?PolarSwitch?和 libpfs?之間的環形緩沖區向?PolarSwitch?發送寫?I/O 請求。(2)?PolarSwitc 根據本地緩存的集群元數據將請求傳輸到相應?chunk ?Leader 節點。(3)?當新的寫入請求到達時,?Leader 節點中的?RDMA NIC?將把寫請求放入預先注冊的緩沖區,并將請求條目添加到請求隊列中。?I/O 循環線程不斷輪詢請求隊列。一旦它看到一個新的請求到達,它立即開始處理該請求。(4) 請求通過?SPDK?寫入磁盤上的日志塊,并通過?RDMA?傳播到?follower?節點。這兩個操作都是異步調用,實際的數據傳輸將并行觸發。(5) 當復制請求到達?follower?節點時,follower?節點中的RDMA NIC也會將復制請求放入預先注冊的緩沖區,并將其添加到復制隊列中。(6) 然后觸發?follower?上的?I/O 循環線程,并通過?SPDK?異步將請求寫入磁盤。(7) 當?write?回調成功返回時,一個確認響應將通過?RDMA?發送回?Leader。(8) 當大多數?follower 成功接收到響應時,Leader 通過?SPDK?向數據塊發出寫請求。(9) 之后,Leader 通過?RDMA?回復?PolarSwitch。(10) PolarSwitch?然后標記請求完成并通知客戶端。

?I/O 請求(更簡單地說)由?Leader 單獨處理。?ChunkServer 中有一個名為 IoScheduler?的子模塊,它負責仲裁并發?I/O 請求發出的磁盤?I/O 操作的順序,以便在?ChunkServer 上執行。IoScheduler?保證讀取操作始終可以檢索最新提交的數據。

ChunkServer 使用輪詢模式事件驅動的有限狀態機作為并發模型I/O 線程保持?RDMA??NVMe?隊列中的事件輪詢,在同一線程中處理傳入的請求。當發出一個或多個異步?I/O 操作并且需要處理其他請求時,I/O 線程將暫停處理當前請求并將上下文保存到狀態機中,然后切換到處理下一個傳入事件。每個?I/O 線程使用一個專用的內核,并使用分離的?RDMA??NVMe?隊列對。因此,即使在一個?ChunkServer 上有多個?I/O 線程,由于?I/O 線程之間沒有共享的數據結構,所以實現?I/O 線程時不會產生鎖開銷。

?

?

5.?一致性模型

5.1?Raft 修訂

用于生產分布式存儲系統需要一個共識協議,以保證在任何情況下都不會丟失所有已提交的修改。在設計過程的開始。考慮到實現的復雜性,我們選擇了?Raft 。然而,一些隱患很快就出現了。

Raft 的設計是高度序列化的,簡單易懂。它的日志不允許在?Leader ?Follower 上都有漏洞,這意味著日志條目由?Follower 確認、Leader 提交并按順序應用于所有副本。因此,當?write?請求并發執行時,它們將按順序提交。隊列末尾的那些請求在之前的所有請求被持久地存儲到磁盤并得到響應之前是無法提交和響應的,這會增加平均延遲并降低吞吐量。我們觀察到隨著?I/O 深度從?8?增加到?32,吞吐量下降了一半。

Raft 不太適合使用多個連接在主從之間傳輸日志的環境。當一個連接阻塞或變慢時,日志條目將無序地到達?Follower。換句話說,隊列前面的一些日志條目實際上比后面的日志條目到達的晚。但是?Raft Follower 必須按順序接受日志條目,這意味著在前面丟失的日志條目到達之前,它不能發送一個確認來通知?Leader 后續的日志條目已經被記錄到磁盤上。此外,當大多數?Follower 在一些丟失的日志條目上被阻塞時,Leader 會陷入困境。然而,實際上,在高度并發的環境中使用多個連接是很常見的。我們需要修改?Raft 協議來解決這種情況。

在事務處理系統(如數據庫)中,并發控制算法允許事務以交錯和無序的方式執行,同時生成可序列化的結果。這些系統自然可以容忍由傳統存儲語義引起的無序?I/O 完成,并自行處理以確保數據一致性。實際上,像?MySQL??AliSQL?這樣的數據庫并不關心底層存儲的?I/O 序列。數據庫的鎖系統將保證在任何時候,只有一個線程可以在一個特定的頁面上工作。當不同的線程同時工作在不同的頁面上時,數據庫只需要成功地執行?I/O,它們的完成順序無關緊要。因此,我們利用這一點來放寬?PolarFS ?Raft 的一些限制,從而開發出一個更適合高?I/O 并發性的一致性協議。

本文在?Raft 上提出了一種改進的一致性協議?ParallelRaft,下面將介紹?ParallelRaft 如何解決上述問題。?ParallelRaft 的結構與?Raft 相當相似。它通過復制日志實現復制狀態機。有?Leader ?FollowersLeader 將日志條目復制到?Followers。我們采用與?Raft 相同的問題分解方法,將?ParallelRaft 劃分為更小的部分:日志復制、領導人選舉和?Catch up

?

?

5.2 無序日志復制

Raft 的序列化分為兩個方面:(1)??Leader ?Follower 發送一個日志條目后,?Follower 需要確認它,以通知該日志條目已經被接收和記錄,這也暗示著前面所有的日志條目都已被看到并保存。(2)??Leader 提交一個日志條目并將此事件廣播給所有 Follower 時,它也承認之前的所有日志條目都已提交。ParallelRaft 打破了這些限制,無序地執行所有這些步驟。因此,ParallelRaft ?Raft 有一個基本的區別。在?ParallelRaft 中,當一個條目被識別為已提交時,并不意味著所有先前的條目都已成功提交。為了保證該協議的正確性,我們必須保證:(1)?在沒有這些串行限制的情況下,所有提交的狀態將與經典且合理的數據庫使用的存儲語義相沖突。(2)?所有提交的修改在任何情況下都不會丟失。

ParallelRaft 的無序日志執行遵循以下規則:如果日志項的寫入范圍不重疊,則認為這些日志項沒有沖突,可以按任何順序執行。否則,沖突條目將在到達時按嚴格的順序執行。這樣,較新的數據就不會被舊版本覆蓋。ParallelRaft 可以很容易地知道沖突,因為它存儲了未應用的任何日志項的?LBA 范圍摘要。下面介紹如何優化?ParallelRaft ?Ack-Commit-Apply?步驟,以及如何維護必要的一致語義。

無序確認(Out-of-Order Acknowledge)。Raft Follower 在接收到從?Leader 復制的日志條目之后不會立即確認而是直到前面所有的日志條目都被持久地存儲起來后才確認。這就增加了額外的等待時間,并且當有大量并發的?I/O 寫入正在執行時,平均延遲會顯著增加。然而,?ParallelRaft 中,一旦成功寫入日志條目,Follower 可以立即確認它。這樣,避免了額外的等待時間,從而優化了平均延遲。

無序提交(Out-of-Order Commit)?Raft Leader 以串行順序提交日志條目,在提交所有前面的日志條目之前,無法提交日志條目。然而,在日志中的大多數副本可以立即提交。這種提交語義對于不像?TP?系統那樣承諾強一致性語義的存儲系統而言是可以接受的。例如,?NVMe?不檢查讀或寫命令的?LBA,以確保并發命令之間的任何類型的排序,也不保證這些命令的完成順序[13]。

允許日志上有漏洞(Apply with Holes in the Log)?像?Raft?一樣,所有的日志條目在 ParallelRaft 中被記錄時都是按照嚴格的順序應用的,這樣數據文件在所有副本中都是一致的。但是,對于無序的日志復制和提交,ParallelRaft 允許日志中存在漏洞。在前面的一些日志條目仍然丟失的情況下,如何安全地應用日志條目?這給 ParallelRaft 帶來了挑戰。

ParallelRaft 在每個日志條目中引入了一種新的數據結構 look?behind?buffer 來解決這個問題。Look?behind?buffer?包含由前?N?個日志條目修改的?LBA ,因此?look?behind?buffer?充當在日志中可能的洞上構建的橋梁。N?是這座橋的跨度,也是允許的最大日志漏洞。請注意,盡管日志中可能存在多個漏洞,但所有日志條目的?LBA 摘要始終是完整的,除非任何漏洞大小大于?N。通過這種數據結構,Follower 可以判斷出日志條目是否沖突,這意味著由該日志條目修改的?LBA 與一些先前缺失的日志條目重疊。可以安全地應用與任何其他條目不沖突的日志條目,否則應將它們添加到掛起的列表中,并在檢索到丟失的條目后進行答復。根據我們在使用?RDMA?網絡的?PolarFS 中的經驗,N?設置為?2?對于它的?I/O 并發性來說已經足夠了。

基于上述無序執行方法和規則,可以成功地實現所需的數據庫存儲語義。此外,通過消除?PolarFS 并行處理中不必要的串行限制,還可以縮短多副本并發寫入的延遲。

?

?

5.3?Leader 選舉

在進行新的?Leader 選舉時,與?Raft 相同,ParallelRaft 可以選擇最新項和日志項最長的節點在?Raft 中,新當選的?Leader 包含了所有以前任期的提交條目。然而,由于日志可能有漏洞,ParallelRaft 中選出的?Leader 最初可能無法滿足這一要求。因此,在開始處理請求之前,需要一個額外的?Merge 階段,使?Leader 擁有所有已提交的條目。在合并階段完成之前,新選擇的節點是唯一的?Leader 候選人,在合并階段完成后,它擁有所有提交的條目,成為真正的?Leader。在合并階段,Leader 候選人需要合并仲裁其他成員看不見的條目。在那之后,Leader 將開始提交以前任期的參與者到法定人數,這和?Raft 一樣。

合并條目時,ParallelRaft 還使用與?Raft 類似的機制。具有相同任期(term)和索引的條目將被提交為相同條目。有幾個不正常的情況:(1)?對于一個提交但缺失的條目,Leader 候選人總能從至少一個?Follower 候選中找到相同的提交條目,因為該提交條目已被大多數法定人數接受。(2)?對于一個沒有在任何候選對象上提交的條目,如果該條目也沒有保存在其中的任何一個上,由于根據?ParallelRaft ?Raft 機制,它之前不可能被提交,所以?Leader 可以安全地跳過該日志條目。(3)?如果一些候選者保存了這個未提交的條目(具有相同的索引但是不同的?term),那么?Leader 候選者選擇具有最高?term 的條目版本,并將此條目識別為有效條目。我們必須這樣做是因為另外兩個事實(3.a)?ParallelRaft 的合并階段必須在新的?Leader 能夠為用戶請求服務之前完成,這決定了如果一個條目設置了一個較高的?term,那么具有相同條目索引的較低?term 之前一定沒有被提交過,并且較低的?term 條目必須從未參與過之前成功完成的合并階段,否則較高的?term 條目不能具有相同的索引。(3.b) 當系統崩潰時,候選項中保存了一個未提交的條目,則該條目的確認可能已發送給前一個?Leader 并回復給用戶,因此我們不能簡單地放棄它,否則用戶數據可能會丟失。(更確切地說,如果失敗節點的總數加上具有此未提交項的節點(具有相同索引的最高?term)超過同一仲裁中的其他節點數,則此項可能已由失效的?Leader 提交。因此,我們應該保證用戶數據安全。)以 3 個副本的情況為例,圖5?顯示了領導人選舉的過程。

(1) Follower 候選者將其本地日志條目發送給?Leader 候選者。Leader 候選者接收這些條目并與自己的日志條目合并。(2) Leader 候選者和?Follower 候選者同步狀態。(3) Leader 候選人可以提交所有的條目,并通知?Follower 候選人提交。最后,Leader 候選人升級為?Leader Follower 候選人也升級為?Follower

通過上述機制,所有提交的條目都可以由新的?Leader 恢復,這意味著?ParallelRaft 不會丟失任何提交狀態。?ParallelRaft 中,不定期地建立一個檢查點(checkpoint),檢查點之前的所有日志項都應用于數據塊,并且允許該檢查點包含一些在檢查點之后提交的日志項。為了簡單起見,檢查點之前的所有日志條目都可以被視為修改過的,盡管實際上它們會保留一段時間,直到資源不足或達到某個閾值為止。

在我們的實際實現中,ParallelRaft 選擇檢查點最新的節點作為候選節點,而不是日志最長的節點,以達到追趕的目的。在合并階段,很容易看出,新領導人將達到相同的狀態時,開始服務。因此,這種選擇并不損害?ParallelRaft 的正確性。

?

?

5.4 追趕

當一個落后的?Follower 想要跟上?Leader 的當前數據狀態時,它將使用 fast-catch-up?或 streaming-catch-up 來重新與?Leader 同步。使用哪一個取決于?Follower 的狀態有多陳舊。快速追趕fast?catch?up)機制是為主從之間的增量同步而設計的,前提是當它們之間的差異相對較小時。?Follower 遠遠落后于?Leader。例如,Follower 已經離線好幾天了,因此完全的數據重新同步是不可避免的。?PolarFS 為此提出了一種稱為 streaming?catch?up 的方法。

圖6?顯示了重新同步開始時,Leader ?Follower 的不同情況。在 案例1 中,Leader 的 checkpoint 比?Follower 的最新日志索引更加的新,它們之間的日志條目將被?Leader 修改。因此,fast?catch?無法處理這種情況,應該使用?streaming?catch?up。案例2案例3 可以通過?fast?catch?解決。

在以下情況下,我們總是可以假設?Leader 的檢查點比?Follower 的檢查點更新,因為如果不滿足這個條件,?Leader 可以立即創建一個比任何其他檢查點都新的檢查點。

檢查點之后的日志條目可以分為四類:已提交和已應用、已提交但未應用、未提交和漏洞

快速追趕(Fast Catch Up)?Follower 可能在其檢查點后有漏洞,在快速追趕時會被填滿。首先,利用?look-behind-buffer?重新填充?Follower 檢查點和?Leader 檢查點之間的漏洞,通過該緩沖區我們可以發現所有缺失修改的?LBA。這些漏洞是直接從?Leader 的數據塊中復制來填充的,這些數據塊包含比?Follower 的檢查點更新的數據。第二,通過讀取?Leader 的日志塊來填充?Leader 檢查點后的塊。在 案例3 中,?Follower 可能包含一些舊?term 中未提交的日志條目。像?Raft 一樣,這些條目被修改,然后將按照上述步驟進行處理。

流式追趕(Streaming Catch Up)。在流式追趕中,比檢查點更舊的日志歷史記錄被認為對完成數據重新同步是無用的,并且必須使用檢查點之后的數據塊和日志項的內容來重建狀態。當復制塊時,整個塊被分割成?128KB 的小塊并使用大量的小任務,每個任務只同步一個?128KB 的塊。我們這樣做是為了建立一個更可控的再同步。7.3?節進一步的討論了設計動機。

?

?

5.5?ParallelRaft 的正確性

Raft 為協議的正確性確保了以下屬性:選舉安全性、僅限?Leader 追加、日志匹配、?Leader 完備性和狀態機安全性。由于?ParallelRaft 并沒有改變它們的性質,所以很容易證明?ParallelRaft 具有選舉安全性、只附加?Leader 和日志匹配的特性

ParallelRaft 的故障承諾引入了與標準?Raft 的關鍵區別。ParallelRaft 日志可能缺少一些必要的條目。因此,我們需要考慮的關鍵場景是,新當選的?Leader 應該如何處理這些缺失的條目。?ParallelRaft ?Leader 選舉添加合并階段。在合并階段,?Leader 將復制丟失的日志條目,重新確認是否應該提交這些條目,然后在仲裁中提交它們(如果需要)。在第5.3節的合并階段之后,保證了?Leader 的完整性。

此外,如第5.2節所述,對于數據庫,PolarFS 中的無序提交是可以接受的。然后我們將證明無序應用不會違反狀態機安全屬性。盡管?ParallelRaft 允許節點無序的獨立應用,由于后面找了緩沖區(5.2節),沖突日志只能應用于一個嚴格的序列,這意味著狀態機(數據+提交日志條目)在同一群體中的所有節點將相互一致。利用這些性質,保證了并行程序的正確性。

?

?

5.6?ParallelRaft vs?Raft

我們做了一個簡單的測試來展示?ParallelRaft 如何提高?I/O 并發性。圖7?顯示了當?I/O 深度從 1 到 32 以及單個?FIO?作業時?Raft ?ParallelRaft 的平均延遲和吞吐量。這兩種算法都是用 RDMA 實現的。由于它們是獨立實現的不同軟件包,所以在開始時的細微性能差異可以忽略不計。隨著?I/O 深度的增加,兩個協議之間的性能差距變得更大。?I/O 深度增加到 32 時,Raft 的延遲大約是并行?Raft 延遲的 2.5 倍,只有?ParallelRaft 達到 IOPS 的一半以下。值得注意的是,當?I/O 深度大于 8 時,Raft 的 IOPS 顯著下降,而?ParallelRaft 則保持了一個穩定的高水平。結果證明了我們提出的優化機制在?ParallelRaft 上的有效性。無序的確認和提交提高了?I/O 并行性,使?PolarFS 即使在繁重的工作負載下也能保持優異和穩定的性能。

?

?

6. FS中層的實現

?PolarFS 的文件系統層,元數據管理可以分為兩部分。第一種方法是組織元數據來訪問和更新數據庫節點中的文件和目錄。二是協調和同步數據庫節點之間的元數據修改。

?

6.1 元數據組織

文件系統元數據有三種:目錄項、索引節點和塊標記(directory entry、inode and block tag)。一個目錄條目保存一個文件路徑的名稱組件,并引用一個?inode。目錄項的集合被組織到一個目錄樹中。inode?描述常規文件或目錄。對于常規文件,inode?保留對一組塊標記的引用,每個塊標記描述文件塊號到卷塊號的映射(each describing the mapping of a file block number to a volume block number);對于目錄,inode?保留對父目錄中一組子目錄項的引用(上面提到的引用實際上是元對象標識符,如下所述)。

這三種元數據被抽象為一種稱為?metaobject?的數據類型,metaobject?具有一個字段,用于保存目錄條目、inode?或塊標記的特定數據。此公共數據類型用于訪問磁盤上和內存中的元數據。創建新文件系統時,元對象在磁盤上以連續?4K 大小的扇區初始化,每個元對象都分配了一個唯一的標識符。在?pfs_mount?中,所有的元對象都被加載到內存中,并被分成?chunk ?type?組。

使用元組(元對象標識符,元對象類型)在內存中訪問元對象。標識符的高位用于查找元對象所屬的?chunk,type?用于查找?chunk 中的組,最后將標識符的低位作為索引訪問組中的元對象。

要更新一個或多個元對象,需要準備一個事務,并將每次更新記錄為一個事務操作。事務操作保留其修改對象的舊值和新值。完成所有更新后,就可以提交事務了。提交過程需要數據庫節點之間的協調和同步,如下小節所述。如果提交失敗,將使用事務中保存的舊值回滾更新。

?

?

6.2 協調與同步

為了支持文件系統元數據的同步,PolarFS 將元數據修改作為事務記錄到日志中文件。那個日志文件由數據庫節點輪詢以獲取新事務。一旦找到新事務,節點將檢索和重新事務(new transactions are retrieved and replayed by the nodes)

通常,只有一個實例可以寫入日志文件,而多個實例可以讀取日志文件。在網絡分區或管理的情況下,可能有多個實例寫入日志文件。在這些情況下,我們需要一種機制來協調對日志文件的寫入。?PolarFS 為此使用了磁盤?Paxos 算法[10]。請注意,這里使用的磁盤?Paxos 算法的目的與?ParallelRaft 大不相同。后者是為了保證塊副本之間的數據一致性。

磁盤?Paxos 算法運行在一個由?4K?大小的頁面組成的文件上,這些頁面可以原子性地讀或寫。這些頁被解釋為每個數據庫節點的一個?Leader 記錄加上數據塊( These pages are interpreted as one?Leader record plus data blocks for each database node )。每個數據庫節點使用數據塊頁來編寫自己的議和讀取其他節點的提議( The data block pages are used by each database node to write the proposal of itself and to read the proposals of others )Leader record?頁面包含當前?Paxos winner?的信息和日志定位點(log anchor)。磁盤?Paxos 算法只由一個寫節點運行。只讀節點不運行磁盤?Paxos 。相反,他們通過檢查?Leader record頁面中的日志定位點來進行投票。如果日志定位點更改,只讀節點知道日志文件中有新事務,它們將檢索這些新事務以更新其本地元數據。我們用一個示例來解釋事務提交過程,如?圖8?所示。其步驟如下:

(1)?在將塊 201 分配給文件 316 之后,節點1?獲取?Paxos 鎖,該鎖最初是空閑的。(2)?節點1?開始將事務記錄到日志。最新寫入的目錄被標記為?pending tail。在所有目錄被存儲之后,pending tail 成為日志的有效末尾。(3)?節點1?使用修改后的元數據更新超級塊。同時,節點2?嘗試獲取?節點1?已經持有的互斥鎖。節點2?必然會失敗,稍后將重試。(4)??節點1?釋放鎖之后,節點2?成為互斥鎖的合法所有者,但是?節點1?附加的日志中的新條目確定?節點2?中的本地元數據緩存已過時。(5)?節點2?掃描新條目并釋放鎖。然后,節點2?回滾未記錄的事務并更新本地元數據。最后,節點2?重試事務。(6)?節點3??開始自動同步元數據,只需要加載增量項并在本地內存中重演。

?

?

7. 設計選擇和經驗教訓

除了系統架構、I/O 模型和共識協議外,還有一些有趣的設計問題值得討論。其中一些屬于?PolarFS 本身,而另一些則針對數據庫特性。

?

7.1 集中或分散

分布式系統有兩種設計模式:集中式和分散式。集中式系統,如GFS[11]和HDFS[5],包含一個主節點,負責元數據的保存和成員管理,這種系統實現起來相對簡單,但從可用性和可擴展性的角度來看,單個?master?可能成為整個系統的瓶頸。像?Dynamo[8]?這樣的分散系統則恰恰相反。在該系統中,節點之間是對等關系,元數據是分片的,節點之間是冗余的。分散系統被認為是更可靠的,但實現和推理也更加的復雜。

PolarFS 在集中式和分散式設計之間進行了權衡。一方面,PolarCtrl?是一個集中式主機,負責諸如資源管理之類的管理任務,并接受控制面板( control plane )請求(如創建?volume)。另一方面,?ChunkServers?正在互相交談,運行一個共識協議,在不涉及?PolarCtrl?的情況下自主處理故障和恢復。

?

?

7.2 自下而上的快照

快照是數據庫的常見需求。PolarFS 支持快照功能,簡化了上層?POLARDB 快照設計。

?PolarFS 中,存儲層為上層提供可靠的數據訪問服務,POLARDB ?libpfs?有自己的日志機制來保證事務的原子性和持久性。PolarFS 存儲層提供了磁盤中斷一致性的快照,?POLARDB ?libpfs?從底層?PolarFS 快照重建自己的一致數據映像。

這里的磁盤中斷一致性是指,如果快照命令在時間點?T?觸發,則存在某個時間點?t0,因此t0?之前的所有?I/O 操作都應包含在當前快照中,T?之后的?I/O 操作必須排除在外。然而,在間隔?[T0,T]??I/O 操作的狀態通常是很短的時間跨度,是不確定的。這種行為類似于磁盤仍在寫入時關機時發生的情況。

當發生意外災難或需要進行主動審計時,PolarCtrl?會將最新的數據快照分配給?POLARDB ?實例,POLARDB ?libpfs?將使用存儲的日志重建一致的狀態。

PolarFS 以一種新穎的方式實現了磁盤中斷一致性快照,在快照過程中不會阻塞用戶的?I/O 操作。當用戶發出快照命令時,PolarCtrl?通知?PolarSwitch?生成快照。從那時起,PolarSwitch?在以下請求中添加了一個?snapshot?標記,它指示它的主機請求發生在快照請求之后。收到帶有快照標記的請求時,ChunkServer 將在處理此請求之前生成快照。?ChunkServer 通過復制塊映射元數據信息來創建快照,這是一種快速的方法,并處理將來的請求,這些請求將以一種?寫時復制?的方式修改這些塊。在帶有?snapshot?標記的請求完成后,PolarSwitch?停止向傳入的請求添加?snapshot?標記。

?

?

7.3 外部服務與內部可靠性

工業系統的可靠性是極其重要的,特別是對于像 PolarFS 這樣的系統,它正在承擔 7X24公共云服務。在這樣的系統中,應該有各種各樣的可靠性維護任務,以防止服務和相關收益的損失。對于 PolarFS 來說,如何高效地運行這些任務,同時為繁重的用戶負載提供平滑的服務,這是一個巨大的挑戰。

?streaming catch up in ParallelRaft?為例,當?Leader 在處理大量的工作負載時,會不斷地生成大量的日志,即使在長時間的日志提取之后,Follower 也無法趕上。由于?I/O 限制,復制整個塊的時間也可能相當長,而且不可預測。這可能會導致我們進行權衡:恢復時間越短,所需資源越多,對系統性能的犧牲就越大;而如果恢復需要很長時間,則系統可用性將面臨風險。

我們的解決方案是將一個 chunk 水平分割成小的邏輯塊(logical pieces),例如, 128KB 的塊。chunk 的完整數據同步被分成許多小的子任務,每個子任務只重新同步一個?128KB?的片段。這些較小的子任務的運行時要短得多,而且更容易預測。此外,還可以在次同步任務( sub-resync-tasks )之間插入空閑周期,以控制 streaming catch up 所需的網絡/磁盤帶寬成本。

其他耗時的任務,如檢查副本之間的一致性的完整數據驗證例程,也可以類似地實現。我們必須考慮使用同步流控制來平衡外部服務質量和?PolarFS 的系統可靠性。由于篇幅的限制,我們將不在這里進一步討論這種權衡的細節。

?

?

8. 價值評估

我們已經實現了?PolarFS ,并在阿里云上發布了?POLARDB 作為公共數據庫服務。在本節中,我們評估和分析了?PolarFS ?POLARDB 的性能和可伸縮性。對于?PolarFS,我們在集群上對其進行了評估,將其與本地?NVMe?上的?Ext4??Ceph[35]?上的?CephFS?進行了比較,后者是一種廣泛使用的開源分布式存儲系統。對于?POLARDB,我們將其與我們最初的?MySQL?云服務?RDS??localext4?上的?POLARDB 進行了比較。

?

8.1?PolarFS 實驗配置

在文件系統性能方面,我們重點研究了三個系統(?PolarFS CephFS ?Ext4 )的端到端性能,包括不同工作負載和訪問模式下的延遲和吞吐量。

PolarFS ?CephFS 的實驗結果是在一個由?6?個存儲節點和一個客戶端節點組成的集群上收集的。節點通過?RDMA-enabled NIC?相互通信。

Ceph 的版本是 12.2.3,我們將其存儲引擎配置為 bluestore,將通信消息器類型配置為 async + posix 。Ceph 的存儲引擎可以配置為使用 RDMA verbs 運行,但其文件系統僅支持 TCP/IP 網絡堆棧,因此我們將 CephFS 配置為使用 TCP/IP 運行。對于 Ext4,我們在丟棄所有舊數據后在 SSD 上創建一個新的 Ext4。

我們使用?FIO[1]生成具有不同?I/O 請求大小和并行性的各種類型的工作負載。FIO?將首先創建文件并將其擴展到給定的長度(這里是10G),然后再進行性能評估。

?

?

8.2?I/O 延遲

?圖9?所示,PolarFS 對于?4K 隨機寫入的延遲約為?48μs,與?CephFS 的延遲(約760μs)相比,非常接近于Ext4在本地?SSD 上的延遲(約10μs)。?PolarFS 的平均隨機寫入延遲是本地?Ext4?的1.6~4.7倍,CephFS ?的平均隨機寫入延遲是本地?Ext4?的6.5~75倍,這意味著分布式?PolarFS 幾乎提供了與?local Ext4?相同的性能。PolarFS ?CephFS ?Ext4?的平均順序寫入延遲比分別為?1.6-4.8??6.3-56。?PolarFS ?CephFS ?Ext4?的平均隨機讀取延遲比分別為?1.3-1.8??2-4。?PolarFS ?CephFS ?Ext4?的平均順序讀取延遲比分別為?1.5-8.8??3.4-14.9。Ext4??PolarFS /CephFS 的大請求(1M)性能降低不同于小請求(4K),因為網絡和磁盤數據傳輸占用了大部分的大請求執行時間。

PolarFS 的性能比?CephFS ?好得多,這有幾個原因。首先,PolarFS 用一個線程處理有限狀態機的?I/O ,如第?4?節所述。這避免了由多個線程組成的?I/O 管道所需的線程上下文切換和重新調度,就像?CephFS ?所做的那樣。第二,PolarFS 優化了內存分配和分頁,在?I/O 生命周期中使用內存池來分配和釋放內存,減少了對象的構建和銷毀操作,使用了大量的頁面來減少?TLB?的丟失和分頁,CephFS 中沒有對應的方法。第三,PolarFS 中關于數據對象的所有元數據都保存在內存中,而?CephFS 中的每個?PG(Placement Group)中只有部分元數據保存在一個小緩存中,因此?PolarFS 大多數?I/O 操作不需要額外的元數據?I/O ,但?CephFS 有時需要對元數據進行額外的?I/O 操作。最后,PolarFS 中的用戶空間?RDMA??SPDK??CephFS 中的內核?TCP/IP?和塊驅動具有更低的延遲。

?

?

8.3?I/O 吞吐量

圖10?顯示了三個文件系統的總體?I/O 吞吐量。對于隨機讀寫,本地?SSD 上的?Ext4、?PolarFS ?CephFS IOPS都是隨著客戶端作業數的變化而變化的;Ext4?的可擴展性瓶頸是單個本地 SSD IOPS,PolarFS 的擴展瓶頸是網絡帶寬,CephFS ?的瓶頸是數據包處理能力(packet processing capacity)。Ext4 和 PolarFS 的隨機 4K 寫/讀?I/O 吞吐量比 CephFS 分別高 4.4/5.1,4/7.7。

對于順序讀/寫,對于本地系統和分布式系統,幾乎所有的請求都由一個磁盤來處理。Ext4和 PolarFS 都可以很好地隨客戶作業的數量進行擴展,直到由于 I/O 瓶頸而達到極限,而?CephFS 的瓶頸是其軟件,它不能使磁盤 I/O 帶寬達到飽和。

在沒有額外的網絡?I/O 的情況下,Ext4??1?臺客戶上的順序讀吞吐量遠遠高于?PolarFS ?CephFS,但隨著客戶端數量增加到2臺,其順序讀吞吐量急劇下降,吞吐量與?2?客戶端的隨機讀吞吐量基本相同。我們重復了幾次評估,結果是可重復的。我們猜測這是由我們的?NVMe?SSD 的特性造成的。SSD-NVM?內置了一個?DRAME?緩沖區。當固件猜測工作負載看起來像順序讀取時,它會將后續數據塊預取到?DRAM?緩沖區中。我們猜測預取機制在非交錯?I/O 模式下會工作得更好。

?

?

8.4 評估?POLARDB ?

為了證明我們的超低?I/O 延遲?PolarFS 對于數據庫的好處,我們對?POLARDB ?進行了一些初步測試,POLARDB 是一個專門與?PolarFS 一起開發的共享存儲云數據庫。我們比較了三個系統的吞吐量:(1) POLARDB ?PolarFS 上,(2) POLARDB 在本地?Ext4,以及(3)?阿里云數據庫MySQL云服務RDS參考。測試?(1)?和?(2)?與以前的?PolarFS 硬件環境處于相同的硬件環境下。

我們分別在模擬的只讀、只(update:delete:insert=2:1:1)和讀/寫混合(read:write=7:2)OLTP?工作負載下運行?Sysbench[21]來分別評估三個數據庫。本實驗使用的數據集由?250?個表組成,每個表有?850?萬條記錄。測試數據的總大小為?500GB

?圖11?所示,?PolarFS ?POLARDB 的吞吐量非常接近本地?Ext4?上的吞吐量,而?PolarFS 提供了額外的 3 副本高可用性。?PolarFS 上的?POLARDB 實現了?653K?讀/秒、160K?寫/秒和173K?(讀寫)/秒。

除了與?PolarFS 集成外,?POLARDB 還應用了一系列基于?Aliyun RDS?的數據庫優化。結果,?POLARDB 的讀、讀寫混合吞吐量幾乎是?RDS??2.794.721.53倍,如圖所示。數據庫級優化超出了本文的范圍。

?

?

9. 相關工作

存儲系統。GFS[11]?及其開源實現?HDFS[5]?提供分布式系統服務,GFS??HDFS?均采用主從架構,主機維護系統元信息、leader 租約機制,并負責故障恢復。與?GFS??HDFS?不同,?PolarFS 采用混合架構。PolarFS 的主節點主要負責資源管理,一般不增加?I/O 路徑的干擾,使主機升級和容錯更容易。

Ceph[35]?是一種廣泛部署的存儲系統。它使用?CRUSH?散列算法來定位數據對象,為正常的?I/O 執行和容錯帶來了一個簡單的設計。RAMCloud[29]是一個低延遲的?KV 系統,它通過在集群之間隨機復制數據并利用集群資源并行恢復故障來提供快速恢復。隨機的數據放置會使一臺機器在云環境下承載上千個用戶的數據,這意味著一臺機器的崩潰會影響到上千個用戶,這是云服務提供商無法接受的。PolarFS control master?在將數據塊分配給實際服務器時,在故障影響和?I/O 性能之間提供了細粒度的權衡。

ReFlex[20]使用?NVMe-SSD 來實現遠程磁盤,它提出了一個?QoS?調度器,可以強制實現尾部延遲和吞吐量服務級別目標,但與?PolarFS 不同,它的遠程磁盤是單副本的,沒有可靠性支持。CORFU[3]??flash?設備集群組織為單個共享日志,多個客戶端可以通過網絡并發訪問該日志。共享日志設計簡化了分布式環境下的快照和復制,但增加了現有系統使用?CORFU?的工程難度,否則?PolarFS 將為用戶提供塊磁盤抽象和類似?POSIX 的文件系統接口。

Aurora[32]?是亞馬遜在其?ECS?服務之上的云關系數據庫服務。Aurora?通過將數據庫重做日志處理推送到存儲端,解決了計算端和存儲端之間的網絡性能約束。Aurora?還修改了?MySQL??innodb?事務管理器,以便于日志復制,而?POLARDB ?PolarFS 上投入了大量資金,但使用了類似?POSIX ?API,最終對數據庫引擎本身幾乎沒有修改。Aurora?的?redo?邏輯下推設計打破了數據庫和存儲之間的抽象,使得每一層的修改更加困難,而?PolarFS 和?POLARDB 保留了每一層的抽象,使得每一層更容易采用其最新技術。

一致性協議。Paxos [22]是分布式系統中最著名的一致性算法之一。但是,它很難理解和正確實施。Paxos 的作者只證明了?Paxos 可以解決一致性問題的一個實例,而沒有說明如何使用?Multi?Paxos 來解決實際問題。目前,大多數一致性算法,如?Zookeeper?使用的Zab[16],被認為是?Multi?Paxos?算法的變種。Zab?用于提供原子廣播原語屬性,但也很難理解。?Raft [28]?是為可理解性而設計的,也是?“Multi?Paxos?算法。它引入了兩個主要約束,第一個是提交日志必須是連續的,第二個是提交順序必須序列化。這兩個約束使得?Raft 很容易理解,但也會對并發?I/O 性能產生影響。有些系統使用多組?Raft ( Multi Groups?Raft )來提高?I/O 并行性,將鍵分成多個組,但它不能解決提交日志包含多個組的鍵的問題。ParallelRaft 通過不同的方式實現這一目標。提交日志允許有漏洞,并且可以無序提交日志條目,但沖突日志條目將以嚴格的順序提交。

RDMA?系統。與傳統的?TCP/UDP?網絡協議相比,RDMA?在降低?CPU?利用率的同時,將往返時延降低了一個數量級,許多新的系統使用?RDMA?來提高性能。FaRM[9]?是一個基于?RDMA?的分布式共享內存,用戶可以使用它的程序原語來構建自己的應用程序。DrTM[34]?是一個基于?RDMA?和硬件事務存儲器的分布式內存數據庫,RDMA?可以快速地從遠程訪問數據,也可以導致硬件事務內存中的本地事務中止,DrTM?結合?RDMA?和硬件事務存儲器來實現分布式事務。FaRM??DrTM?都專注于內存事務,而?PolarFS 使用?RDMA?構建分布式存儲。

Pilaf[27]?是一種基于?RDMA?和自驗證數據結構的鍵值存儲,但與?PolarFS 不同,Pilaf 的鍵值接口相對簡單,沒有分布式共識協議。

APUS[33] 使用 RDMA 構建可伸縮的 Paxos,PolarFS 提供了一個對高并行 I/O 友好的 ParallelRaft。PolarFS 使用?RDMA?來構建可靠的塊設備,由于?RDMA?比傳統網絡協議消耗更少的?CPU,PolarFS 可以以運行到完成的方式處理 I/O ,避免了上下文切換。結合?RDMA??SPDK,存儲節點可以在整個 I/O 生命周期內不接觸負載完成 I/O,所有負載的移動都由硬件完成。

?

?

10. 結論

PolarFS 是一個分布式文件系統,它提供了極高的性能和高可靠性。PolarFS 采用了新興的硬件和最先進的優化技術,如?OS-bypass?零拷貝,使其延遲與?SSD 上的本地文件系統相當。為了滿足數據庫應用的高?IOPS?要求,我們開發了一種新的一致性協議?ParallelRaft?ParallelRaft 在不犧牲存儲語義一致性的前提下,放寬了?Raft 嚴格的順序寫入,提高了?PolarFS 的并行寫入性能。在重負載下,我們的方法可以將平均延遲減半,系統帶寬增加一倍。PolarFS 在用戶空間中實現了類似?POSIX 的接口,這使得?POLARDB 只需稍加修改就可以實現性能改進。

?

?

原論文中的聲明:

本作品根據 Creative Commons AttributionNoDerivatives 4.0 國際許可證授權。要查看此許可證的副本,請訪問http://creativecommons.org/licenses/by-nc-nd/4.0/。對于本許可證涵蓋范圍以外的任何用途,請通過電子郵件獲得許可info@vldb.org。版權歸所有人/作者所有。授權 VLDB 基金會出版權。

總結

以上是生活随笔為你收集整理的PolarFS :一个用于共享存储云数据库的超低延迟和容错分布式文件系统的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。