読者です 読者をやめる 読者になる 読者になる

サナギわさわさ.json

サナギさんとキルミーベイベーとプログラミングが好きです

Apache Sparkについてのメモ

大規模バッチ処理が必要になったので、名前だけ聞いた事はあっても詳細を知らなかったApache Sparkについて簡単に調べました。

参考サイト

http://spark.apache.org/talks/overview.pdf

Apache Sparkってどんなものか見てみる(その1 - 夢とガラクタの集積場

Resilient Distributed Datasetsに関する論文まとめ(1章〜5章 - 夢とガラクタの集積場

spark_rdd.md · GitHub

Apache Spark

  • インメモリな分散データ処理プラットフォーム
  • データをメモリに保持するため、ストレージから入力を受けストレージに出力するMapReduceと比較して、機械学習やグラフ描画などの同じデータを繰り返し用いるジョブに対して強い
    • 初回ロード時は重くなるが、それ以降はメモリ上から読み込むためHadoopより速度が上がる。機械学習などのイテレーション複数回走る処理ではかなり差が出る。
    • 必要なメモリ量はHadoopよりも多くなる
  • Resilient Distributed Datasets(RDDs)を採用する事で、Hadoopの耐障害性、データ局所性、スケーラビリティを保持しつつメモリ上へのデータ保持を行っている。

Resilient Distributed Datasets(RDDs)

概要
  • 耐障害性を確保した上でメモリ上での計算を可能にするための読み取り専用分散データセット
  • 効率的な耐障害性の確保のために、「荒い変換のみ可能」な制限されたデータセットとして提供されている。(例:map, filter, join)
  • RDDsに対して荒い変換を行うと、RDDs内に存在する全てのデータに対して同じ演算が発生する (一斉書き込みのみをサポート)
  • 実データそのものを記録するのではなく、「データに対して行った変換」を記録する事で、効率的な耐障害性を実現している

プログラミングインタフェース概要

  • RDDsの概念を実装したインタフェースはScalaで提供される
  • RDDsはまず静的ストレージに対するtransformation(map,filterなど)で生成される
  • 生成されたRDDsに対して値を返すアクションやデータ出力のアクションを実行可能
  • 生成したRDDsをその後の処理で再利用したい場合は、persistメソッドを呼び出す事で対象のRDDsをメモリ上に保持できる
    • メモリ上に収まらない場合はディスクも併用
    • persistメソッドを呼ぶ際に、ディスクのみに保存するか、マシン間レプリケーションを行うかの配置選択も可能

RDDsの主な利点(vs分散共有メモリシステム)

  • 一括書き込みのみを認めているため、より効果的な耐障害性が提供される
    • データロストの場合でも、データ変換記録をたどって復旧が可能なためチェックポイントのオーバーヘッドが発生しない
    • パーティションがロストした場合でもプログラム全体のロールバックが必要なく、異なるノードでの並列計算で復旧できる
  • データが読み取り専用であるため、遅いタスクのコピーを実行する事で実行時のパフォーマンス向上が可能 (分散共有メモリシステムでは、2箇所から更新が来た場合競合が発生するためタスクのコピーが不可能)
  • メモリが不十分になった際に、スキャンをメモリ上で優先実行しそれ以外をディスクに移行する事でパフォーマンス低下を極力防げる

RDDsが適するケース

  • データ全体に対して一括操作を実行する場合に適している
  • 状態を管理しながら短いスパンで同期して処理を進めていく必要があるケースには適していない

RDDsの表現方法

上述した通り、RDDsは必ずしも実データそのものを保持しておらず、「データに対して行った変換」を保持する抽象的なモデルである。
RDDsではグラフベースのRDD表現によって様々なtransformationを追跡可能にしている。RDDに付与される5つの情報を以下に示す。

ここで重要なのがRDD間の依存関係をどのように表現するかということだが、依存を以下の2つに分類することでシンプルに依存が表現可能になっている。

  • 狭い依存:親RDDが子RDDに最大1つまでしか参照されない
  • 広い依存:親RDD複数の子RDDに参照される

この依存定義は以下の2つの理由で便利である。

  • 狭い依存ではクラスタノードを全て親のパーティションで実行可能であり、すなわちパイプラインを実行可能という事を意味する。(広い依存では全子ノードの親RDDが使用可能である必要が有る)
  • ノード障害時に、狭い依存の場合はロストしたパーティションのみを再計算すれば良い。広い依存の場合はノード間を含めた完全再計算が求められるケースがある。

Spark Streaming

  • Sparkはあくまでバッチ処理フレームワーク
  • しかしデータを超細切れなバッチの系列として処理する事で、ストリームコンピューティングを実現する事ができる。これがSpark Streamingである。
  • これによって、従来はバッチ処理とストリーム処理を別々に実装し運用しなければならなかったのが、同じ基盤上で走らせる事ができるようになる。(らしい)
  • だが、本質的にはやはりストリーム処理とバッチ処理は異なり、StormとSpark Streamingの違いもそこにあるらしい。その辺は今度まとめる

以上。