はじめに
EMR(Elastic MapReduce)はマネージド型のHadoopフレームワークを提供してくれるサービスです。
EMRを利用している事例は多々あれど、分析業務での活用が主流です。
本記事ではそんなEMRをエンタープライズで、しかもゴリゴリ基幹業務に導入した際に考えたことを徒然まとめてみました。
そもそもHadoopを基幹業務で利用している事例が世界規模で少なく、いわんやEMRの場合はもう皆無です。
なので、これから導入を検討している方々の少しでも参考になれば嬉しいです。
それEMRで!!
基幹業務でも短時間で大規模な業務利用データをたくさんつくらなきゃねーってことがありますよね。
でも処理するデータ量によってはRDBがんばれな構成だと結構厳しい。
そこで分散処理による高スループットなアーキテクチャが必要だったという背景からEMR使ってみるかーと思った次第です。
Redshiftというのがあってだな・・・
いまや分散DBの代表格ですね。ポスグレと同様の文法もサポートしているし、開発もしやすくとても魅力的です。
ただ以下の理由からEMRも魅力的だなーと思っています。
- バッチ処理の時だけ起動して使いたい
- バッチ処理時間の時だけ使えればよかったので、その用途からするとEMRの方がぽいのかなと。
- クラスタ構成を柔軟に変えらえるようにしたい
- こっちの方がEMRを選んだ一番の理由です。処理するデータ量の増減に応じて柔軟にクラスタ構成を変えられると幸せ。
- Redshiftだとそもそも選べるインスタンスタイプが少ないし、台数並べようと思うとお値段が…orz
- EMRなら実態は選べるインスタンスタイプも豊富、EC2なのでそこそこ台数並べても一気に値段が跳ね上がるようなことがない!
もっといろいろ比較検討はしてみたのですが、あとはざっと以下のような理由でEMRを選んでます。
- RedshiftはSQLで処理できるから開発生産性も高そう!でも最近SQL on Hadoopって流行ってるしEMRでもSQL使えるしいっか
- EMRはEC2が起動するから、いざ何か特殊なことやりたいってなった時も直接EC2を操作できるっていう手段もとれるしなー
- Hadoopエコシステムって豊富だし、結構枯れてるし、他システムとの連携をサポートしたツールも豊富だし幸せになれそう
こんな感じにデザインしてみた
以下のステップでバッチ処理を実行するようにしています。
- 加工元のデータをRDSからEMRへSqoopを使ってインポート、あわせてそのままのテーブル構造でHiveのテーブルも作っちゃう
- HiveQLでガシガシ加工
- 加工後のデータを再度RDSへSqoopでエクスポート
- あとはアプリケーションがそのデータをRDSから利用
採用プロダクトと役割は以下のような形です。
ちなみにHiveのメタストアはRDSに外出ししていません。あと現状はEMRFSも利用しませんでした。これらの理油は後ほど。
採用プロダクト | 用 途 |
---|---|
EMR | 分散処理を行うための基盤 |
RDS | 加工元データと加工後データの格納先 業務データを利用するアプリケーションはこのRDSから加工後データを利用 |
Hive | EMR上でのデータ加工 |
Sqoop | EMRとRDS間のデータ移送 |
設計にあたってすごく考えたこと
いざEMRを導入して設計するぞとなると、やっぱり特有の癖があるわけです。
Hadoopの特性もあるのですが、設計にあたっては以下のようなコンセプトを置きました。
- 壊れることを前提とした設計
- マネージドの恩恵をうける
以降で一つずつ説明していきます。
壊れることを前提とした設計
エンタープライズだとオンプレミスでのサーバ運用というのもまだまだ主流です。
私自身も長くオンプレ環境のエンジニアだったこともあり、壊れることを前提とした設計や運用というとどこか後ろめたさがあります笑
ただ、技術検証をしているとEMRのコアノードがしれっとお亡くなりになっていることもちょいちょいあったのと、
SAの方も業務上重要なデータをEMR上で永続化しておくのはおすすめできないという話も伺ったので、以下のような考え方で設計してみました。
あくまでEMRは処理エンジン
EMR上にはクリティカルな業務データは持たせず、RDSでデータは永続化させてマルチAZで可用性も担保することにしました。
なのでパフォーマンス重視で処理はインスタンスストレージで実施し、今のところEMRFSでS3を利用することはしていないです。
また、Hiveではプライマリーキーがそもそも存在しないので、RDS側で重複がないかといったデータの整合性を担保させてます。そうすることで、EMRへデータを取り込んだあとは一意制約違反が起きていないかなどを気にせず処理に集中できるようにしています
万が一、HiveQL内で誤った処理をしてしまい、重複データなどの不正データが作成されてしまったとしても、RDSへエクスポートする際に一意制約違反などが発生するので、そこで誤ったデータ挿入されることはある防げるだろうという意図もあります。
あとは、EMRには分散しやすい得意な処理に集中させたかったので、複雑なロジックが必要となる処理はRDS上で前処理として実施します。
処理のリランを割り切る
処理のリランも結構割り切って考えるとすっきりします。
万が一アプリケーションエラーで処理が途中で失敗してしまっても、途中からリランということはせず、そのテーブル加工の処理は頭からやり直す方針にしています。
Hiveで加工処理を行うのですが、業務SQLによくあるような一本の長い&複雑なSQLではなく、複数のワークを経由して最後にがっちゃんこさせることで処理の並列度をあげられるようなアプリ方針にしています。
そのため、処理の途中からリランをする場合、こうした中間ワークテーブルのデータや状態を管理する必要があり結構しんどくなってしまうのですが、割り切ってそのデータ作成ジョブを頭から流しなおすという方針にすることでリラン運用もシンプルに保つようにしています。
また、処理を分散してあとはマシンパワーで乗り切るアーキテクチャをなのだから、こまごまと状態管理して細かい粒度で処理を実行するよりも、リソースも有効に活用できて処理時間も大きな差が出ないだろうという考えもあります。
あくまで運用性を重視しています。
クラスタ障害でインスタンスストレージ上のデータが消えてしまった場合も、ソースデータはRDS上で永続化させているので、またそれをインポートすればよいと割り切ってます。(Sqoopによるインポートであればさほど時間もかからない)
このようにDROP&CREATEを基本としているため、HiveのメタストアをRDS上に配置して、メタデータだけ手厚く耐障害性を考慮してもメリットが薄く、むしろ運用対象のシステムが増える方が嫌だなーと思い、メタストアはEMRのマスタノード上に配置することにしています。
運用監視も割り切る
エンタープライズの領域だと、監視ポリシーなどが結構厳しかったりします。
ただ、さきほどから記載している通り、EMRをあんまり目くじら立てて監視するのは得策ではないと考えてます。
「バッチ処理を最後まで実行できるのか」という観点で、監視項目も割り切ります。
こまごまとしたプロセス監視や死活監視は行わず、クラスターとして処理の継続が不可能になるような項目や事象に絞った監視ポリシーとすることでだいぶすっきりしました。
マネージドの恩恵をそこなわない
これに関して結構悩みどころです。
せっかくマネージドでいろいろと面倒なところをAWS側でカバーしてくれているのだから、利用する側もなるべくシンプルに素のまま使いたいなあと思うわけです。
Hadoopは構成するソフトウェアが多いぶん、パラメータ設計など本気でやろうとするとなかなか骨が折れますしね。
また変更したパラメータなどはちゃんと管理する必要もあるし、構築後の運用も考えると、パラメータチューニングをどこまでやるのかが悩みものです。(たいていドキュメント化してもメンテされなくなるし・・・)
なので、今のところ変更を加えているパラメータは必要最低限にするような方針にしています。
ここでいう必要最低減とは以下のような考え方です。
- あきらかに変更が必要なパラメータ(変更しないとそもそも処理すら動かせないといったもの)
- 世の中的にも当たり前になっているようなベストプラクティスなパラメータ(圧縮など)
チーム開発にあたって
最後にEMRでの開発にあたって考慮したことをまとめてみます。
なかなかEMR(というかHadoop全般)に精通したエンジニア自体が少ないなか、以下に開発生産性をあげるかがポイントだと考えました。
そこで以下のような方針をとるようにしています。
開発言語の選択
開発にあたっては、JavaでMapReduce処理を記述せず、SQLライクに操作できるものを選択するようにしています。
理由としては、やはりキャッチアップコストが一番にあげられます。
またコーディング規約を作成するにあたっても、SQLの方がルールを整理しやすいと考えました。
Javaで実装する場合、どの処理をMap、どこをReduce、中間ファイルはどこで作成するかなど、ジョブ毎に検討を行うのはなかなか骨が折れますし、規約化するポイントも増えるのではと懸念しました。
Pigなども検討しましたが、なるべく特殊な文法を覚えなくてすむという点でもバッチ処理では手堅くHiveを選択するようにしています。
ちなみに
最近話題の他のSQL on Hadoopプロダクトも検討したのですが、業務バッチ処理での採用はまだ見送っています。
ImpalaやPresto、Apache Drillなどが有名で、その特徴としてANSI準拠のSQLが利用可能な点があげられます。
ただ、そもそもSQL on Hadoopがアドホッククエリ用途を目的としているのもあり、メモリ上に乗り切らない規模のデータを扱うと極端に性能劣化するケースが多いです。
多少時間がかかってもいいから処理が安全に完了することを優先し、Hiveを採用することにしています。
以前SQL on Hadoopのプロダクト選定を行った際の内容をLTで紹介した資料があるので、ご参考までにご紹介します。
開発の標準化
HiveがSQLライクに記述できるとはいえ、裏で実行されるのはMapReduceジョブなので開発者が自由にHiveQLを記述してしまうと性能劣化につながる懸念があります。
なのでHiveQLコーディングの規約書を作成するようにしています。
規約自体は開発者がチェックリスト的に扱えるようにしており、なるべく開発者自身がMapReduceの挙動を意識しなくてもコーディングできるようにしています。
またその規約内で、ワークテーブルの作成基準なども合わせてまとめています。
運用しているHiveQLの規約については、機会があれば紹介させていただこうかと思います。
開発の環境
開発環境用のクラスタは節約のためマスタ/コアノードを同居させたEC2を1台で運用し、開発チームごとに割り当てています。
ちなみに、開発環境はディスク容量節約のためHDFSのブロックレプリケーション数を1にしています。(涙ぐましい・・)
また開発用のエディタとしてはHueを利用しています。
ただ、HueはローカルPC上に記述したHiveQLを保存できないため、主に動作確認を目的として利用しているのが現状です。
(おまけ)ちなみにエンタープライズといえばMapRじゃないの?
MapRは商用版のHadoopディストリビューションで、EMRでも選択できます。
商用版なだけに魅力的な機能が多いのですが、EMRでMapRを選択すると選べるEC2インスタンスタイプに限りが出てしまいます。。。
システム構成を後からでも柔軟に変えたいって時にちょっとつらいので採用は見送っています。
最後に
情報系の領域やWEB業界ではHadoopは枯れ枯れなのですが、まだ基幹領域での導入にあたっては考慮すべき事項があります。
ただそのパワーは絶大なので、ぜひエンタープライズ分野でもHadoopを盛り上げていきましょう!!