分布式存儲 Ceph 的演進經驗 · SOSP 2019
『看看論文』是一系列分析計算機和軟件工程領域論文的文章,我們在這個系列的每一篇文章中都會閱讀一篇來自 OSDI、SOSP 等頂會中的論文,這里不會事無巨細地介紹所有的細節,而是會篩選論文中的關鍵內容,如果你對相關的論文非常感興趣,可以直接點擊鏈接閱讀原文。
本文要介紹的是 2019 年 SOSP 期刊中的論文 —— File Systems Unfit as Distributed Storage Backends: Lesson Effis from 10 Years of Ceph Evolution[^1],該論文介紹了分布式存儲系統 Ceph 在過去 10 多年演進過程中遇到的一些問題,我們作為文件系統的使用者也能從中可以借鑒到很多經驗與教訓,在遇到相似問題時避免犯相同的錯誤。
圖 1 - Ceph
從 2004 年到今天,Ceph 的存儲后端一直都在演變,從最開始基于 B 樹的 EBOFS 演變到今天的 BlueStore,存儲后端已經變得非常成熟,新的存儲系統不僅能夠提供良好的性能,還有著優異的兼容性。我們在這篇文章中將要簡單介紹分布式存儲 Ceph 的架構以及演進過程中遇到的挑戰。
Ceph 架構
分布式文件系統能夠聚合多個物理機上的存儲空間并對外提供具有大帶寬、并行 I/O、水平擴展、容錯以及強一致性的數據存儲系統。不同的分布式系統可能在設計上稍有不同并且使用不同的術語描述物理機上用于管理存儲資源的模塊,但是存儲后端(Storage backend)一般都被定義為直接管理物理機上存儲設備的軟件模塊;而在 Ceph 中這一模塊就是對象存儲設備(Object Storage Devices、OSDs):
圖 2 - Ceph 架構
Ceph 使用如上圖所示的架構,它的核心是可靠自主分布式對象存儲(Reliable Autonomic Distributed Object Store、RADOS),該模塊可以水平擴展出成千上萬個 OSDs 提供自愈、自管理并且強一致的副本對象存儲服務。
我們可以使用 Ceph 提供的 librados 操作 RADOS 中存儲的對象和對象集合,該庫提供了易于操作的事務接口,在該接口之上我們可以構建出:
- RADOS 網關(RGW):類似于 Amazon S3 的對象存儲;
- RADOS 塊設備(RBD):類似于 Amazon EBS 的虛擬塊設備;
- CephFS:提供 POSIX 語義的分布式文件系統;
RADOS 中的對象會被存儲在邏輯分區中,也就是池(Pool);對象會在池中分片,每個分片單位被稱作放置組(Placement Groups、PGs),放置組中的數據會根據配置好的副本數同步到多個 OSD 上,這樣可以在單個 OSD 宕機時保證數據的正確性。
RADOS 集群中的每個節點都會為每個本地存儲設備運行獨立的 OSD 守護進程,這些進程會處理來自 librados 的請求并配合其他 OSD 節點完成數據的拷貝、遷移以及錯誤恢復等操作,所有的數據都會通過內部的 ObjectStore 接口持久化到本地,我們可以為硬件設備實現不同的接口以滿足兼容性的需求。
演進挑戰
與其他的分布式文件系統不同,今天 Ceph 的存儲后端 BlueStore 繞過了本地的文件系統,直接管理本地的裸設備,這是因為 Ceph 團隊的經驗說明在本地的文件系統上構建存儲后端是一件非常麻煩的事情:
圖 3 - 存儲后端的挑戰
- 在本地文件系統上直接構建無額外開銷的事務機制是非常復雜的;
- 本地文件系統的元數據性能對分布式文件系統的性能有很嚴重的影響;
- 成熟的文件系統有著非常嚴格的接口,適配新的存儲硬件很困難;
高效事務
事務可以通過將一系列操作封裝到獨立的原子單元來簡化應用程序的開發,這一系列操作要么全部執行、要么全不執行,對數據庫稍有了解的工程師應該都很了解事務的四個特性,也就是原子性、一致性、隔離性和持久性,我們這里就不展開討論了。
雖然事務能夠極大地簡化應用程序開發者的工作并減輕負擔,但是想要在本地的文件系統之上支持高效地事務機制是非常有挑戰的任務,這篇論文給出了三種實現事務的方法:
圖 4 - 三種實現事務的方式
1.基于文件系統內部的事務機制 — 很多文件系統都在內部實現了事務,這樣能夠原子地執行一些內部的復合操作,然而因為這些事務機制僅用于內部,所以功能非常受限、甚至不可用,所以也就很難利用文件系統的內部事務;
2.在用戶空間實現邏輯預寫式日志(Write-Ahead Log、WAL)— 雖然這種實現方式可以工作,但是它卻會遇到三個比較嚴重的問題;
- 讀-修改-寫操作緩慢(Slow Read-Modify-Write)— 基于 WAL 的日志機制會為每個事務執行如下所示的步驟:序列化事務并寫入日志、調用 fsync 提交事務、事務操作提交到文件系統,因為每個事務在執行前都需要讀取前一個事務執行的結果,即等待三個步驟執行完成,所以這種實現比較低效;
- 非冪等操作(Non-Idempotent Operations)— 部分文件的操作可能不是冪等的,錯誤恢復重放日志時會導致數據發生錯誤的結果甚至數據損壞;
- 雙寫(Double Writes)— 所有數據都會被先寫入 WAL 并隨后寫入文件系統,同時向兩個地方寫入相同的數據會降低一半的磁盤帶寬;
3.使用支持事務的鍵值數據庫 — 元數據存儲在 RocksDB 中,而對象仍然使用文件系統存儲,因為在存儲中寫入對象需要分別將對象寫入文件、將元數據寫入 RocksDB 并調用兩次 fsync,而部分文件系統(JFS)對每個 fsync 都會觸發兩次昂貴的 FLUSH CACHE,這也就是一致性帶來的高額外開銷;
快速元數據操作
本地文件系統中低效地元數據操作對分布式文件系統的影響非常大,當我們使用readdir 操作在 Ceph 中遍歷大的文件目錄時,就可以體會到元數據操作對整體性能的影響。
RADOS 集群中的對象會根據文件名的哈希映射到某一個放置組中,這些對象在遍歷時也會遵循哈希順序,當我們在系統中遇到很長的對象名時,可能需要使用擴展屬性突破本地文件系統的文件名長度限制,查找這些文件時也需要調用 stat 獲取文件的真實文件名進行比對。為了解決系統的緩慢遍歷問題,我們使用如下所示的層級結構來存儲文件對象:
圖 5 - 文件夾和對象
查找或者遍歷文件時,我們會先選擇合適的文件夾,再遍歷文件夾中的對象,而為了減少stat 函數的調用,存儲后端需要保證每個文件夾中的文件盡可能少;當文件夾中的內容逐漸增加時,我們也需要將其中的內容拆分到多個文件夾中,不過這個內容分割的過程卻是極其耗時的。
支持新硬件設備因為分布式的文件系統的運行基于本地的文件系統,而存儲硬件的高速發展會為分布式文件系統帶來更多的挑戰。為了提高存儲設備的容量與性能,HDD、SSD 的提供商通過引入主機管理的 SMR 以及 ZNS 技術對現有的硬件進行改進,這些技術對提高分布式文件系統的性能異常重要,而存儲設備的開發商也在開發新的硬件,這也增加了文件系統的適配成本。
總結傳統的分布式文件系統開發者一般都會將本地的文件系統作為它們的存儲后端,然后嘗試基于本地的文件系統構建更加通用的文件系統,然而因為底層的工具并不能完全兼容,所以這會為項目帶來極大的復雜性,這是因為很多開發者認為開發新的文件系統可能需要 10 年的時間才能成熟,然而基于 Ceph 團隊的經驗,從零開始開發成熟的存儲后端并不要那么長的周期。
從作者的角度來看,Ceph 的演進過程其實是合理的,我們在剛開始構建系統時希望盡可能利用現有的工具減少我們的工作量,只有當現有的工具不再趁手時,才應該考慮從零構建復雜的系統,如果 Ceph 從立項開始就從零構建存儲后端,可能 Ceph 也不會占領市場并得到今天這樣的地位。
本文轉載自微信公眾號「真沒什么邏輯」,可以通過以下二維碼關注。轉載本文請聯系真沒什么邏輯公眾號。