失敗は一時の恥

パッケージソフト開発をしているプログラマが気の赴くままに何かを投稿するブログ.

ZooKeeper に触ってみよう

ZooKeeper に触ってみよう

ZooKeeper という,分散アプリケーション協調サービスがあります. どんなことができるのか,簡単に ZooKeeper に触れてみましょう.

この記事では ZooKeeper についての簡単な紹介と, 実際に ZooKeeper を起動して,簡単なコマンドを実行するところまで試してみます.

ZooKeeper とは何か

ZooKeeper というのは,分散アプリケーションを協調させるためのサービスです.

分散アプリケーションというのは,1 台のマシンで実行されるのではなく,複数のマシンで別々のプロセスとして実行されるといったアプリケーションです. 単に別個のプロセスとして走らせているだけではデータの整合性などで問題が出たりするため,各プロセスは何らかの形で「協調」することが求めらたりします.

ZooKeeper は,その「協調」のための仕組みを提供してくれます. ZooKeeper Recipes and Solution というページでは,次のようなケースに ZooKeeper を使用できるという例が挙げられています:

  • バリア (Barriers)
  • キュー (Queues)
  • ロック (Locks)
  • 2 相コミット (Two-phased Commit)
  • リーダー選出 (Leader Election)

実際に ZooKeeper が提供しているのは,ネットワーク越しにアクセスする小さなファイルシステムのようなものです.

ルートディレクト/ に相当するものがあり,その配下に znode と呼ばれるエントリーを作成していきます.

各 znode は最大 1 MB のデータを保持することができます. また,各エントリーは子エントリーを持つことができます.

分散アプリケーション達は,この znode と呼ばれるデータ構造を介して協調をすることになります.

実際にどんなところで使われている?

ZooKeeper はこんなところで使われているようです:

Apache Solr

Solrオープンソースの検索システムです. Solr には,SolrCloud モードという仕組みがあり,複数台の Solr を組み合わせて冗長化を行うことができます.

この冗長化を行うにあたり,各 Solr ノードの協調に ZooKeeper を利用しています.

Apache Hadoop

Hadoop は,MapReduce でデータを分散処理することなどができて,いわゆるビッグデータ絡みでよく名前が挙がりますね.

この Hadoop も ZooKeeper を利用しています.

Netflix のシステムのどこか

curator という ZooKeeper を利用するライブラリを,NetflixOSS として公開しています.あの動画配信の Netflix です.

具体的に Netflix がどういう風に ZooKeeper を利用しているのかは明らかではない (ちょっと調べれば事例とかあるかも?) のですが,ライブラリを作り込むくらいには ZooKeeper が利用されているものと思われます. (いい加減な説明ですみません...)

他にも,ZooKeeper/PoweredBy - Hadoop Wiki などを参照すると事例が多く見つかります.

ZooKeeper を起動する

それでは ZooKeeper を起動してみましょう.

方法はいくつかあります.

といった選択肢がありますが, 今回は使い捨てのお試し程度の利用なので,Docker を利用します. (Docker 自体の導入方法や細かい使い方の説明は,ここではしません)

ZooKeeper の Docker イメージは, Docker Hub の公式イメージを使います.現在 (2018 年 1 月時点) の最新安定板は 3.4.11 となっているので,それを利用します.

起動するには

$ docker run -d --rm --name zoo -p 2181:2181 zookeeper:3.4.11

などとします.

ここでは,

  • バッググランドで動作させる (-d)
  • 停止時に自動でコンテナを破棄する (--rm)
  • コンテナに "zoo" という名前をつける (--name zoo)
  • コンテナのポート 2181 をホストのポート 2181 として公開する (-p 2181:2181)

というオプションにしています.

$ docker ps

とすれば,"zoo" というコンテナが動作していることがわかるはずです.

停止するときは,

$ docker stop zoo

とします.

zkcli で ZooKeeper に接続する

ZooKeeper サーバが起動したので,クライアントからアクセスしてみましょう.

$ docker run -it --rm --link zoo:zookeeper zookeeper:3.4.11 zkCli.sh -server zookeeper

上記のコマンドを実行すると,Docker コンテナとして zkCli.sh という対話環境に入ることができます.

ここでは Docker で zkCli.sh を実行しましたが,zoo コンテナのポートをホストに公開してあるので,ホストマシンから zkcli コマンドで (インストールしてあれば) 接続することもできます.

zkcli のコマンド

クライアントの準備もできたので,ZooKeeper のコマンドを使ってみましょう.

基本的なコマンドをあげてみます.

  • 指定した znode の子ノードを取得する:
$ ls /
# => [zookeeper]
  • znode を作成する:
# create /test 'Test'
# ls /
# => [zookeeper, test]
  • znode のデータを取得する:
# get /test
# => 先にセットした Test という値と,そのほかのメタデータが得られる
  • 対話環境から抜ける:
$ quit

極めて基本的なコマンドではありますが,これで ZooKeeper のデータを登録・取得することができます.

協調のためのエッセンス

ZooKeeper でファイルシステムのようなデータツリーを作成できることはわかりましたが,それだけならわざわざ ZooKeeper なんていう不慣れなものを持ち出す必要はありません.

ここでは,分散アプリケーションの協調に役立つ ZooKeeper の特徴的な機能を見ていきます.

分散アプリケーションのための機能ですから,コンソールを 2 つ立ち上げて,2 つの zkCli で実験をしてみましょう.

セッションが有効な間だけ存続するデータ

ZooKeeper では,クライアントのセッションが有効な間だけ存続するデータを作成することができます. これを短命 (ephemeral) znode と呼びます.

まず,1 つ目の zkcli で短命 znode を作成してみましょう. 短命 znode を作成するには,-e オプションを使用します.

$ create -e /ephemeral_test 'This is ephemeral znode'

2 つ目の zkcli で,作成した znode を確認します.

$ ls /
# => [ephemeral_test, zookeeper]

ここで,1 つ目の zkcli を終了します.

$ quit

再度 2 つ目の zkcli で znode を確認するとどうでしょう.

$ ls /
# => [zookeeper]

/ephemeral_test という znode が消えています.

このような短命 znode は,例えば動的に増減するアプリケーションインスタンスの管理に役立てることができます.

データに対する変更の検知

ZooKeeper には,データに変更が加えられたときそれを検知するための仕組みがあります.

1 つ目の zkcli でデータの作成,監視 (watch) を行います.監視を行うには,get コマンドに watch オプションを付加します.

$ create /watch_test 'Watch Test'
$ get /watch_test watch

2 つ目の zkcli で,/watch_test のデータを変更してみましょう.

$ set /watch_test

すると,1 つ目の zkcli の方で

WatchedEvent state:SyncConnected type:NodeDataChanged path:/watch_test

というメッセージが表示されます. メッセージから「/watch_test という znode のデータが変更された」ということが読み取れます.

検知できる変更は他にも

  • znode が作成された
  • znode が削除された
  • znode に子 znode が作成された

といったイベントがあります.

この監視の仕組みを利用して,データの追加・変更・削除についてアプリケーション達は協調動作をすることができるようになります.

実際にアプリケーションを協調させるには

ここまででは zkcli コマンドを使って ZooKeeper にアクセスしていましたが,実際に分散アプリケーションを協調動作させるには,アプリケーションの中で ZooKeeper を利用した実装を行う必要があります.

ZooKeeper の公式な API としては,Java と C が提供されています. これ以外の言語についてもサードパーティーが提供している場合があります.

おわり

今回は ZooKeeper を起動して,簡単なコマンドを叩いてみました.

短命 znode や変更の検知など,分散アプリケーションを協調させるうえで役立ちそうな機能も確認しました.

いずれ,実際に動くプログラムの紹介もしてみようと思います.