CubeFSの論文を読んだ
CubeFS(ChubaoFS)の論文を読んだのでメモ
CubeFSの論文を読んだ。
この論文の著者欄は中国科学技術大学とjd.comのエンジニアとなっているが、
このメモは論文の単なる要約ではなく、私自身の意見も踏まえた上で書いているので誤解している箇所もあるだろうし、論文に書かれていないことも書いているのであくまでただのメモだと認識してほしい。
背景
現代のコンテナが一般的となったシステムでは、計算が実際に行われるノードとストレージの結合を上手く抽象化してやる必要がある。密結合な状態ではコンテナの動的なスケジューリングは難しい[1]。
加えて、ストレージシステムにはメタデータサービスが必要だがシングルノードのメタデータサーバはハードウェア限界からボトルネックが生まれる[2]。
そしてPOSIXの厳格なインターフェースは性能向上を図る上でとても厄介だ。
これらの問題に対処するために作られたCubeFSは以下の特徴を持つ
- 汎用高性能ストレージ
- Linuxのpunch holeインターフェースの活用がキモである
- シナリオ別のレプリケーション
- appendとoverwriteの2つのレプリケーション戦略の使い分け
- 使用量を考慮したメタデータの配置
- メタデータのリバランシングを回避する
- MooseFSも同様のアプローチを取っている
- POSIXマンティクスの緩和と原子性の保証
- 厳格なPOSIXせマンティクスは性能を稼げないので、注意深く弱めた
- (私見)これはみんなやってること
アーキテクチャ
Metadata subsystem、Data subsystem、Resource managerの3つのコンポーネントからなる。
Volumeはクライアントから見た場合は1つのファイルシステムと同じように見えて、マウント可能である。
Resource managerはシステム自体の管理を行うノードでNodeの追加や削除などのメタ的な操作を処理し、
メタデータサーバ
inodeとdentryを扱うBTree、free listなどをインメモリに持つ構造。
データサーバ
複数のData partitionを持つ。Data partionはextent store
データサーバはある境界値t(デフォルトだと128 KB
)より小さいものを
Large fileは単一または複数のextentを排他的に使う。
Small fileはextentを共有する。extentとオフセットの情報はメタデータサーバに記録され、fallocate
で領域を確保することで細かいストレージ管理をLinuxに委任している。
シナリオ別のレプリケーション
Sequential Writeはprimary-backupレプリケーション、
primary-backupレプリケーションで上書きを行うとその度に新しいextentが発生し、
一方でoverwriteレプリケーションはWrite ampiliationを発生させるが、
Failure recovery
まずはprimary-backupレプリケーションでextentを用意し、
またデータパーティションは古いデータが残っていることを許容する。
リソースマネージャ
シングルノードではなくマルチノードでメタデータサービスを構築する場合の手法として、
lazyhybridやdynamic partitioningといった手法による対処もあるが、
使用率ベースの分散は単純な方法でこれを解決する。
また、メタデータについてはテーブルの分割が必要になる場合がある(inodeかdentryが上限に達した場合)
また何らかの障害でメタデータパーティションが利用不能となった場合は残りのレプリケはreadonlyに設定され、
クライアント
FUSEで提供され、データそれ自体を除く多くの情報をキャッシュする。
最適化
- heatbeatの最小化
- これは所謂MultiRaftそのもの
- 非永続的なコネクション
- 大量のコネクションが保持され続けるのはリソースの無駄
メタデータ操作
多くのPOSIXに準拠したファイルシステムは空間的局所性のために同じノードに
そこでトレードオフとして、dentryが 常に 少なくとも1つのinodeに結び付けられている場合に原子性の要件を緩和する。fsck
のようなツールも提供している。
Create
Resource managerがメタデータパーティションを割り当てるので、unlink
リクエストを送り、evict
リクエストによってGCされる。
Link
inodeでnlink
をインクリメントしてからdentryを作成する。nlink
を巻き戻す
Unlink
dentryを削除し、inodeのnlink
をデクリメントする。nlink
が0ならOrphan listに追加する。
ファイル操作
CubeFSは逐次一貫性のみを保証し、複数のクライアントからの同時書き込み防止などのメカニズムは提供しない(提供されるとSSFとかがまともに使えないのでこの方が良い気がする)
Sequential Write
Sequential writeでは逐次的に固定サイズのパケットをリーダーへ送り続ける。fsync
が呼ばれるか、または一定の周期でメタデータサービスとの同期を行う。
Random Write
Sequential Writeとの差分はレプリケーションがRaftで行われること、
削除
メタデータサービスからの削除は既に述べたとおり。
読みとり
読み取りは Raftの リーダーノードからのみ行われる(Primary-backupレプリケーションのリーダーはRaftのリーダーとは異なる場合がある)
Disucssion
Centralization v.s. Decentralization
Centralizationアプローチは単一のサーバーがボトルネックとなりやすい反面、
CubeFSは全体としてはCentralizationアプローチを採用しているが、
メタデータとデータを切り離すかどうか
CubeFSはメタデータとデータを切り離している。
(HPC向けの高パフォーマンスファイルシステムもメタデータとデータを分散させる構成を取るものが多い)
一貫性モデル
低レイヤのストレージ層はprimary-backupとRaftの二種類のレプリケーションプロトコルを用いて
比較
同様のハードウェア構成をとったCephと比較した。Cephはbluestore
を用いている。ior
のmdtest
を用いている。TreeCreation
以外は2から5倍ほどのパフォーマンスの優位性がある。 fio
を用い、40 GiB
のファイルを操作した。
関連研究
- GFS, HDFS
- 大きなファイルを志向。スケーラビリティのためにメタデータサービスを分割している
- Haystack
- ログ追記型でメタデータをinmemoryに持つ
- CubeFSはpunch holeを活用してより良いパフォーマンスを実現する
- 一貫性もCubeFSの方が強い
- Windows Azure Storage
- ランダム書き込みを低レイヤに渡す前に専用のレイヤがある
- PolarFS
- RDMA, NVMe, SPDKといった技術を活用している
- OctopusFS
- Storageのtieringを行う
- GlusterFS
- MooseFS
- 高機能だがメタデータサーバは単一
- MapR-FS
- Cephとにている
Footnote
- 1.
ここだとネットワーク越しにストレージを提供するアプローチの話をしているが、
TopoLVMのように ストレージに合わせて計算をスケジューリングするアプローチもある。 こちらのアプローチだとストレージとの通信がSATAやNVMeとなるので 低レイテンシ高スループットになるしスケジューリングも自動化されている。 その一方でノード障害には弱い(LVMなので可用性はRAIDで担保するしかない)し、 ストレージノード間のデータ移動も難しい。また、NVMoFでIBやSlinghshot使えばよく無い? みたいな身も蓋もない意見もあり得る……。 - 2.
メタデータサーバが単一だとボトルネックになると論文では主張しているが、
これに関しては全く逆の意見もある。 現代のCPUアーキテクチャではもはやシングルノードですら内部バスで繋がった分散システムだが、 それでもノード内とノード外の通信のコストは全然違う。 強力なSmartNICと大量のDRAMを積み強力なCPUで動かせばシングルノードの方がむしろ 性能出るんじゃ無いかという話もある。 SingularFSは(まだ論文読めてないが)このアプローチを取っている。 IO500の上位システムはもはやCPU 2 cycleで1回のメタデータ操作しているし(わけわからん) 以外と無茶苦茶な話でも無いのかもしれない。 DRAMで巨大なメモリ空間を用意するのは大変だしそもそも永続化出来ないじゃんという話については Persistet Memoryがあった。今は(ほぼ)死んだけどCXLで復活するかもしれないし。 とは言えこれは耐障害性をあまり考えなくてもよく、かつ金を掛けられるHPCでの話なので Webサービスを提供する会社だとまた話は変わってくる。