たごもりすメモ

コードとかその他の話とか。

Fluentdのflush_mode immediateはいつ使うのか

Fluentd実践入門をあらためて手元でぱらぱらやってたら、しまった! この話をどこかにちょっとでも書こうと思ってたのに忘れてた! という話が出てきたので、忘れないうちに書いて放流する。

flush_modeとはなにか

FluentdのOutputプラグインには<buffer>セクションで指定できるflush_modeというパラメータがあって、これはOutputプラグインがどういう基準でバッファ内のデータを書き出す(writeメソッドを呼ぶ)かという戦略をコントロールする。有効な値はdefaultimmediateintervallazyの4つ。

ただし多くのケースでこのパラメータは明示的には指定されていないはず。というのも、デフォルト値であるところのdefaultの場合には、<buffer>セクションに指定されている他のパラメータ((と、例外的に<buffer>セクションの外側に指定されているflush_intervalも見ている。これはFluentd v0.12以前のプラグインの使い方をそのまま踏襲している設定について、動作を壊さないための措置。))を確認して適切なモードを自動的に選ぶようになっているからだ。たとえばバッファのチャンクキーにtimeが指定されている場合にはlazyが選ばれる。

といったようなことは「Fluentd実践入門」のp166-167あたりにもちろん書いてある。みんな買って読もう!(宣伝)

flush_mode immediateとは何か

ところで、flush_modeのうちには、他のパラメータをどうセットしても暗黙には選ばれないものがあって、それがimmediateだ。これはFluentd v1系*1における完全に新しい機能・挙動なので、特に過去の設定パターンとの互換性を考える必要がないため。

これがどう動作するかというと、バッファリングは行うが、データが書き込まれたバッファチャンクは即座にflushされる。つまり一回のemitで渡ってきたデータは即座にwriteに渡される。

flush_mode immediateは低レイテンシ、かつ出力リトライが必要な場合に使う

ここからが書き忘れたところ。

immediateは、動作としては非バッファOutputプラグインに近いが、データが一度バッファチャンクに書き込まれる点が異なる。で、このモードをどう使うのかという話。

データ処理基盤を作っていると、とにかくこのデータだけは低レイテンシで処理したい、ということがたまにある。全データに低レイテンシを求めるのは非効率だが、それでもごく一部のデータに限ってであれば、イベントの発生から処理の最後、典型的にはオペレータへの通知など、までを数秒で行いたいというような要求はありうる。

ただし、低レイテンシで処理を行うからには非バッファOutputプラグインを使えばいいかというと、それも困るケースがある。ネットワーク転送などを行っているときに障害が発生したら即座にデータが失われるようではマズい。このため、普段は可能な限り低レイテンシで出力を行うが、障害時にはバッファリングとリトライを行い、その間にOutputプラグインが受け取るデータはバッファチャンクに適切に貯まるようにしたい。flush_mode immediateを指定していればこれが実現できる。

過去に(現在でも?)これを実現する方法のひとつとしては、flush_interval01にセットしてしまうという手があり、実際にやっている例も知っている。ただしこれはデータの到着にバラつきがあるときでもflushスレッドがかなり忙しくループしてしまうため、全体としてはあまり効率的ではない、という問題があるし、設定の意図があまり明確ではなくなるという難点もあった。

immediateは気軽に使っていいのか

あまり気軽に使うのはオススメしない。バッファOutputプラグインは実装としては通常の、バッファチャンクが適切なサイズに育ってから一気に出力するような処理をするように書かれているだろうから、それを半ば無理矢理に高頻度で呼ぶようになるので、想定していなかった問題が起きないとも限らない。

またflush_mode immediateを使って出力を行っている場合、通常の状況では出力単位が1〜数イベント、サイズにして数KB程度までとなることが多いだろう。一方で障害時にはリトライを続けている間に到着したデータはchunk_limit_sizeで設定したサイズまでチャンクに溜め込まれるため、障害が解消した直後はいきなり数MBのデータがどかっと出力されることになる。出力データサイズの不均衡は後々の処理において、処理性能や使用メモリサイズなどの点で問題を誘発することが多い。

なので、データ処理パイプライン全体をちゃんと考えて、どうしても低レイテンシ・出力リトライを両立させたいところのみでflush_mode immediateを使用しましょう。

まあ、実際のところこれを必要とするのはごく一部の大規模なデータを扱っている人達だけじゃないかなとは思う(ので書き忘れてた)。他にも大規模データ基盤向けの話はいくつもあるんだけど、それをまとめた章を書こうとしたときに手が止まったんだよなあ。対象読者数があまりに少ない内容になるんで……。

というようなことが

Fluentdの他の部分についてえんえんと書かれているFluentd実践入門をよろしく!!!!!!

Fluentd実践入門 ──統合ログ基盤のためのデータ収集ツール:書籍案内|技術評論社

amzn.to

*1:v0.14以降のこと