この記事は Jubatus Advent Calendar 2016 の13日目です。
本記事では、Jubatus の分散モードについての説明と注意事項などをまとめたいと思います。
分散モードとは
Jubatus は、スループットを向上させるために「分散モード」というクラスタ構成で運用することができます。
Jubatus サーバ のみで稼働させる「スタンドアロンモード」でも十分な性能が期待できますが、Jubatus サーバ と Jubatus プロキシ、Apache ZooKeeper による「分散モード」を使うと、スループットと耐障害性を向上させることができます。
「分散モード」のアーキテクチャ、概念、利用方法は、公式サイトの以下が参考になります。
分散モード運用時の注意点
前述の公式サイトにも記載されていますが、「分散モード」を運用する上で、注意しなくてはいけないことを少し説明します。
ZooKeeper の運用
「分散モード」では、Jubatus サーバ、Jubatus プロキシ の各プロセスは、ZooKeeper 上で管理され、死活監視が行われます。
簡単に説明すると以下のような感じです。
- Jubatus サーバ を起動すると、 ZooKeeper 上に
IPアドレス_ポート
というノード識別子 1 が追加される。 - Jubatus サーバ が停止すると、 ZooKeeper 上の ノード識別子 が自動的に削除される。
Jubatus サーバ のプロセスの監視はこのように行っており、タイミングにもよりますが、停止した Jubatus サーバに対して、Jubatus プロキシからリクエストが転送されるということは、発生しにくいようになっています。
運用上、問題となるのは ZooKeeper が停止したときです。
ZooKeeper が停止すると、この ZooKeeper に接続している Jubatus サーバ と Jubatus プロキシ は、協調動作ができないと判断し、 自らプロセスを停止 します。
そのため、 Jubatus を「分散モード」で動作させるときには、以下を推奨しています。 2
- ZooKeeper は冗長化(アンサンブル構成)して運用する
- ZooKeeper のパフォーマンスが低下しないように、ZooKeeper 専用のマシンを用意する
分散モードで理解しておきたいこと
「分散モード」で、理解しておきたいことをいくつかピックアップして紹介します。
プロキシの転送処理
まず、はじめに理解しておきたいのは、Jubatus プロキシのリクエスト転送処理です。
Jubatus 1.0.0 現在、Jubatus プロキシには、Jubatus サーバの負荷情報を確認してリクエストを転送するロードバランシングのような機能は存在せず、以下の 3種類 を提供しています。3
転送方式 | IDLにおける表記法 |
---|---|
すべての Jubatusサーバ へリクエストを転送する | broadcast |
ランダムに選択されたいずれか1台の Jubatusサーバ へリクエストを転送する | random |
Consistent Hashing にもとづいて Jubatusサーバ を選択し、リクエストを転送する(RPCメソッドの第1引数をキーとする) | cht |
各機械学習エンジン、各RPCメソッドにどの転送方式が採用されているかは、実は、公式サイトには掲載されていません。
ここ にある .idl
という拡張子のファイルに書いてあるアノテーションから確認することができます。(機械学習エンジンのデータの持ち方や各RPCの利用シーンを想定して設定されています)
MIX (ゆるやかなモデル共有)
前述で紹介した公式サイトのページにもあるとおり、「分散モード」では、「MIX」という処理が動きます。
「MIX」は、 ゆるやかなモデル同期 を行う機能で、同一時刻において同じモデルが全サーバノードで共有されていることを保証しない という割り切った処理です。そのため、学習(登録)したデータをもれなく正確に返却する必要があるような利用シーンでは、「分散モード」ではなく「スタンドアロンモード」で利用することを推奨します。(機械学習の利用シーンでは、そのようなケースはあまり無いかもしれませんが)
これがどういうことかということを、前述の Jubatus プロキシ の転送方式 も加味して説明します。
以下のような Jubatus クラスタ を想定します。
- 機械学習エンジン: 推薦 (
jubarecommender
) - Jubatus サーバ数: 3
- Jubatus プロキシ数: 1
上記のクラスタに対して、データの追加(update_row
) と 推薦(similar_row_from_datum
) を行うようなケースでは、以下のようなことが起こりえます。
-
hoge
という ID のデータを追加する:- クライアント から Jubatus プロキシ に対して、
update_row("hoge", datum)
をリクエストする。 -
update_row
のリクエスト転送方式は、cht
であるため、Jubatus プロキシは、 Jubatus サーバ のなかからCHTにもとづいてノードを選択し、リクエストを転送する。 - 2 で選択された Jubatus サーバに
hoge
という ID のデータが追加される。
- クライアント から Jubatus プロキシ に対して、
-
MIX が行われる前に 推薦結果 を取得する:
- クライアント から Jubatus プロキシ に対して、
similar_row_from_datum(datum)
をリクエストする。 -
similar_row_from_datum
のリクエスト転送方式は、random
であるため、Jubatus プロキシは、 Jubatus サーバ のなかからランダムにノードを選択し、リクエストを転送する。 => このときupdate_row
が通知されていないノードが選択されたとする - 2 で選択された Jubatus サーバのモデルを参照して、結果を返却する。 => モデルにデータが存在しないので
hoge
という ID は返却されない
- クライアント から Jubatus プロキシ に対して、
と、このように データの追加(update_row
) と 推薦(similar_row_from_datum
) では、リクエストの転送方式が異なるので、Jubatus クラスタに対してデータを追加したつもりでも、分析結果には追加したはずのデータが含まれていないという状況が発生することになります。(補足: MIX が行われた後だったら、このようなことは発生しません)
まとめ
Jubatus の「分散モード」をテーマに公式サイトのリンクを交えながら、運用上の注意点 や 理解しておきたい仕様 を簡単に紹介しました。
「スタンドアロンモード」だけでこと足りることも多いですが、「分散モード」もぜひ使ってみてください。
明日は @torash さんの記事です。お楽しみに!
最後に... 文字ばっかりになってしまい、ごめんなさい。
-
Jubatus プロキシでは、この ノード識別子 の一覧を参照し、リクエストを転送する先を決定する。 ↩
-
ZooKeeper の運用については、ZooKeeper の公式ドキュメント を参考にしましょう。 ↩