今熱い視線を向けつつもそれだけで終わってしまっている Apache Spark の勉強会があるということで Hadoopソースコードリーディング 第16回 Tickets, Thu, May 29, 2014 at 7:00 PM | Eventbrite に参加してきました。Hadoop じゃなかった気もするけど奇しくも初の Hadoop ソースコードリーディング参加で非常に濃密な時間を過ごすことができました。
スライドもかなり濃密で前の方に早く来て座ってて良かったーと思ってたんですが素晴らしいことに全部 Slideshare で公開されました。何度も反芻しないと理解しきれない感じしていたので大変ありがたいです。
ということでやや勘違いしているところもありそうですがメモを残しておきます。
Apache Spark のご紹介 前半 (土橋昌さん / NTT データ)
- 最近 Puppet から Ansible に移った (ちなみに近くAnsible 勉強会が日本で開かれる)
- 基本、机上調査 + ソースコード調査 (7 月くらいにもっとまとめてどこかで話す予定)
- Spark では Java や Scala のコレクション操作のような使い方で分散処理を実現できる
- Hadoop 上の処理である程度小さくなったデータでも Dataware house に転送するコストは無視できない
- Hadoop を業務処理に使ってジョブが 200段くらいになってしまっているところもある
- MR と Spark の組み合わせのベストプラクティスはまだない
- Spark を使わない方が良いのはクラスタ全体のメモリに乗り切らない巨大なデータ処理(TB 以上)
- Spark Summit 2013 で Databricks CEO は『Spark の上で全部やれるようになることを目指している、Hadoop とは共存する』というメッセージを発していた
- Yahoo 台湾などで本格的に導入されている
- Databricks の中の人曰く Spark 単体で動かしている人たちが多いらしい
- デバッグに関して知識がいる。遅延処理スケジューリングなど癖がある。
- Mahout のブログでは Hadoop から Spark への移行を推す?ようなエントリーもあった*1
Apache Spark のご紹介 後半 (猿田浩輔さん / NTT データ)
- Hadoop 徹底入門 や Hadoop HACKS の執筆者
- Spark はユーザーが定義したRDD の系譜(Lineage)に従って処理を実施する
- コレクションのようなデータ構造で内部要素をイテレートできる
- パーティションに分割され、サーバー上インメモリで分散配置される
- 遅延計算される(系さを行うタイミングをスケジューリングされた後に実際に計算される)
- 単純な変換関数 : 計算がスケジューリングされない
- アクション : 計算がスケジューリングされる
- RDD はイミュータブル(フォールトトレラント性を担保するため)
- 各サーバに分散は位置されたデータ(パーティション)が処理中に欠損した場合に備える
- しかしネットワーク転送は避けたい。Hadoop などではレプリカを作るがそれだとデータ転送が発生する
- 取得したいデータが失われていたら前のデータから再生成する
- そのために RDD はイミュータブルにする必要がある
- 出発点の元データは高可用性、堅牢、イミュータブルでなければならない
- RDD の変換において、変換元の親と変換後の子には依存関係が定義される
- 依存関係はスケジューリング (RDD の変換チェインを処理可能なタスクに分割する)に関係する
- 狭い依存関係 (filter 関数など。子パーティションの生成に単一の親しか関わっていない)
- 広い依存関係 (groupByKey 関数のようにキーに基づくグルーピングを行うと親パーティションが複数の子パーティションの生成に関わる)
- 広い依存関係が発生する処理を実行するとエグゼキュータ間で通信が発生する
- 系譜をもとにタスクを生成したりエグゼキュータへの割当をコントロールするのはスケジューラの役割
- DAGScheduler が系譜をステージに分割する。
- ステージは系譜中で狭い依存関係が連続して発生する範囲
- RDD の系譜を逆にたどって行って狭い依存関係のときは同ステージとして判断する。
- その後ステージ間の親子関係を定義する
- エグゼキュータ一つがまとめて計算できる変換の範囲を決めるため
- 広い依存関係のときは RDD を配布しなければいけないため通信先を決定しておく必要がある
- Spark コンテクストというオブジェクトの中に複数のジョブを定義できる
- 子の RDD がキャッシュされている場合は親ステージでの実行処理自体する必要がない
- プリファードロケーションが RDD にセットされている場合はそれをヒントにエグゼキュータを選ぶ
- ない場合は親をたどって最初に見つかったものを使う
- プリファードロケーションは RDD の種類ごとに定義される
- FIFO と FAIR の二つのスケジューリング方式がある
Spark Internals (Taro L. Saito (@taroleo) さん / Treasure Data)
- snappy-java 開発者
- 20,000 行 -> 50,000 行になったもののコアな仕組みはあまり変わっていない
- Shark が SparkSQL に変わった
- 怖くない Scala
- Scala のコードは密度が高い。Java の 10倍?
- Scala を扱う IDE は IntelliJ x Scala Plugin 一択
- Scala console 便利
- Scala 基礎
- シングルトンの定義が簡単
- クラス(名)で case 文を書いて条件分岐できる
- Scala Cookbook で Scala の勉強しよう
- Spark の処理は SparkContext がエントリーポイント
- @transient はシリアライズしないというアノテーション
- NSDI 2012: Resilient Distributed Datasets から盛り上がった
- Iterator はまずキャッシュに実行結果があるかチェックする。
- StorageLevel
- useDisk, useMemory, useOffHeap, deserialized, replication などポリシーを設定できる
- チェックポイントでディスクに退避するなどある (persistentRdds ?)
- コンフィグでどれだけメモリーを使っていいか決められる様子
- データがあるところに処理を送るから速い
- TaskLocality
- DelayScheduling : Local -> RackLocal-> どのノードでも というようにポリシーを変えている
- ASM4 というライブラリを使ってバイトコードの中をトラバースし、フィールドでどれを使っているかを列挙して使っていなければ null を入れて送っている。
- ただし関数呼び出しの先まで辿っているわけではないので不完全。
- javap -v を使うとバイトコードでどんなアクセスがあるかわかる
- SparkEnv に Spark で使われているコンポーネントが羅列されている
- Mesos Scheduler
- Fine Grained は毎回 JVM を各タスク実行時に立ち上げるので重い
- Coarse Grained は Spark のクライアントを立ち上げっぱなしにするのでリソースをロックしてしまう
- Google の Omega Scheduler はその辺をうまくやってくれる
- Mesos との連携はあまりうまく言っていないので YARN に期待
- RDD が GC されたときにキャッシュを削除するように全台に送る (ContextCleaner)
- Spark は Java に近い書き方をしているので読みやすい
- DSL にしてしまうとよくわからなくなる
- Akka になって RPC 周りがわかりやすくなった
- Spark では再帰探索やパターンマッチングも Scala らしさを活かしている
その他、
- Spark 開発元の Databricks さんはメジャーリリース 1.0 今週か来週出るよと先週言っていた。
- Hadoop Conference Japan 2014 は 7/8(火) !
などなど。
ちょっと自分でもコード読まないと駄目だなということで復習かねて読んでみようと思います。コードリーディングの勉強会初めて参加しましたがえらくタメになりました。今後も継続して参加したいです。
*1:未確認です