夢とガラクタの集積場

落ちこぼれ三流エンジニアである管理人の夢想=『夢』と、潰えた夢=『ガラクタ』の集積場です。

Apache Kafkaってそもそも何か確認してみます(その3

こんにちは。
とりあえず前回の続きを。

6.メッセージの永続化/保持

ファイルシステムを恐れるな!

Kafkaはメッセージの保存と保持にあたってファイルシステムに密接に依存している。
ディスクは遅いという一般見解があるため、
こう書いてしまうと性能を確保できるか疑われるかもしれない。

ただ、実際のところディスクはどう使うかで大きくパフォーマンスが変わる。
ディスクの構造に併せた設定を行えば、ネットワークと同等の性能を出すことも可能である。

ディスク性能に関するポイントは、
ディスク性能はディスクのシークによって遅延が発生するということ。

実際のところ、シーケンシャル領域に対する書き込み性能は
6台構成の7200rpmのSATA-RAID5ディスクで300MB/secにも達する。
だが、ランダム書き込みは50KB/secまで落ち込んでしまう。
実に、10000倍近い差が出てくる。

連続的に読み書きは利用方法に応じて予測可能。
ゆえに、事前読込/遅延書込を駆使して論理的な小さい読込/書込に
マージすれば、ディスクの性能を引き出すことができる。

上記の関連情報として、下記の情報がある。

つまりは、シーケンシャルなディスクに対するスループットは、
ランダムなメモリアクセスを上回る。

上記にあるような性能の差分を補うために、
最近のOSはメモリをディスクのキャッシュ領域として積極的に用いている。

最近はどんなOSでもメモリ解放の(若干の)性能負荷を見込んだ上で
空きメモリ領域を全てディスクキャッシュとして転用している。

ディスク読込/書込は上記のディスクキャッシュを通して行われる。

そのため、プロセスが保持しているプロセス内キャッシュが
OSの保持しているページキャッシュと重複してくる。
結果、重複した書き込みが行われる状況を
ダイレクトIOを用いずに解消することは容易ではない。

更に忘れてはならない内容として、JVM上の
Javaのメモリ利用として下記の2つを押さえておく必要がある。

1.オブジェクトのメモリオーバヘッドが大きく、しばしば重複して保持される
2.JavaGCはヒープ上のデータが増えるにつれて、大雑把かつ負荷は増大する

上記の要素の結果として、
ページキャッシュに依存したファイルシステム
メモリキャッシュなど他の領域に保持するより優れたものとなってくる。

全空きメモリの少なくとも倍のキャッシュを保持することで、
個々のオブジェクトに着目するより最終的に保持するバイト数は小さくなる。
結果、メモリが32GBのマシン上で28-30GBのキャッシュをGCのペナルティなしで持つことが可能となる。
#この辺うまく訳せていません。
#とりあえずプロセス内キャッシュを使うより素直にOSの機構を使え、ということなのは確かですが。

その上、これらのキャッシュはプロセスが再起動しても保持されます。
対して、プロセス内キャッシュの場合プロセス再起動時に再度初期化するか、
初期化用データを破棄してコールド起動する必要があります。
(キャッシュ初期化には10GBで10分かかるということもあり得ます。
 また、コールド起動の場合初期のパフォーマンスが低下します。)

加えて、キャッシュとファイルシステムの同期を
プロセスで1回行うという実装と比べて確実に実施されるOSにゆだねる事によって、
コードが簡略化されます。
また、ディスク使用が線形アクセスが多い場合、
ページキャッシュによる先読み機構がより有効に作用します。


これまで記述した設計は出来る限りメモリ上にデータを保持し、
必要な場合のみディスクに出力する・・・という設計と比して非常にシンプルです。
全てのデータは特に書き込み命令の実施無しに常時永続化されます。
→ 実際にはOSが後で永続化するためのファイルキャッシュに書き込むのみです。

ハードクラッシュによって消えるリスクがある状態のメッセージ増大を防ぐため、
一定時間ごと/一定数のメッセージを保持するたびに物理ディスクへの書き込みを行う
設定の追加を可能としている。

ページキャッシュ中心のこの設計はこのページを参考にしてほしい。
理解の手助けとなるはずだ。

=====

・・・英語をうまく訳せていませんね(汗
とりあえず、ポイントは下記のようです。
・ディスクは正しく使えば早い
・下手にプロセス内キャッシュを保持するよりOSにゆだねた方がいい
・その上で、OSに出力命令を出す機構も持たせている

ただ、ハードクラッシュが発生したら永続化していなくても
どちらにしてもNGな気はしますが・・・
その辺りは違う例やでカバーされているという前提なんでしょうかね。