Zookeeperによる分散システム管理(1)

仕事でZookeeperを直接触る機会があったので「ZooKeeperによる分散システム管理」を読みました。
個人的に大事そうと思ったことをまとめてみました。


はじめに

提供する機能

分散システムの協調動作を実現するための以下の機能を提供する。 ここで言う分散システムとは複数の筐体にまたがって独立並行に動作する複数のコンポーネントからなるシステムである。

  1. 強一貫性、順序保存、耐久性の保証
  2. 典型的な同期機構を実装するための機構
  3. 実際の分散システムが誤動作に導く並行性の様々な側面を扱う簡単な方法

Zookeeperで管理するべきデータ

アプリケーションを設計する際には、アプリケーションデータと制御データとを分離するのが理想である。 Zookeeperのアンサンブルが管理するべきデータは後者である。

基本

znode

Zookeeperではデータをznodeと呼ばれる小さいデータノードに格納する。

形式

バイト配列。

属性
  • 永続znode
  • 短命znode

それを作成したセッションが存在する間のみ有効(クライアントがクラッシュしたり、接続がクローズされたりすると自動的に削除される)。

  • シーケンシャル

/tasks/task-のようなznodeを作成すると、シーケンシャルに採番され/tasks/task-1のようにznodeは作成される。

  • 通知

znodeに対する変更通知トリガーを設定することが可能。 通知は1度きりであるが、他の変更が同じznodeに加えられるよりも先にクライアントに配送されることが保証されている。

  • バージョン

znodeはバージョン管理されており、データが更新されるとインクリメントされる。

アーキテクチャ

クォラム構成

Zookeeperでは構成する全てのサーバにデータを複製するが、クライアントがデータを送信した際に、全てのサーバにデータが格納されるのを待つのではなく、過半数のサーバに対してデータが格納されればOKとしている。 したがって、クォラム構成を組む場合には、最低でも3台のサーバを用意する必要がある。 (障害が許容される台数は半分よりも小さい台数(3台の場合、1台))

セッション

1つのセッションにおいてリクエストの順序は保証される。
複数のスレッドがある場合は、注意が必要。
具体的には、ConnectionLossExceptionによってリクエストを再発行する際には新しいリクエストが生成されるので、元のリクエストよりも後に他のスレッドで生成されたリクエストよりも後に実行される可能性があるため注意が必要。

  1. Disconnected
  2. SyncConnected
  3. AuthFailed
  4. ConnectedReadOnly
  5. SaslAuthenticated
  6. Expired

イベントのタイプ

  1. NodeCreated
  2. NodeDeleted
  3. NodeDataChanged
  4. NodeChildredChanged

運用

再構成

計算機3台からなるZookeeperアンサンブルを作成した後、スケールするために計算機5台で再構成したくなったとする。
その場合、リーダー選出され全てのサーバに同期されるのを確認した後、落として再度起動する。
同期が完全でない状態で落としてしまうと、不整合が発生する可能性があるためである。
なお、スタンドアロン構成からの再構成はできない。

動的再構成の機能は2018/02/21現時点で3.5.3-betaバージョンには盛り込まれているが、最新の安定版である3.4.11には含まれていない。

マルチテナント

1つのZookeeperを複数のアプリケーションで運用する方が、現実的。

理由は以下の3つ。

  1. 信頼性の高いサービス提供のためには専用のハードウェアを用いることが望ましい。
  2. 経験的にバースト的なトラフィックが起こり負荷が上がることはあるが、その後は長い間不活性となる。複数のアプリで利用した方が、資源を有効利用できる。
  3. 2つのアプリケーションが3サーバからなるアンサンブルをそれぞれ持つよりも、5サーバからなる1つのアンサンブルを利用した方が、より障害耐性が高くなる。


その場合、クライアント側の接続識別子に

host:port

ではなく

host:port/appname

のようにすることで、アプリケーション側では専用のZookeeperを利用しているかのように利用することができる。