Go ahead!

Memoization for Everything

YAPC::Asia 2014

| Comments

YAPC::Asia 2014に初めて参加した.

Perl使ってないし最初は行く気なかったんだけど,登録中のセッション見るとPerlじゃないの多いし, 個人スポンサーになればTシャツやパーカーも貰えると言うことで,個人スポンサーでチケット入手.

0日目は参加せず,1日目は朝から,2日目は昼から参加.

1日目

完成されたシステムなどない。完成された人間もいない。あるのは成長し続ける未完成なシステムと、それを支える未完成な人間だけだ

YAPCでのTEDを目指したという発表.大ホールの暗い雰囲気と,宇宙に覆われたスライドによって, 宗教的な感じがしたプレゼン.

発表時間の半分で発表そのものは終わったのだけど,質疑応答をもっと盛り上げれば,完成度は上がったんじゃ無いかと思う.

お待たせしました。Perl で BDD を簡単に実践する最高にクールなフレームワークができました

一番Perlっぽい話かな,と思って参加.Perlのテストにおける歴史みたいなのとか, エコシステムの話みたいなのが聞けたのは面白かった.

「Perl 6と同じくらい夢が詰まっている」という言葉,つらい.

作られては消えていく、泡のように儚いクラスタの運用話

TV番組用システムの裏側の話.あるある系もあったり,便利そうなコマンド作ってたり, なかなかみんな苦労しているな,と.最近TV系の運用話はちょくちょく聞くので,どこも似ている感じ.

ライブコーディング

songmuさんともずにおんのコンビ漫才を休憩がてら見ていた.やっぱ本番では色々とミスが起きるw

ここで食べたDMMかき氷,普通に美味しかった

O2O/IoT/Wearable時代におけるWeb以外のネットワーク技術入門

IoT周辺の技術の用語とか仕組みの説明.いやー,しかしこの辺りは略語が多くてすぐ覚えるのがつらい.

その後はセッションには参加せず,休憩スペースで何人かでISUCONとかPHPとか色々とだべっていた. MQTT Meetupに参加する予定があったので,懇親会には参加せず会場を去った.

2日目

naoyaさんの発表をにやにやしながら見ようかと思っていたのだけど,起きたらもう終わっていたのが心残り.

ついた時間も中途半端だったので,naoyaさんとHUBに行き,そこでmiyagawaさんとかけんじおじさん,shiba_yuさんとかとしゃべっていた. 時間が経つと色々と人が集まってきたのだけど,大ホールの席を取るため移動.

そんなにビッグでもないデータ処理手法の話

言うことはないというか,全部知っている話だったので内職をしていた.が,ベストトークで2位だったので, やっぱ分野が違うと受けるトークも変わるんだなぁという.

ただ,最初にモリスさんがFluentdのユーザを聞いてくれたら半分くらい?は手をあげていたので, ちゃんと浸透してるんだなと嬉しく思う反面,あと半数にどうやってリーチすべきかというのも考えないと行けない.

モリストリーム…じゃなくてNorikraの宣伝が少なかったな,という印象.

Lightning Talks Day 2

席を取っていて良かった,というくらい人がわらわらと集まってきていた.

FluentdがTwitterで非常にアクティブに議論・サポートされている話とか出てきて,Twiterの監視社会怖い!
やっぱLTは短い中にネタを押し込んでくる人が多いので,それ故に面白いのだけど,すぐ終わるのがちょっと悲しい.

キーノート

typesterさんのエモい話.typesterさんのキャリアって他の人が真似するのはかなり難しいのだけど, 話の中でも出ていた「複数の人のロールモデルを参考にする」というのに結局落ち着く.

お子さんも一緒に来ていて,ほっこりする感じの発表だった.

あと,typesterさんはIngressは緑のLv8だったので,青のLv8の俺とどこかでやりあってたかも, と思ったけど鎌倉だし全然関係なかった.

HUB

そうそうに一つのビールが無くなっていたけど,ジンジャーエール派の俺には関係なかった. 土曜日は夜に外せない用事があるので,色々な人に絡んでから,早めに帰った.

改善点

他の人も書いてると思うけど,意見が多いとそれだけ反映されるだろうということで書いておく.

キャパシティプランニング

今年の参加者は約1300人で,それに対して会場のキャパシティは約500人らしく,非常に狭かった. 特に多目的教室は毎度部屋から出るくらいまで立ち見とか出ていたので,ちゃんと聞けない人も多かったのではないかなと.

去年も同じ場所で約1100人だったらしいけど,去年は大丈夫だったのかな?参加してないのでよく分からない. この辺のマネージは本当に難しいので,一発で解決のアイディアは提示できないのだけども…

トーク間の移動時間

2つのトークが続いて休憩がないのがいくつかあって,これは質疑応答と移動時間がかぶってしまうので勿体ないなと.

まとめ

トークの種類がPerlに限らず色々とあり,それに伴って参加者も結構多様な感じがしていて楽しかった. ベストトーク賞のベスト3がどれもPerl関係ないのが,それを物語っていると思う.

ネットワークも快適だったし,休憩スペースも飲み物とかあって,セッション以外でぶらぶらするのも困らなかった.

1000人規模の運営超大変だし,運営チームの方達は本当にお疲れ様でした!来年も楽しみにしてます :)

Fluentd v0.12でのFilterとLabel

| Comments

Fluentd,最近だと海外でも露出が増えてきていて,軽量・柔軟・ロバストという所で, 新規の他,既存のログコレクタのリプレース含め,採用する所が増えてたりします.

より改善するため色々とユーザにヒアリングした結果,「フィルタ機能が欲しい」というのが一番多い意見でした. Fluentdは元々Treasure Dataへロバストにデータを転送するためのミドルウェアで,「ETLとかはTreasure Dataで」 というのもあり,組み込みでフィルタ機能はありませんでした.

今現在のOutputプラグインによるフィルタ実装は,タグの書き換えが必要だったりして少し慣れが必要で,初心者にはちと難しい. ということで,より簡単に効率よくデータストリームを扱えるフィルタ機能を入れることにしました!

前置きが長くなりましたが,次のバージョンであるv0.12ではFilterとLabelの導入が目玉機能になります. これらは二つともデータストリームの処理をより楽にするための機能です.

後,Fluentd v0.10.53のリリースアナウンスでも書きましたが, 今現在のmasterブランチはすでにv0.12用になっています.また,以下の機能はまだmasterにはマージされていません.今週中にはマージ予定ですが, 試して見たい方は,PR #416をチェックしてください.

Filter

Outputプラグインで出力する前に,イベント群に処理を適用するための仕組みです. greprecord_refomergeoipプラグインなどは,Filterとして実装することでより効率良く処理出来るようになります.

最初に実装,その後に設定の例を見せます.

実装

FilterのAPIは以下のようになっています.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module Fluent
  class SomeFilter < Filter
    Plugin.register_filter('some_filter', self)

    def filter(tag, time, record)
      # レコードを弄るプラグインは,ここを実装すればOK
      # レコードを返す必要がある
      modified_record
    end

    def filter_stream(tag, es)
      # 以下はFilterのデフォルト実装.grepなどはこちらを置き換えればOK
      new_es = MultiEventStream.new
      es.each { |time, record|
        new_es.add(time, filter(tag, time, record))
      }
      new_es
    end
  end if defined?(Filter) # v0.10とかでエラーにならないための回避策
end

filter(tag, time, record)

SetXXXMixinを置き換えるadd_metadataフィルタを見て貰えればわかりやすいと思いますが, 引数で渡ってくるレコードを弄って,それを返り値にするだけです
filterとは違いfilter_streamは上記のデフォルト実装があるので,変更する必要はありません.

大抵のプラグインはこのAPIをオーバーライドして処理を実装すれば,その結果が次のフィルタに渡されるようになります.

filter_stream(tag, es)

EventStreamを直接処理するFilterを書くためのAPIです.例えばgrepはレコードを弄らず,EventStream全体に対して処理を行うプラグインなので, このAPIをオーバーライドします.filter_streamを変更する場合,filterを変更する必要はありません.
filterとは違い,返り値としてEventStreamを返す必要があります.Fluentdは,このfilter_streamの返り値を次のFilterに渡し,最終結果をOutputプラグインに渡します.

また,record_reformerrenew_recordのように,新しくレコードを生成する系のプラグインもこちら側で処理を実装することになります. greprecord_reformerのFilter例は以下にあります.

設定

<filter>セクションが追加されています.たとえば,add_metadatagrepを使う場合には以下のようになります.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<source>
  type forward
</source>

<filter> # <filter>と<filter **>は同じ
  type grep
  input_key message
  regexp WARN
</filter>
<filter>
  type add_metadata
  include_tag_key
</filter>

<match **>
  type stdout
</match>

Fluentdの設定ファイルの流儀にしたがって,上から順番にmatchにマッチしたところまでのFilterが適用されます. この例では,まずgrepが適用され,その次にadd_metadata,そしてこれらの結果のEventStreamがstdoutに渡されます.
例えば以下のデータが入ってきたとして:

{"message":"INFO"}
{"message":"WARN"}

stdoutには,grepで最初のレコードがフィルタリングされ,add_metadataでタグが追加された以下のデータが渡されます:

{"message":"WARN", "tag":"filter.test"}

タグを書き換えてmatchの条件を調整して〜という煩わしさから解放されるようになります.

注意点としては,マッチしたmatchの下にあるfilterは,たとえtagがマッチしようが適用されない所です.

パフォーマンス

タグの書き換えや再emitが発生しないため,速度やメモリ効率は多少よくなるはずです.

手元で約450MBのファイルをin_tailで読み込み,record_reformerでホスト名などを付加して転送する, というのをv0.10とv0.12で測ってみた所,v0.10は181秒,v0.12は149秒で,約30秒短縮されました.

ユーザによってはもっとFilterがチェーンしている所もあるはずなので,そういう場合には恩恵が大きいと思います.

Label

これはFilterやOutputをまとめるための機能になります.制限として,InputはLabelの中に含めることは出来ません. こちらは先に設定から見てみます.

設定

以下が簡単な例になります.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<source>
  type forward
  @label @forward
</source>

<source>
  type tail
  path /path/to/file
  tag tail
</source>

<filter **>
  type grep
  # ...
</filter>

<match **>
  type mongo
  # ...
</match>

<label @forward>
  <filter **>
    type add_metadata
    include_tag_key
  </filter>
  <match **>
    type file
  </match>
</label>

forwardの中に@label @forwardというパラメータがあります.これがLabelの指定になっていて, @labelがあるとその指定されたLabelにイベント群が流れて行きます.なので,この例ではforwardで 受け付けたイベント群は,add_metadataフィルタを通り,その下のfileに到達します.
一方,@labelのないInputは今までと同じ挙動となり,トップにイベント群を流します. この例では,grepフィルタを通り,その下のmongoに到達します.

Labelの機能によって,各プラグイン間の関係がわかりやすくなり,またルーティングのためにタグを調整する必要もなくなります. out_relabelプラグインを使えばデータを別のLabelに飛ばせるので,入力によって違うフィルタを適用したいが,書き込み先は一緒にしたい, みたいな処理も簡単にできるようになります.

実装

v0.12から,routerというのがInput/Outputに増えてます.今までEngine.emitと書いていた所を,router.emitに書き換えるだけで, Labelの機能が使えるようになります.
言い換えれば,この書き換えをしていないInput/Outputプラグインは,@labelが使えないということになります.

まとめ

v0.12の主要機能であるFilterとLabelについて簡単に説明しました.まだ実装としていくつか細かな改善はあるのですが, 基本機能は上記のままで行くと思います.
何かフィードバックがあれば@repeatedlyにmentionをするか,上記の該当PRにコメントをして貰えればと思います.

Fluentd UI

| Comments

fluent/fluentd-ui

"Fluentd UI image"

Fluentdのエコシステムの一つとして,Fluentd UIをリリースしました. すでに試してくれたユーザもいるようなので,現在の使用感などは下記の記事を参考にしてください.

この記事ではFluentd UIそのものについてつらつらと書きたいと思います.英語でのアナウンスもいずれ公式ブログに載るはず.

Fluentd UIの生い立ち

Fluentd UIの背景として,Fluentdも最近は国を問わず色々な所でユーザが増えてきており, 「CLIとか楽勝!」以外のユーザの割合も増えつつあります.

ログコレクタでリッチな管理UIを持っているプロダクトってほとんどないと思うのですが, 新しく使い始めるユーザの嵌まり所とか見ていると, GUIの方が始めるための敷居が下がりそうなポイントがいくつかありました.

なので,Fluentdを使いたい人がなるべく嵌まらずに始められるようにと, 万葉の方と開発したのがFluentd UIです.

Fluentd UIのコンセプト

生い立ちの所で書いた通り,Fluentdの敷居を下げるのが第一の目的なので, すでにFluentdをバリバリ使っている人はユーザの対象ではありません.

バージョン0.1.0の段階で,以下の機能があります:

  • Fluentdのプロセスの管理 (start/stop/restart)
  • Fluentdの設定ファイルの管理と編集
  • Fluentdのプラグインの管理 (install/uninstall/update)
  • ログやシステム情報のビューワー,などなど

最初に色々機能を洗い出したのですが,全部入れるとリリースが遅れるし, 複雑なのを入れるとユーザが混乱するかもということで,ベーシックな機能セットに絞りました.
それでも,プラグイン入れての挙動チェックなど,全部Webから出来るようになっています.また, ユーザがテストしにくかったin_tailは,Fluentularを参考にかなり使いやすいUIになったと思います.

実装的にもかなり依存を減らしていて,例えば,最初はSQLiteベースだったのですが, 「SQLiteだとFluentd UIそのもののセットアップに嵌まる人が出る可能性がある」とファイルベースに変更したりしました.

Fluentd UIの今後の展望

機能追加

バージョン0.1.0ということから分かる通り,まだまだ始まったばかりのプロダクトで, 今回は開発者側が「こういう機能があったら始めやすいだろう」というものを中心に入れました.
今後はユーザからのフィードバックも受けつつ,更に使いやすさを改善して行けたらなと.

現状各プラグインの設定を削除する時は,自分でフリーフォームから消す必要があるので, この辺もボタンで消せるようにとか,出来たらいいかなぁと考えてます.
あと,今設定が組み込みで実装してあるので(インストールした3rd partyプラグイン用の設定ページがない), 各プラグインから自動で設定ページが生成できるような仕組みも必要かなと,色々と模索中です.

td-agent 2への同梱

td-agentには同梱予定はないんですが,td-agent 2にはtd-agent-uiみたいな感じで同梱する予定です.すでに起動した人は知っていると思いますが,td-agentをセットアップする用のボタンがあります :)

他の環境との連携

Fluentd UIは,UI上で色々と試行錯誤しその結果出来た設定ファイルをChefとかで配布, みたいなのを想定しているのですが,毎回コピペとか面倒ですし, 最近だとfluentd-serverとかもあるので,この辺なんか上手くやりたいな,と.

まとめ

Fluentd UIについて背景含めつらつらと書きました.是非試して頂いて,問題があったらissue投げるなりPRなりしてもらえると助かります!

あ,ちなみに最初のリリースは俺がやりましたが,開発はコミットを見れば分かる通りuu59さんでちゃんとしたRailsコードになっているので,ご心配なく!

Fluentdとログ収集のパターン

| Comments

「ログを集めて保存する」と言うのは簡単だけど,ログ収集の構成にはいくつか方法があり,勉強会などでちょくちょく聞かれるので,いくつかのパターンについて書く.
「俺はもうバリバリログ収集やってるぜ!」という人は多分すでに知っていることが書かれているので,タブを閉じて良い.

ここではログコレクタにFluentdを想定しているが,他のログ収集プロダクトにも適用出来るはず. ただ,Fluentdはタグベースのルーティングを持ち,単体でもキューのように動作させることが可能で,既存のものより複雑な問題を解決しようとしているので,少し工夫が必要かもしれない.
Fluentdそのものについては公式ドキュメントや,Fluentdとはどのようなソフトウェアなのかを参考に.

クライアントから直接保存する

"Only client pattern"

いきなりFluentdを使わないパターン.JavaScript SDKを提供している解析サービスやモバイル端末などでよく使われている.ログがユーザサイドで発生する場合にはログコレクタを仕込むことは出来ないので,基本このアプローチになる.
これらはクライアントの出来によって精度が左右されるが,モバイルであれば繋がらなかったら一定量バッファリングをし,ネットワークが繋がった段階で非同期に転送などがよくある実装.

ログコレクタを用意出来るサーバサイドでこのアプローチを取っているシステムは最近だとあまり聞かない.もしやるならエラーハンドリングとして

  • バッファリング
  • リトライ
  • ロードバランシング

などの問題を解決する必要がある.Fluentdであればこれらの機能が最初からついているので,今から構築するシステムでやる必要はほとんど無いと思われる.

末端ノードのログコレクタから直接保存する

"Only leaf node pattern"

アプリケーションやノードからログを集め,ログコレクタから直接保存する.「クライアントから直接保存する」の例で,ローカルにログコレクタを置き,そこ経由でデータを投げつけるモデル.
ネットワーク周りのややこしい問題をログコレクタに任せられ,Fluentdであればプラグインで容易にストリームを操作できるのがメリット.また,ApacheやNginxから直接外部にデータを投げるのは難しいので,Fluentdでファイルにはき出されたログを収集するときにはこの構成となる.

この構成だと,収集対象のサーバが多くなるだけアクセスが増えて保存先への負荷があがるので

  • データのストリームがそれほど大きくない
  • 保存先が書き込みに対して耐性がある (クラウドサービスなど)

などの場合に有効になる.次で書く集約ノードが必要ないので,その分管理は楽になる.
Fluentdは転送役と集約役に違いはないので,この段階でフィルター系プラグインを使って,データを加工することもある.

Treasure Dataの場合には,Librato Metricsに投げる所などは集約ノードを経由せず,各Fluentd(Treasure Agent)から直接投げている.この場合は各ノードのメトリックスが取りたいので,集約ノードでデータストリームをまとめる必要もない.

これとは違いMongoDBの場合だと,細かいのをちまちま送るより大きめのバッチでガンと書き込んだ方が効率が良いので,このモデルよりも集約ノードを置いた方が良い.

集約ノードのログコレクタを経由して保存する

"Using aggregation node pattern"

ログコレクタでの多段構成モデル.集約ノードを置く利点は,データストリームをまとめてデータに対する処理をしやすくする点が大きい.また,各ノードから集めることでストリームが太くなり,マイクロバッチの効率も良くなる.

Fluentdでもアグリゲーションをしたり,Norikraと連携するプラグインがあったりするので,その手の処理はこの集約ノードでやるのがベター.

大抵のログコレクタと同じく,Fluentdのデフォルトの転送プロトコルはPush型になっていて,多段構成時には流れるように保存先にデータが集まるようになっている.
多段構成時の注意点は,ある場所のノードが落ちた時にストリームが途切れてしまう所.Fluentdの場合は障害に対応するために,転送先を複数指定可能で,その中で負荷分散とノードが落ちた時の処理を指定出来るようになっていて,よほど一気にノードが落ちない限りストリームが途切れることはない.もし落ちてもバッファリングが行われるので,ノードを再度立ち上げればデータはまた流れ出す.

PaaS上でのアプリケーション

アプリケーションをホストするような環境だとローカルにFluentdを置けなかったりするので(HerokuだとFluentdは起動できるが,ファイルバッファが使えなかったりする.ユースケース次第),その場合はいきなり集約ノードやキューにデータを投げることになる.

キューを置く

"Using queue pattern"

データストリームの中でキューを間に挟むことの主な理由は,ログのreliabilityの向上と,処理の間にワンクッション置くこと.

そもそもキューはPush型ではなくPull型であり,Producer・Queue・Consumerと登場人物も増えるので,キューを置くことでログ収集そのものが効率化されることはあまりない.異なる粒度のシステム間で連携をする時に,間にキューを置くことが多い.

実際Fluentdとキューを連携させている例はいくつかあり,たとえば複雑なシステムを構築しているVikiの例ではKestrelでFluentdからのデータストリームを分岐させているし,AWSは本家がfluent-plugin-kinesisを書いているので,いずれこの事例も増えるはず.

KafkaやKinesisなど信頼性のあるキューを間に置けば,ログをそれなりの期間保持しつつ,Consumerを複数用意することでストリームを分岐できる.
Push型での分岐とは違い,キューからログを取る側の都合でデータを処理出来るので,各データストリームで処理粒度が違う時に有効. ただ,キューそのものに信頼性があってもProducer/Consumerが駄目だと効率が良くならずログが欠損/重複するので,自分たちのシステム要件に合わせてちゃんと構築する必要がある.

Pull型のログ収集

キューを置かずにPull型でログを転送する方法もある.Kafkaほどの信頼性を期待するのは難しいが,Pull型の利点を享受できる.まだ完成していないが,Fluentdだとモリス=タゴという人が,pullforwardというのを開発中らしい.

Fluentdを使わない方が良いパターン

プロダクションで使われているパターンをいくつか書いた.大抵のシステムは上のどれかの構成に当てはまる.FluentdはWebや広告のみならずIoTやPOS含め色々なところで使われていて,データのアーカイブ,簡単なストリーム処理,ノードやアプリケーションのモニタリング,などなど様々なユースケースの基盤になれる柔軟性がある.

また,LINE社で2年間問題なく動いているし,最近勉強会とかで話を聞くと「安定していて自分の仕事がない」と言われる位,よほど変なことしない限り安定性もある.ある会社で100億events/dayをFluentdクラスタで転送した実績もあるので,パフォーマンスもそれなりにある(フィルタ的な処理を重ねまくると,もちろん遅くなる).

が,Fluentdを使わない方が良いケースもある.以下主に二つ.

Exactly Onceが必要なケース

一切ログの欠損も重複も許せない,しかも確実に書き込む必要がある,というケース.
ストリーム処理でExactly Onceを保証するのはかなり難しく,俺が知っている限りOSSでは存在していない.商用でもほとんど知らない.

Exactly Onceを実現しようとすると,ログ発生時点から書き込むまでを完全に同期的にやるか,様々な箇所でトランザクションが必要になり,スケールアウトが難しくコストもものすごく掛かる.そして保存先にもそれなりの機能が求められる.

かつてOSSでマスターノードを使い到達保証を目指したプロダクトがあったが,結局パフォーマンスがボトルネックになり,そこまでしてもログの欠損が防げなかったため,新しいバージョンでは諦めることになった.

Fluentdのモデル

FluentdはデフォルトAt Most Onceであり,ドキュメントにもモデルの説明と対策が書いてある
これはログが欠損/重複しまくるということではなく,At Most OnceもAt Least Onceも通常は問題は起きない.トポロジーに問題がある場合に,システム的に欠損/重複が起きうるという話.そして大抵のユーザはExactly Onceでなくても上手く行く.

Fluentdでも欠損/重複を防ぐための対策はいくつかあり

  • ログにユニークIDを足して,HadoopなどのETLで重複を削除する
  • 直近の生ログは保持しておき,保存先とのレコード数を比較する.おかしい所は再送
  • データストリームを複数作って冗長性を持たせる

などなど.システム的にExactly Onceではなくても,それに低コストで近づけることは可能.

追記(2014/11/14)

v0.12からはAt Least Onceもサポートする.現在リリースされているv0.12.pre2から使えるが,v0.12の正式リリース後,ドキュメントにもちゃんと書く.

データストリームが一本で密結合したサービスがある

たとえばAWSのCloudWatch Logsがそう.Agentのセットアップが必要だったりして楽かと言われるとまだ微妙だが,今後最初からインストールされる可能性もある.
そのような状況で,Agentから取れるログをCloudWatch Logsで直接見るので十分であれば,Fluentdを入れるメリットは少ない(CloudWatch Logs用のプラグインがあるので,Fluentdから利用することは可能).

Fluentdの利点は簡単にロバストで柔軟性のあるログ収集基盤が作れて,一度構築してしまえば,環境非依存でそのログ収集基盤を再利用出来るところなので,そのような必要性がないのであれば,環境と密結合したサービスを使う方が運用コストそのものは直近は削減できるはず.

まとめ

Fluentdが向いているケースと向いてないケース,そのPros/Consみたいなのを書いた.細かく書けばもっと色々と書けるのだけど,記事でそんなに長々と書いても疲れるだけなので大まかに. 何か質問があればTwitterで@repeatedlyにmentionするなり,この記事にコメントするなりしてください :)

もうすぐFluentd + Elasticsearch + Kibanaという有名な構成のムック本が出るようなので,この本とか読むと,解析のノウハウ含め色々とここには書いていない情報が手に入るのではないかと思います.

MPP on Hadoop, Redshift, BigQuery

| Comments

Twitterで「早く今流行のMPPの大まかな使い方の違い書けよ!」というプレッシャーが半端ないのでてきとうに書きます.この記事は俺の経験と勉強会などでユーザから聞いた話をもとに書いているので,すべてが俺の経験ではありません(特にBigQuery).各社のSAの人とかに聞けば,もっと良いアプローチとか詳細を教えてくれるかもしれません.
オンプレミスの商用MPPは使ったことないのでノーコメントです.

MPP on HadoopでPrestoがメインなのは今一番使っているからで,Impalaなど他のMPP on Hadoop的なものも似たような感じかなと思っています. もちろん実装の違いなどがあるので,その辺は適宜自分で補間してください.

前提

アプリケーションを開発していて,そのための解析基盤を一から作る.

簡単なまとめ

  • データを貯める所が作れるのであれば,そこに直接クエリを投げられるPrestoなどのMPPクエリエンジンを立てるのが楽
    • 特にHadoopとかすでにある場合には,まずこれ
  • データマートが必要であれば,RedshiftやBigQueryの方が向いている
  • ストレージもスキーマも運用も何も考えずにやりたいのであれば,BigQueryにFluentdとかでとりあえずJSONでぶち込むのが,多分この候補の中では一番初期コストが掛からない
    • もちろん要求によるので気をつける
  • Presto + Redshiftというケースも有り(アドホックなクエリはPresto,BIからガリガリつなぐのにRedshiftなど)

以下つらつらとリスト形式で書いてます.

Presto/Impala/Drill

PrestoやImpalaやApache Drillは,Redshift/BigQueryと違ってMPPデータベースではなくてMPPクエリエンジンなので,そこに違いがある. Prestoそのものについては,@frsyuki がHCJ 2014で発表したスライドがあるので,そっちも参考に.

  • PrestoやImpalaはそもそもサービスじゃないので,自分ですべて運用する必要がある.
    • 死活監視とか,もう少しワーカーが欲しかったら追加でデプロイみたいなのをする人が必要
  • 外部にストレージが必要
    • すでにある場合には,RedshiftやBigQueryじゃなくて,まずこれで十分かどうか試すという流れになりつつある
    • PrestoならS3とかにもクエリが投げられるので,FluentdでS3にJSONで貯めて,とかで構築コストはかなり軽減出来る
  • ストレージ側にスキーマを要求せず,直接クエリが投げられる
  • MapReduceとかとデータソースを共有出来る
    • データ量が増えてくると,ストレージからMPPデータベースにimportするだけでコストになるので,アドホックにクエリが投げにくくなる
    • PrestoやApache Drillは一つのクエリで複数のデータソースにアクセス出来るので.マスターテーブルとのjoinとかが楽に出来る
  • 速さに関しては,やはりスキーマありでチューニングされたMPPにはまだ基本勝てない.状況によっては勝てる時もある
    • それでも数秒 - 数十秒で返ってきたりするので,どこまでパフォーマンスを求めるかによる
  • クエリ同時実行制御に関しては,まだ商用のものに迫っているのはない印象
    • ここの改善に取り組んでいる人たちがいるので,いずれデータマート的にも使えるようになる可能性は高い
  • オープンソースなので,問題があったら自分で修正可能,処理傾向も把握しやすい

Redshift

  • スキーマが必須なので,アドホックに解析するためのデータベースとしては少し不向き
    • やるならデータをJSON文字列で保存,クエリ時に分解する.効率は落ちる
  • MPPデータベース(ParAccel)がAWSカスタマイズされて載っているので,その辺の知識がないと嵌まりやすい
  • マネージドサービスとはいえ,リーダーノードの挙動がおかしい時など,面倒を見ないと行けないケースはある
  • カラムを弄る場合は基本テーブルを作り直すのがベター.クラスタ再配置中はREAD ONLYになるので,その辺含めて運用を考える必要がある
    • 数時間READ ONLYの場合,貯めようとしていたログはどうするか,など
    • 今時はMPPデータベース単体で運用している所は少ない.RedshiftでもEMRなどからデータを整形して一気にガツンと入れるのが多い
  • クエリの同時実行制御周りはそれなりに頑張っている
  • ストレージと演算パワーが分離してないので,ユースケースによってはコストが割に合わない

BigQuery

  • Redshiftと同じく,アドホックに色々とデータをぶち込んで解析するには,JSON文字列(record型?)で保存する必要がある
  • 既存のMPPデータベースとかで考えないと行けない問題(distkeyとか)を,Googleパワーで強引に解決
  • 運用は完全Google任せ
    • Redshiftと違いGoogleの環境を共有するので,細かなことは出来ない
  • Googleの制約を受ける
    • 負荷が極端に上がるようなクエリとかは望み薄(FULL OUTER JOIN, 数億同士のjoin,count(distinct))
    • Redshift同様,でかいバッチ向けにHDFSとかオブジェクトストレージに生のデータを置いておくのがベター
  • BigQueryもスキーマがあり,alter column的なものがないので,変更する時は適宜テーブルを作り直すのがベター
  • Redshiftと違いクエリ単位の課金なので,どれだけ掛かるか把握するのが難しい
    • 小さい会社だとかなりマネージしやすい(この辺の話).大きい会社や,マーケや営業の人がガンガン使う場合には,かなりバーストする可能性がある.Reservedがあるが,月200万からなので,判断が難しい
  • Streaming Importが結構パフォーマンスが出るので,importして即クエリがやりやすい(参考記事)
    • リミットがあるので,大量に入れる時には気をつける.2015年から有料.
  • 同時実行制御周りは基本よく動く
    • リソースはGoogle側が管理しているので,バッチ投げたら詰まるとかは起きにくい
    • リソースを占有しているわけではないので,勝手にクエリが死んだり,いきなり遅くなったりすることもある
      • 日本時間の21時当たりで起きやすいらしい.でかいバッチを投げまくっているユーザが海外にいる?

まとめ

基本的にこれらの裏にはHadoopなどの基盤が前提になりつつある(オブジェクトストレージ + 演算リソースでも可).上のリストを眺めれば,なんとなく使い分けが分かるんじゃないでしょうか! MPPと一纏めにするにはユースケースや得意なものが違うので,ちゃんと使い分けましょう.基本的にどれもBIツールと接続する方法があり,苦労はそんなにしないはず.

各プロダクトは常に改善されているので,ここに書いてある制約などは,いずれ緩和される可能性があります.常に最新情報をチェックしましょう.

今回はMPPクエリエンジンプロダクトの話なので上のリストでは省きましたが,Treasure Dataが提供しているTQAというMPPサービスは「Prestoで運用とかストレージを考えなくていい版」に近い感じになります.TDはさまざまな外部ストレージと連携出来るので,Treasure Dataを中心に使い分ける感じになります
最後に宣伝!

P.S

Twitterに流したさらに要約したtweet.