Apache > ZooKeeper
 

ZooKeeper

ZooKeeper: 分散アプリケーションのための分散協調サービス

ZooKeeperは、分散アプリケーションのための分散型のオープンソース協調サービスです。同期、構成管理、グループとネーミングのためのより高度なサービスを実装するために、分散アプリケーションが基盤として利用できるシンプルなプリミティブのセットを公開しています。プログラミングが容易になるように設計されており、ファイルシステムの使い慣れたディレクトリツリー構造に似たデータモデルを使用しています。Javaで動作し、JavaとCの両方のバインディングがあります。

協調サービスは、正しく実装するのが非常に難しいことで知られています。特に、競合状態やデッドロックなどのエラーが発生しやすいためです。ZooKeeperの動機は、分散アプリケーションが協調サービスをゼロから実装する責任を軽減することです。

設計目標

ZooKeeperはシンプルです。 ZooKeeperは、標準のファイルシステムと同様に編成された共有階層名前空間を通じて、分散プロセスが互いに協調することを可能にします。名前空間は、ZooKeeper用語で「znode」と呼ばれるデータレジスタで構成されており、これらはファイルやディレクトリに似ています。ストレージ用に設計された一般的なファイルシステムとは異なり、ZooKeeperのデータはメモリ内に保持されるため、ZooKeeperは高いスループットと低いレイテンシを実現できます。

ZooKeeperの実装は、高性能、高可用性、厳密に順序付けられたアクセスを重視しています。ZooKeeperのパフォーマンスの側面は、大規模な分散システムで使用できることを意味します。信頼性の側面は、単一障害点にならないようにします。厳密な順序付けは、高度な同期プリミティブをクライアントで実装できることを意味します。

ZooKeeperは複製されます。 ZooKeeperが調整する分散プロセスと同様に、ZooKeeper自体もアンサンブルと呼ばれるホストのセットに複製されることを意図しています。

ZooKeeper Service

ZooKeeperサービスを構成するサーバーは、すべて互いに認識している必要があります。永続ストア内のトランザクションログとスナップショットとともに、状態のメモリ内イメージを保持します。サーバーの大部分が利用可能であれば、ZooKeeperサービスは利用可能です。

クライアントは、単一のZooKeeperサーバーに接続します。クライアントは、リクエストの送信、レスポンスの受信、ウォッチイベントの受信、ハートビートの送信を行うTCP接続を維持します。サーバーへのTCP接続が切断された場合、クライアントは別のサーバーに接続します。

ZooKeeperは順序付けられています。 ZooKeeperは、すべてのZooKeeperトランザクションの順序を反映する番号で各更新にタイムスタンプを付けます。後続の操作では、この順序を使用して、同期プリミティブなどのより高度な抽象化を実装できます。

ZooKeeperは高速です。 特に「読み取り dominant」ワークロードで高速です。ZooKeeperアプリケーションは数千台のマシンで動作し、書き込みよりも読み取りが一般的な場合、約10:1の比率で最適なパフォーマンスを発揮します。

データモデルと階層型名前空間

ZooKeeperによって提供される名前空間は、標準のファイルシステムの名前空間とよく似ています。名前は、スラッシュ(/)で区切られたパス要素のシーケンスです。ZooKeeperの名前空間内のすべてのノードは、パスによって識別されます。

ZooKeeperの階層名前空間

ZooKeeper's Hierarchical Namespace

ノードと一時ノード

標準のファイルシステムとは異なり、ZooKeeper名前空間の各ノードには、データと子が関連付けられています。ファイルがディレクトリでもあることを許可するファイルシステムのようなものです。(ZooKeeperは、状態情報、構成、位置情報などを格納するように設計されているため、各ノードに格納されるデータは通常、バイトからキロバイトの範囲で小さくなります。)ZooKeeperデータノードについて話していることを明確にするために、_znode_という用語を使用します。

Znodeは、データ変更、ACL変更、タイムスタンプのバージョン番号を含む統計構造を保持し、キャッシュの検証と調整された更新を可能にします。znodeのデータが変更されるたびに、バージョン番号が増加します。たとえば、クライアントがデータを取得するたびに、データのバージョンも受信します。

名前空間内の各znodeに格納されているデータは、アトミックに読み書きされます。読み取りは、znodeに関連付けられたすべてのデータバイトを取得し、書き込みはすべてのデータを置き換えます。各ノードには、誰が何ができるかを制限するアクセス制御リスト(ACL)があります。

ZooKeeperには、一時ノードの概念もあります。これらのznodeは、znodeを作成したセッションがアクティブである限り存在します。セッションが終了すると、znodeは削除されます。

条件付き更新とウォッチ

ZooKeeperは、_ウォッチ_の概念をサポートしています。クライアントは、znodeにウォッチを設定できます。 znodeが変更されると、ウォッチがトリガーされ、削除されます。ウォッチがトリガーされると、クライアントはznodeが変更されたことを示すパケットを受信します。クライアントとZooKeeperサーバーのいずれかとの接続が切断された場合、クライアントはローカル通知を受信します。

3.6.0の新機能:クライアントは、znodeに永続的な再帰ウォッチを設定することもできます。これは、トリガーされたときに削除されず、登録されたznodeと子znodeの変更に対して再帰的にトリガーされます。

保証

ZooKeeperは非常に高速で非常にシンプルです。しかし、その目標は、同期などのより複雑なサービスを構築するための基盤となることであるため、一連の保証を提供します。これらは次のとおりです。

シンプルなAPI

ZooKeeperの設計目標の1つは、非常にシンプルなプログラミングインターフェイスを提供することです。その結果、次の操作のみがサポートされます。

実装

ZooKeeperコンポーネントは、ZooKeeperサービスのハイレベルコンポーネントを示しています。リクエストプロセッサを除いて、ZooKeeperサービスを構成する各サーバーは、各コンポーネントの独自のコピーを複製します。

ZooKeeper Components

複製データベースは、データツリー全体を含むメモリ内データベースです。更新は回復のためにディスクに記録され、書き込みはメモリ内データベースに適用される前にディスクにシリアル化されます。

すべてのZooKeeperサーバーはクライアントにサービスを提供します。クライアントは、リクエストを送信するために1つのサーバーに接続します。読み取りリクエストは、各サーバーデータベースのローカルレプリカから処理されます。サービスの状態を変更するリクエスト、書き込みリクエストは、合意プロトコルによって処理されます。

合意プロトコルの 一環として、クライアントからのすべての書き込みリクエストは、_リーダー_と呼ばれる単一サーバーに転送されます。 _フォロワー_と呼ばれる残りのZooKeeperサーバーは、リーダーからメッセージの提案を受信し、メッセージの配信に同意します。メッセージング層は、障害発生時のリーダーの交換と、リーダーとのフォロワーの同期を処理します。

ZooKeeperは、カスタムのアトミックメッセージングプロトコルを使用します。メッセージング層はアトミックであるため、ZooKeeperはローカルレプリカが決して分岐しないことを保証できます。リーダーが書き込みリクエストを受信すると、書き込みが適用される時点でのシステムの状態を計算し、この新しい状態をキャプチャするトランザクションに変換します。

用途

ZooKeeperへのプログラミングインターフェイスは、意図的にシンプルです。ただし、これを使用して、同期プリミティブ、グループメンバーシップ、所有権など、より高度な操作を実装できます。

パフォーマンス

ZooKeeperは、高性能を実現するように設計されています。しかし、本当にそうでしょうか?Yahoo! ResearchのZooKeeper開発チームの結果は、それが高性能であることを示しています。(読み取り/書き込み比率が変化する場合のZooKeeperスループットを参照してください。)書き込みにはすべてのサーバーの状態を同期する必要があるため、読み取りが書き込みを上回るアプリケーションでは特に高性能です。(協調サービスの場合、通常は読み取りが書き込みを上回ります。)

ZooKeeper Throughput as the Read-Write Ratio Varies

読み取り/書き込み比率が変化する場合のZooKeeperスループットは、デュアル2Ghz Xeonと2つのSATA 15K RPMドライブを搭載したサーバーで実行されているZooKeeperリリース3.2のスループットグラフです。1つのドライブは、専用のZooKeeperログデバイスとして使用されました。スナップショットはOSドライブに書き込まれました。書き込みリクエストは1K書き込み、読み取りは1K読み取りでした。「サーバー」は、ZooKeeperアンサンブルのサイズ、つまりサービスを構成するサーバーの数を示します。クライアントをシミュレートするために、約30の他のサーバーが使用されました。ZooKeeperアンサンブルは、リーダーがクライアントからの接続を許可しないように構成されました。

注記

バージョン3.2では、r / wのパフォーマンスが以前の3.1リリースと比較して約2倍向上しました。

ベンチマークは、信頼性も高いことを示しています。エラー発生時の信頼性は、デプロイメントがさまざまな障害にどのように対応するかを示しています。図に示されているイベントは次のとおりです。

  1. フォロワーの障害と回復
  2. 別のフォロワーの障害と回復
  3. リーダーの障害
  4. 2つのフォロワーの障害と回復
  5. 別のリーダーの障害

信頼性

障害が注入されたときのシステムの経時的な動作を示すために、7台のマシンで構成されるZooKeeperサービスを実行しました。以前と同じ飽和ベンチマークを実行しましたが、今回は書き込みの割合を一定の30%に保ちました。これは、予想されるワークロードの控えめな比率です。

Reliability in the Presence of Errors

このグラフから、いくつかの重要な観察結果が得られます。まず、フォロワーに障害が発生してもすぐに回復する場合、ZooKeeperは障害にもかかわらず高いスループットを維持できます。しかし、おそらくもっと重要なことは、リーダー選出アルゴリズムにより、スループットの大幅な低下を防ぐのに十分な速さでシステムが回復できることです。私たちの観察では、ZooKeeperは新しいリーダーを選出するのに200ミリ秒未満かかります。3つ目に、フォロワーが回復すると、ZooKeeperはリクエストの処理を開始するとスループットを再び上げることができます。

ZooKeeperプロジェクト

ZooKeeperは、多くの産業アプリケーションで успешно 使用されてきました。Yahoo!では、高スケーラブルなパブリッシュ/サブスクライブシステムであるYahoo! Message Brokerの調整および障害復旧サービスとして使用されており、数千のトピックの複製とデータ配信を管理しています。また、Yahoo!クローラーのFetching Serviceでも障害復旧の管理に使用されています。その他にも、多くのYahoo!広告システムが、信頼性の高いサービスを実装するためにZooKeeperを使用しています。

すべてのユーザーと開発者は、コミュニティに参加して専門知識を提供することをお勧めします。詳細については、ApacheのZookeeperプロジェクトをご覧ください。