Ceph BlueStore 和双写问题
論開源分布式存儲,Ceph大名鼎鼎。用同一個存儲池融合提供塊存儲、對象存儲、集群文件系統。在國內有近年使用量迅速攀升,Ceph Day峰會也搬到北京來開了。
大型公司內部研發云虛擬化平臺,常使用開源方案Openstack或者Kubernetes,配套的為虛機或容器提供塊存儲的開源方案,幾乎為Ceph莫屬。對象存儲幾年發展迅速,圖像、視頻、網站資源等皆可適用,有初創公司基于Ceph搭建存儲服務方案。企業存儲方面,國外有Redhat收購了Inktank,后者由Ceph初創作者Sage Weil創建;國內有XSky星辰天合,聚集了大量從早期就開始專注Ceph的專家。(P.S.關于國內誰在大規模使用Ceph,上Ceph Day看Slides可以知道。)
可以將Ceph理解為分布式管理層,加上每個存儲節點(OSD)的存儲后端。社區成熟的存儲后端使用FileStore,用戶數據被映射成對象,以文件的形式存儲在文件系統上。文件系統可以是EXT4、BtrFS、XFS等。最近兩年,因為FileStore的種種問題,由Sage Wei推動,Ceph社區合力推出了新的存儲后端,BlueStore。
BlueStore有獨特的架構,解決了Ceph社區一直煩惱的FileStore的日志雙寫問題,測試性能比FileStore提高了一倍。這讓人非常想深入剖析BlueStore。另一方面,公有云內部開發的存儲系統也如同Ceph,歷久年月不斷翻新;像Ceph社區這樣,能夠提出全新架構,把性能提升一倍,是非常值得借鑒的。
關于Ceph BlueStore的資料
CDM(Ceph Developer Monthly)是Ceph開發者之間的分享會議,技術細節原汁原味。下面的視頻非常全面地覆蓋了Ceph BlueStore的動機、設計、工作流程、未來發展等等。Slides鏈接如下,但許多內容只在視頻中(雖然視頻2016但Slides是2017,但內容大體一致)。本文使用了其中的不少插圖。(P.S.經過兩年的開發,如今BlueStore成果顯著;相比應用開發,也可看出底層存儲開發周期之慢…)
[2016-JUN-21 -- Ceph Tech Talks: Bluestore – YouTube]
[BlueStore, A New Storage Backend for Ceph, One Year In]
System Notes博客發布了多篇非常深入的Ceph BlueStore解析,甚至也是國內最早的。本文也直接使用了其中的插圖。下面的鏈接是其中一篇
[System Notes: ceph存儲引擎bluestore解析]
筆記社區WuXiangWei的文章有多篇非常深入的Ceph BlueStore剖析。例如BlueFS設計、對象到磁盤的映射等。本文也使用其中的插圖。下面的鏈接是其中的一篇
[WuXiangWei:Ceph BlueFS分析]
關于Ceph BlueStore以及其它幾種存儲后端的寫行為和寫放大的深入解析,有一篇論文。論文中有對各種后端的寫路徑和相關特性的詳細描述。
[Understanding Write Behaviors of Storage Backends in CephObject Store]
關于Ceph的寫路徑,最全面的資料在它的開發文檔里。其中列舉了BlueStore應對不同類型寫入所采取的策略,結合前述Slides看更加容清楚。
[BlueStore Internals]
為什么需要BlueStore
在上文的CDM的BlueStore介紹中詳細解釋,歸結起來,主要有這些方面:
首先,Ceph原本的FileStore需要兼容Linux下的各種文件系統,如EXT4、BtrFS、XFS。理論上每種文件系統都實現了POSIX協議,但事實上,每個文件系統都有一點“不那么標準”的地方。Ceph的實現非常注重可靠性,因而需要為每種文件系統引入不同的Walkaround或者Hack;例如Rename不冪等性,等等。這些工作為Ceph的不斷開發帶來了很大負擔。
其次,FileStore構建與Linux文件系統之上。POSIX提供了非常強大的功能,但大部分并不是Ceph真正需要的;這些功能成了性能的累贅。另一方面,文件系統的某些功能實現對Ceph并不友好,例如對目錄遍歷順序的要求,等等。
另一方面,是Ceph日志的雙寫問題。為了保證覆寫中途斷電能夠恢復,以及為了實現單OSD內的事物支持,在FileStore的寫路徑中,Ceph首先把數據和元數據修改寫入日志,日志完后后,再把數據寫入實際落盤位置。這種日志方法(WAL)是數據庫和文件系統標準的保證ACID的方法,但用在Ceph這里,帶來了問題:
1)數據被寫了兩遍,即日志雙寫問題,這意味著Ceph犧牲了一半的磁盤吞吐量。
2)Journaling of Journal問題,這個在上述Write Behaviors論文中有講。Ceph的FileStore做了一遍日志,而Linux文件系統自身也有日志機制,實際上日志被多做了一遍。
3)對于新型的LSM-Tree類存儲,如RocksDB、LevelDB,由于數據本身就按照日志形式組織,實際上沒有再另加一個單獨的WAL的必要。
4)更好地發揮SSD/NVM存儲介質的性能。與磁盤不同,基于Flash的存儲有更高的并行能力,需要加以利用。CPU處理速度逐漸更不上存儲,因而需要更好地利用多核并行。存儲中大量使用的隊列等,容易引發并發競爭耗時,也需要優化。另一方面,RocksDB對SSD等有良好支持,它為BlueStore所采用。
另外,社區曾經為了FileStore的問題,提出用LevelDB作存儲后端;對象存儲轉換為KeyValue存儲,而不是轉換問文件。后來,LevelDB存儲沒有被推廣開,主流還是使用FileStore。但KeyValue的思路被沿用下來,BlueStore就是使用RocksDB來存儲元數據的。
展望未來,ScanDisk開源的ZetaScale存儲能夠更加出色地發揮SSD/NVM/PersistentMemory的性能。它有智能內存緩存、最大化并發和減小響應時間、支持原子操作/快照/事務,等等特色。Ceph可能將它作為新的存儲后端,或者替換掉BlueStore中的RocksDB;當然也可以等RocksDB發展得更好。(P.S.其實大半年前已經開始做了。)
BlueStore的架構
BlueStore的出發點其實應驗了這樣的哲學,存儲的最常用寫路徑應該盡量地短、盡量地簡單,這樣才能有最好的性能,盡管另外的異常處理路徑可能是非常復雜的。BlueStore的設計有如下特色
1)Ceph并不需要POSIX文件系統。拋棄它,實現一個盡量簡單的文件系統,專門給RocksDB使用。這個文件系統叫作BlueFS。
2)元數據存儲在RocksDB中,用KeyValue的方式正合適。而數據不需要文件系統,直接存儲在裸塊設備上即可。我們在塊設備上需要的,其實是一個空間分配器(Allocator)。
?
查看BlueStore的代碼,相比FileStore小了很多。Allocator是可插拔更換策略的,大約3000行代碼。BlueFS本就是極簡的文件系統,約3000行代碼。事務的實現借用RocksDB對事務的支持,簡化很多。而且沒有自己實現日志的需要了,剩下了FileStore中的Journal一塊。
還有一點,如上圖所示,BlueStore中不同組件可以使用不同的塊設備。例如給RocksDB的WAL文件配備NVRAM,給SST文件配備SSD,給數據文件配備磁盤;方案是靈活的。
BlueStore的元數據管理
在涉及寫路徑之前,先看看Ceph BlueStore如何管理元數據。首先的問題是,對象如何映射成磁盤數據結構(Ceph的底層是對象存儲,向上封裝出塊存儲、文件系統)?
Onode代表對象,名字大概是從Linux VFS的Inode沿襲過來的。Onode常駐內存,在RocksDB中以KeyValue形式持久化;關于內存Cache的結構,在CDM的Slides中有講。Onode包含多個lextent,即邏輯extent。Blob通過映射pextent、即物理extent,映射到磁盤上的物理區域。Blob通常包括來自同一個對象的多段數據,但是也可能被其它對象引用。Bnode是對象快照后,被用于多個對象共享數據的。
?
上面僅是關于對象映射的。更進一步,RocksDB中存儲有許多類型的元數據,包括塊分配、對象集合、快照、延遲寫(Deferred Writes)、對象屬性(Omap,即一個對象上可以附加一些KeyValue對作為屬性,例如給圖片加上地點、日期等),等等。在CDM的Slides中有詳述。
?
BlueStore的寫路徑
寫路徑包含了對事務的處理,也回答了BlueStore如何解決日志雙寫問題。
首先,Ceph的事務只工作于單個OSD內,能夠保證多個對象操作被ACID地執行,主要是用于實現自身的高級功能。每個PG(Placement Group,類似Dynamo的vnode,將hash映射到同一個組內的對象組到一起)內有一個OpSequencer,通過它保證PG內的操作按序執行。事務需要處理的寫分三種:
1)寫到新分配的區域。考慮ACID,因為此寫不覆蓋已有數據,即使中途斷電,因為RocksDB中的元數據沒有更新,不用擔心ACID語義被破壞。后文可見RocksDB的元數據更新是在數據寫之后做的。因而,日志是不需要的。在數據寫完之后,元數據更新寫入RocksDB;RocksDB本身支持事務,元數據更新作為RocksDB的事務提交即可。
2)寫到Blob中的新位置。同理,日志是不需要的。
3)Deferred Writes(延遲寫),只用于覆寫(Overwrite)情況。從上面也可以看到,只有覆寫需要考慮日志問題。如果新寫比塊大小(min_alloc_size)更小,那么會將其數據與元數據合并寫入到RocksDB中,之后異步地把數據搬到實際落盤位置;這就是日志了。如果新寫比塊大小更大,那么分割它,整塊的部分寫入新分配塊中,即按(1)處理,;不足的部分按(3)中上種情況處理。
?
上述基本概述了BlueStore的寫處理。可以看到其是如何解決FileStore的日志雙寫問題的。首先,沒有Linux文件系統了,也就沒有了多余的Journaling of Journal問題。然后,大部分寫是寫到新位置的,而不是覆寫,因此不需要對它們使用日志;寫仍然發生了兩次,第一次是數據落盤,然后是RocksDB事務提交,但不再需要在日志中包含數據了。最后,小的覆寫合并到日志中提交,一次寫完即可返回用戶,之后異步地把數據搬到實際位置(小數據合并到日志是個常用技巧);大的覆寫被分割,整塊部分用Append-only方式處理,也繞開了日志的需要。至此,成為一個自然而正常的處理方式。(P.S.總之,個人感覺日志雙寫不是一個該存在的問題,不知為何成了一個問題,好在今天終于不是問題了。)
更深入地,Ceph的開發文檔中列出了所有的寫策略處理方式。可以看到Inline Compression也是BlueStore的功能點之一;其中也有對Partial-write問題的處理。
?
CDM的Slides中有BlueStore寫的狀態機圖。狀態機是存儲中常用的處理方式,處理寫路徑,Ceph的PG Peering過程也有相應的狀態機。數據落盤,對應的是PREPARE->AIO_WAIT間的“Initiate some AIO”一步。之后經過多個隊列,向RocksDB提交事務,以及完成Deferred Write和Cleanup。直到最終完成。
?
另外,BlueStore使用Direct IO提交數據,這樣數據會立即落盤,而不是在內核中緩存;從而,存儲系統可以完全自主地控制寫的持久化。這是一個如今常見的做法。但代價是,不能利用內核緩存,需要自己處理緩存問題;也必須處理好數據對齊,以及寫小于一扇區時的Partial-write問題。
BlueFS的架構
BlueFS以盡量簡單為目的設計,專門用于支持RocksDB;RocksDB總之還是需要一個文件系統來工作的。BlueFS不支持POSIX接口。總的來說,它有這些特點:
1)目錄結構方面,BlueFS只有扁平的目錄結構,沒有樹形層次關系;用于放置RocksDB的db.wal/,db/,db.slow/文件。這些文件可以被掛載到不同的硬盤上,例如db.wal/放在NVMRAM上;db/包含熱SST數據,放在SSD上;db.slow/放在磁盤上。
2)數據寫入方面,BlueFS不支持覆寫,只支持追加(Append-only)。塊分配粒度較粗,越1MB。有垃圾回收機制定期處理被浪費掉的空間。
3)對元數據的操作記錄到日志,每次掛載時重放日志,來獲得當前的元數據。元數據生存在內存中,并沒有持久化在磁盤上,不需要存儲諸如空閑塊鏈表之類的。當日志過大時,會進行重寫Compact。
下圖見于CDM的Slides,顯示了BlueFS在磁盤上的數據結構。Superblock用于存儲整個文件系統級別的元數據,日志和數據本著盡量簡單的設計,按照追加的方式不斷寫入。關于寫放大的問題,這是Append-only式通有的,在Write Behaviors論文中有詳述。
BlueStore的性能
如果問為什么BlueStore相比FileStore能夠提高越一倍的吞吐量,可能在于其更加簡單、更加短的寫路徑;解決了雙寫問題,大部分數據不再需要在日志中多寫一遍;借用RocksDB處理元數據,后者實現成熟,對SSD優化良好。
?
更重要的,和Ceph類似,公有云內部開發的存儲系統也歷久年月不斷翻新;像Ceph社區這樣,能夠提出全新架構,把性能提升一倍,是非常值得借鑒的。
總結
以上是生活随笔為你收集整理的Ceph BlueStore 和双写问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 多窗口管理器Tmux - 从入门到精通
- 下一篇: tmux多窗口工具基本操作