Overview

Cassandraの書き込みはまずコミットログ(CommitLog)に対して行われます。そしてColumnFamilyごとにMemtableと呼ばれる構造体に対して書き込まれます。Memtableは基本的にキーで参照可能なデータ行のライトバックキャッシュです。つまりライトスルーキャッシュと違ってSSTableとしてディスクに書き込まれる前に、Memtableが一杯になるまで書き込まれます。

Flushing

MemtableをSSTableへ変換するプロセスをフラッシュ(flushing)と呼びます。JMX経由で(例えばnodetoolを使用して)手動でフラッシュを実行することも可能です。コミットログのリプレイ時間を短くするためにノードを再起動する前に行った方が良いでしょう。Memtableはキーでソートされ、シーケンシャルに書き出されます。

したがって書き込みは超高速に行われます。コミットログへの追記とフラッシュ時のシーケンシャルな書き込みしかコストがかかっていません!

一旦フラッシュされると、SSTableのファイルは変更不可能になります。それ以上の書き込みはできません。したがって読み込み時には、要求されたデータを生成するためにサーバーは(潜在的にはブルームフィルタなどのトリックを使用して余計な読み込みは回避しているのですが)すべてのディスク上のSSTableとまだフラッシュされていないMemtableから行の断片を組み合わせる必要があります。

Compaction

読み込む必要があるSSTableファイルの数を制限するため、また使用されていないデータによって埋められているスペースを取り戻すために、Cassandraはコンパクションを行います。コンパクションとは複数の古いSSTableファイルをひとつの新しいファイルにマージすることです。コンパクションは少なくともN個のSSTableがディスクにフラッシュされた場合に実行されます。Nは設定可能ですがデフォルトは4です。4つの似たようなサイズのSSTableが1つのSSTableにマージされます。SSTableはMemtableのフラッシュ時のサイズと同じサイズから始まって、サイズが最大N倍になりながら階層的に形作っていきます。したがって、まずMemtableと同じサイズのSSTableがN個まで作成され、次にそれらの最大N倍のサイズで作成され、そして次にそれらの最大N倍のサイズで作成され、というように形成されます。

"マイナー"コンパクションは同じようなサイズのSSTableをマージします。"メジャー"コンパクションはあるColumnFamilyのすべてのSSTableをマージします。0.6.6/0.7.0以前ではメジャーコンパクションの時だけtombstoneのついたデータの削除が行われます。

入力元となるSSTableはすべてキーでソートされているため、マージは効率良く行われランダムI/Oを必要としません。コンパクションが終了すると古いSSTableファイルは削除されます。注意点としては、最悪の場合(上書きや削除がないデータで構成されている場合)今使用している容量の倍のディスク容量が一時的に必要になります。数TBのディスクが主流の現在はあまり問題になりませんが、警告のための閾値を設定する場合には注意しておくと良いでしょう。

コンパクションによって廃棄されたSSTableはJVMがGCを行う際に非同期に削除されます。必要に応じてjconsoleからGCを実行できますが、Cassandraはディスク容量が少なくなってきたのを検知すると自動でGCを実施します。また、GCが行われずに再起動した時のために、起動時に削除されるよう廃棄されるはずのSSTableにコンパクションの印を追加しておきます。

ColumnFamilyStoreMBeanはSSTableが使用している領域に関して、getLiveDiskSpaceUsed(廃棄されていないファイルのみ含む)とgetTotalDiskSpaceUsed(すべてを含む)の操作を公開しています。

(Memtable/SStableの高レベルな設計と名前は、GoogleのBigtableに関する論文のセクション5.3と5.4を参考にしています。ただしコンパクション周りの用語は若干異なります。)

http://wiki.apache.org/cassandra/ArchitectureSSTable

https://c.statcounter.com/9397521/0/fe557aad/1/|stats

  • No labels