夢とガラクタの集積場

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

Apache Spark Streamingの論文を読んでみます(1章

こんにちは。

ここ何回かでApache Spark自体の機構は大体わかりました。
そのため、今度はApache Sparkを基にしたストリーム処理基盤であるApache Spark Streamingについても確認してみます。

読んだ論文は以下です。
「Discretized Streams: A Fault-Tolerant Model for Scalable Stream Processing」
http://www.eecs.berkeley.edu/Pubs/TechRpts/2012/EECS-2012-259.pdf

こちらも内容が理解できればいいので、全文訳というわけではありません。
また、読むのも新規情報が主に出てくる実装方式までです。
評価については以前確認した資料とほとんど変わりませんでしたので。

では、入ります。

概要

多数のビッグデータアプリケーションがデータを受信したタイミングでリアルタイムに処理することを求め始めている。
しかしながら、現状の分散ストリーム処理のプログラミングモデルは比較的低レベルであり、
状態の一貫性やシステム障害への対応をユーザが個別に気にしなければならない状況が発生している。
更に、障害回復を行う際には動作中の随時レプリケーションや長時間の復旧時間などコストがかかる状況になっている。

そのため、私たちは離散ストリーム(D-Streams)という新しいプログラミングモデルを提案する。
これは高レベルの機能API、強一貫性、効果的な障害復旧を提供するものである。
D-Streamsは新たな復旧メカニズムをサポートする。
これは伝統的なレプリケーションやストリームデータベースにおける上流バックアップ手法をより効率的にしたもので、
”ロストした状態の並行復旧”が可能。
加えて、以前のシステムとは異なり、システムの中の「ボトルネック(落後者?)」の影響も軽減可能。

私たちはD-StreamsをSparkというクラスタコンピューティング基盤を拡張して実現し、
ストリーム処理とバッチ処理インタラクティブなクエリ実行をシームレスに実行可能にした。
このシステムにおいて、100ノードのクラスタでは6000万レコード/秒のペースで数秒単位の遅延での処理を可能とする。

1. イントロダクション

ビッグデータはリアルタイムに到達しつつあり、受信したタイミングで処理し続けることの価値が高まっている。
例えば、SNSで話されたはやりのトピックを素早く検知する、ニュースサイトに訪れたユーザの動線を把握する、
プログラムログから数秒の間にエラーを検知する・・など。

これだけの大量データを扱うアプリケーションを処理するためにはクラスタ上で並列処理をする必要がある。
しかしながら、これまで開発されてきたクラスタ上で並列処理をするためのプロダクト・・・
MapReduceやDryadは分散することや耐障害性についてはうまくハンドリングできるが、ストリーム処理としては適さない。
これまで開発されてきたストリーム処理のプロダクト・・・Twitter Storm、Yahoo S4やストリームデータベースは
「その場で処理する」モデルを確立しており、状態を保持したオペレータが流れてくるイベントを処理し続け、出力する。

このモデルより、大規模クラスタ上でのいくつかの技術的挑戦が提示される。

  • 障害と遅いノードへの対応

その場で処理するシステムは耐障害性をレプリケーションで実現する。
その場合実際に処理するオペレータのコピーを保持し、あるノードで障害が発生した場合、
オペレータのコピーに対してメッセージを再送する形になる。

だが、このアプローチは大規模クラスタでは有効ではない。
レプリケーションを使うことによって常時2倍近いマシンを消費する形になってしまうし、
マスタとレプリケーションで両方障害が発生した場合は上流から処理をやり直す必要が出てきて、
全体のシステムが障害から復旧するまでの時間停止してしまう。

また、私たちは処理が遅いノードをどう扱うかについても議論中である。

  • 一貫性

いくつかの「その場で処理する」システムにおいては異なるノードが
非同期にデータを処理し続けているため、「グローバル状態」を確保するのが困難である。
例えば、ページビュー数を男性ユーザの値をあるノードが、女性ユーザの値を違うノードがカウントし続けていたとする。
その際、処理中のあるタイミングで男性ユーザと女性ユーザのアクセス割合を算出した場合、誤っている可能性が出てくる。

ストリーム処理を行うシステムは常時動作&イベント駆動となる関係上、
ユーザのオペレーションで開始するバッチ処理システムとはモデルが異なってくる。
そのため、同じ解析をする際にユーザはストリーム処理用、バッチ用と2つの解析タスクを作成する必要が出てくる。

加えて、ストリームデータと過去データの結合は困難となる。
例えば、ストリームイベント処理と過去データのjoinを考えた場合、
どうハンドリングすればいいかは困難であることがわかるはず。

これらの挑戦が重要であるからこそ、
既に一部の要素を解決しているクラスタコンピューティングシステムの確認を行った。

バッチ処理システム:
MapReduceやDryad。これらのシステムは各アプリケーションをグラフ中の細かい、決定論的なタスクに分解している。
こういう形で細かく分割することによって、部分的な再実行や遅いノードに対する投機的実行といった
効果的な障害復旧メカニズムを実現している。

一貫性の観点においては、これらのシステムは「少なくとも1回実行する」というセマンティクスの上で動作する。
そのため、障害が発生しても発生しなくても同一の出力が得られるようになっている。

結果、これらのシステムは高いスケーラビリティを確保し、
常時何千ものノードで処理を実行することが可能となっている。

この確認結果に基づいて、私たちはストリーミング処理システムが
より効果的にスケールする重要かつ決定的な設計ポイントを提案する。

それは、「ストリーミング処理を決定論的なバッチ処理を短い間隔で実行することの連続として扱う」ことである。
尚、私たちはその「短い間隔」を0.5秒未満、その上でエンドツーエンドの処理時間を1秒未満に抑えることを目標としている。

この方式は実世界の「ビッグデータ」アプリケーションの多くに適合し、追跡するイベントの時間精度も上がると考えている。
私たちはこのモデルを「離散ストリーム」、またはD-Streamsと呼ぶ。

残念ながら、現状のバッチ処理基盤で秒単位のレイテンシを達成することは難しい。
小規模なジョブを実行する場合でも、大抵分単位のレイテンシが発生してしまう。
こうなってしまう理由はジョブは結果をレプリケーションされたディスクストレージシステムに書き込むためで、
ディスクIOとネットワーク上のレプリケーションによって多くの時間が使用されている。

今回秒単位のレイテンシで処理を可能としたキーポイントはRDDsを活用することである。
RDDsは以前提案したメモリ上の共有状態のことで、ディスクに出力することなく耐障害性を実現している。
RDDはディスクにデータそのものを出力する代わりにオペレーションの系統グラフを保持することにより、
ロストした個所を再演算可能とすることで耐障害性を確保している。

RDDはD-Streamsに理想的に適合し、各コンピューティング処理を50〜200msのオーダーで実行可能となっている。
私たちはRDDsを用いて典型的なストリーム処理をどう実現するかを示す。
その中には状態をもった処理やインクリメンタルなスライディングウィンドウを含むものもあり、
それが数秒単位のレイテンシで実行し続けることができている。

尚、D-StreamsはRDDという更新が制限された状態を介するため、効果的な障害復旧も可能となっている。
既存のこれらのシステムにおいてはレプリケーション
上流データのバックアップによって障害復旧を行っていた。

だが、バッチ処理モデルにおけるD-Streamsは障害発生時は
障害が発ししたノードの保持していた情報のみを並列に再計算することで復旧が可能となっている。
これはレプリケーションやバックアップと比して非常にコストが少ない。

この並列な状態復旧は「レコードをその場で処理する」システムにおいては通常
複雑な状態を保持していたり、レプリケーションを行っているストリーム処理においては困難。
だが、バッチジョブの状態を復旧することはそう難しいことではない。
そのため、D-Streamはシンプルな復旧が可能となる。

また、「遅いノード」についても同様の方式でシンプルな投機的実行が可能。
「遅いノード」問題はクラスタコンピューティングにおいてはしばしば発生する事象のため、非常に有効。
既存のストリーム処理プロダクトはこの「遅い」問題に対応するのが困難である。

私たちはD-StreamsをSpark Streaming(Sparkの拡張コンポーネント)として実装した。
このシステムは6000万レコード/秒の処理を100ノード上で実行することで秒単位のレイテンシで処理が可能となっており、
障害や「遅いノード」の問題に対する復旧も1秒未満で可能となっている。

これは現状広く使用されているOSSのストリーム処理プロダクト(Storm)の5倍のスループットを誇る。
(障害復旧、イベントの抜け検知等は同等に行った上で)
尚、パフォーマンスの章においてはSpark Streamingを使用して
「ビデオ配信モニタリングシステム」「オンライン機械学習」を実施した結果を示している。

D-Streamsを用いるより重要な理由として、処理モデルやデータモデル(RDD)が
バッチ処理と同じものを用いてストリーム処理を実施することができるというものがある。
Spark Streamingは内部的にはSparkのバッチ処理インタラクティブクエリ処理とシームレスになっている。

これは実際に非常に有用な特徴で、この特徴を持つためにSpark Streamingはストリームに対して
アドホックなクエリを実行したりストリームを過去データと結合することが同一API上で可能となっている。

このようなバッチ処理とストリーム処理の境界を曖昧にして共通的に実行する方法についても記述する。
====
というのが概要です。
このあたりは以前のスライドでも書いてあった内容ですね。

ちなみに、Stormにおいてもグルーピング無し+localOrShuffleGroupingを用いると性能が数倍に跳ね上がります。
なので性能が5倍云々は微妙そうです。

ただ、「イベントの抜け検知」をStormがイベント単位で行っているのに対して
Spark StreamingはRDDパーティション単位で行っています。
なのでそのあたりの効率はSpark Streamingの方がいいですね。

但し、Spark Streamingがデータ局所性を用いて単純化&性能向上を図っているのに対し、
Stormは処理する際に何かしらのキーでGroupingをかけたとしてもそこまで性能のロスは発生しません。
そのため、結局のところアプリケーションの性質によってどちらがより効果を発揮するかは決まってきそう・・・
というありきたりな結論になりそうではあります。

では、次回以降も続けます。
この論文についてはさっさか終らせて、Apache MesosとSparkの構築に入りたいところですね。