|
この記事はWeChat公式アカウント「sowhat1412」から転載されたものです。著者はsowhat1412です。転載の許可については、sowhat1412公式アカウントまでお問い合わせください。 1. ZooKeeperの紹介 ZooKeeperは、分散アプリケーションに一貫性サービスを提供するために設計されたオープンソースの分散コーディネーションフレームワークであり、ビッグデータシステム全体の管理者として機能します。ZooKeeperは、複雑でエラーが発生しやすい重要なサービスをカプセル化し、ユーザーに効率的で安定した使いやすいサービスを提供します。 上記の公式用語がよくわからない場合は、ZooKeeper をファイル システムと通知監視メカニズムを組み合わせたものと考えることができます。 1.1 ファイルシステム ZooKeeper はファイルシステムに似たツリー型のデータ構造を維持します。この特性のため、ZooKeeper は大量のデータの保存には適していません。各ノードのストレージ容量は 1MB に制限されています。NameService などの各サブディレクトリエントリは、znode(ディレクトリノード)と呼ばれます。ファイルシステムと同様に、znode を自由に追加および削除したり、znode の配下の子 znode を追加および削除したりできます。唯一の違いは、znode はデータを保存できる点です。znode にはデフォルトで 4 つの種類があります。
1.2 監視および通知メカニズム WatcherメカニズムはZooKeeperの非常に重要な機能です。ZooKeeper上に作成されたノードに基づいて、ノードデータの変更、ノードの削除、子ノードの状態の変化といったイベントをリッスンするイベントをこれらのノードにバインドできます。このイベントメカニズムを通じて、分散ロックやZooKeeperベースのクラスタ管理といった機能を実装できます。 ウォッチャーの機能: データが変更されると、ZooKeeper は Watcher イベントを生成し、クライアントに送信します。ただし、クライアントが通知を受け取るのは一度だけです。その後、ノードが再び変更された場合、以前に Watcher を設定したクライアントはメッセージを再度受信しません(Watcher は 1 回限りの操作です)。Watcher をループ処理することで、永続的な監視を実現できます。 ZooKeeper の Watcher メカニズムは、大きく分けて 3 つのプロセスに分けられます。
リスニングプロセス:
1.3 Zookeeperの機能
分散調整システム:リーダーはフォロワーにデータを同期し、ユーザーリクエストはフォロワーを介してデータを取得できます。これにより単一障害点が回避され、同期時間が極めて短い限り、これは優れた分散調整システムです。 CAP定理(CAP原理とも呼ばれる)は、分散システムにおいて、一貫性、可用性、分断耐性は互いに排他的であると述べています。CAP定理によれば、これら3つの特性のうち最大でも2つしか同時に達成できず、3つすべてを同時に達成することは不可能です。 2. Zookeeperが提供する機能 ZooKeeper の豊富なデータ ノードを相互に活用し、Watcher イベント通知メカニズムと組み合わせることで、データの公開/サブスクリプション、負荷分散、ネーミング サービス、分散調整/通知、クラスター管理、マスター選択、分散ロック、分散キューなど、分散アプリケーションに関係する一連のコア機能を簡単に構築できます。 1. データの公開/購読 特定のデータが複数のマシンで共有され、データ量が少ないのにこの情報が頻繁に変更される場合、このデータは ZK での保存に適しています。
2. 分散ロック 分散ロックについてはRedisのセクションで既に説明しましたが、Redisの分散ロックはZooKeeperよりも優れたパフォーマンスを提供します。ZooKeeperベースの分散ロックは、一般的に2つのカテゴリに分類されます。 排他性を維持する コアとなるアイデア:ZooKeeperには、固有のエフェメラルノードが存在します。そのノードを取得したスレッドのみがデータを操作でき、取得していないスレッドは待機状態になります。欠点:これはハーディング効果を引き起こす可能性があり、最初のスレッドがロックの使用を終えた後、999個の同時スレッドが同時にZooKeeperにロックを要求する可能性があります。 タイミングを制御する 主な目的は、集団化効果(ハーディング効果)を回避することです。一時的なノードは事前に存在します。ロックを取得しようとするすべてのスレッドは、その下に一時的な連番ディレクトリノードを作成します。最も小さい番号を持つノードがロックを取得し、使用後に削除します。後続のスレッドはロック取得のためにキューイングを行います。 3. 負荷分散 異なるサーバー上の複数の同一 JAR ファイルを使用して同じサービスを実行するには、サーバー側で Nginx を使用して、またはクライアント側で ZooKeeper を使用して負荷分散を構成できます。
ZooKeeper ロード バランシングと Nginx ロード バランシングの違い: ZooKeeperには単一障害点の問題はありません。zabメカニズムにより、単一障害点が発生した場合でも新しいリーダーが選出されます。zabはサービスの登録と検出のみを担当し、転送は行わないため、データ交換(コンシューマとサービスプロバイダ間の直接通信)が1回で済みます。対応する負荷分散アルゴリズムは、お客様ご自身で実装する必要があります。 Nginxは、高負荷と大容量データが発生する単一障害点(SPOF)の問題を抱えています。KeepAlivedとLVSを組み合わせたバックアップシステムによって高可用性が実現されています。各負荷条件は中間者(man-in-the-middle)として動作し、ネットワーク負荷を増加させます(コンシューマーとサーバー間の間接通信による)。また、組み込みの負荷分散アルゴリズムも備えています。 4. ネーミングサービス ネーミングサービスとは、名前を指定してリソースまたはサービスのアドレスを取得することを指します。ZooKeeperを使用してグローバルに一意のパスを作成することで、このパスをクラスター内のクラスター、提供されているサービスのアドレス、リモートオブジェクトなどを指す名前として使用できます。 5. 分散調整/通知 システム スケジューリングでは、ユーザーが ZooKeeper 内のノードの値を変更すると、ZooKeeper はそのノードのウォッチャーを登録しているすべてのクライアントにその変更を送信して通知します。 パフォーマンス レポートの場合、各作業プロセスは作業の進行状況を保持するディレクトリ内に一時ノードを作成します。これにより、集約されたプロセスはディレクトリのサブノードの変更を監視し、作業の進行状況に関するリアルタイムのグローバル情報を取得できます。 6. クラスター管理 ビッグデータシステムにおけるクラスタサービスのほとんどは、ZooKeeperによって管理されているように見えます。しかし実際には、管理の主な焦点は、マシンの動的なオンライン/オフライン状態とリーダー選出にあります。 動的なオンライン/オフライン ステータス: 例えば、ZooKeeper サーバーには /Configuration という znode があります。クラスタ内の各マシンが起動すると、このノードの下に EPHEMERAL タイプのノードが作成されます。例えば、server1 は /Configuration/Server1 を作成し、server2 は **/Configuration/Server1** を作成します。そして、server1 と server2 の両方が親ノード /Configuration を監視します。つまり、この親ノードの下のデータまたは子ノードに変更があると、このノードを監視しているクライアントに通知されます。 リーダー選挙: ZooKeeper の強力な一貫性を活用することで、分散型かつ高同時実行性のシナリオにおいて、ノード作成のグローバルな一意性を保証します。つまり、複数のクライアントが同時に /Master ノードの作成を要求した場合、最終的に成功するのは 1 つのクライアント要求のみです。この特性により、分散環境におけるクラスタ選出が非常に容易になります。 これには動的なマスター選出が含まれます。これは、各ノードに自動的に番号を割り当てるEPHEMERAL_SEQUENTIAL型ノードの特性を活用します。すべてのリクエストは成功しますが、作成順序が定められており、毎回、シーケンス番号が最も小さいマシンがマスターとして選択されます。 3 リーダー選挙 ZooKeeper クラスタ内のノード数は奇数でなければならず、通常は 3 または 5 で十分です。クラスタがリーダーレス状態にならないようにするには、リーダーを選出する必要があります。これは頻繁にテストされる概念です。 3.1 予備知識 3.1.1. ノードの4つの状態。 LOOKING: リーダー探索状態。サーバーがこの状態にある場合、現在のクラスターにはリーダーが存在しないと想定し、リーダー選出状態に移行する必要があります。 FOLLOWING: フォロワー状態。クライアントからの非トランザクションリクエストを処理し、トランザクションリクエストをリーダーサーバーに転送し、トランザクション提案への投票に参加し、リーダー選出投票に参加します。 LEADING: リーダー状態。トランザクションリクエストの唯一のスケジューラおよびプロセッサであり、クラスタ内のトランザクションの順次処理を保証します。また、クラスタ内のすべてのサーバーのスケジューラ(フォロワーの管理とデータの同期)でもあります。 OBSERVING: オブザーバー状態。バージョン3.0以降で導入されたサーバーロールです。クラスタのトランザクション処理能力に影響を与えることなく、クラスタの非トランザクション処理能力を強化します。非トランザクションクライアントリクエストを処理し、トランザクションリクエストをリーダーサーバーに転送し、いかなる投票にも参加しません。 3.1.2 サーバーID サーバーIDは通常、ZooKeeperクラスタのセットアップ時にmyidファイルで各ノードに割り当てられます。IDが大きいほど、リーダー選択アルゴリズムにおける重み付けが大きくなります。例えば、初期起動時には、サーバーIDに基づいて比較が行われます。 3.1.3 ZXID ZooKeeper は、識別のためにグローバルに増加するトランザクション ID (zxid) を使用します。すべてのプロポーザルには、送信時に ZooKeeper トランザクション ID が付加されます。zxid は 64 ビットの Long 型で、トランザクションの順序一貫性を確保するために不可欠です。zxid の上位 32 ビットはエポックを表し、下位 32 ビットはトランザクション ID (xid) を表します。zxid が大きいほど、より新しいデータであると考えられます。 各リーダーは、時代/王朝を表す固有のエポック値を持ち、リーダーのサイクルを識別するために使用されます。新しいエポックは、新しい選出が始まるたびに生成されます。新しいリーダーが選出されると、エポックがインクリメントされ、すべてのzkServerのzxidとエポックが更新されます。 `xid` は連続して増加するトランザクション番号です。値が大きいほど、データは新しいことを意味します。すべての提案は、送信時に `zxid` が割り当てられます。その後、データベースの2段階プロセスに従って、まずトランザクション実行リクエストが他のサーバーに送信されます。半数以上のマシンがリクエストを正常に実行できる場合、実行が開始されます。 3.2 リーダー選挙 リーダー選出は、一般的に、起動時選出と、リーダーが失敗した後の実行時選出に分けられます。 3.2.1 起動時のリーダー選出 上記の 5 台のマシンを例にとると、クラスターは、その半分以上、つまり少なくとも 3 台のサーバーが起動されている場合にのみ正常に動作します。
上記のプロセスと同様に、サーバー1と2はまず自身に投票します。その後、サーバー3のIDが最も大きいため、サーバー3に投票先を変更します。投票結果は、サーバー1が0票、サーバー2が0票、サーバー3が3票です。この時点で、サーバー3が過半数(3票)以上を獲得し、サーバー3がリーダーに選出されます。サーバー1と2のステータスは「FOLLOWING」に変更され、サーバー3のステータスは「LEADING」に変更されます。
この時点で、サーバー1、2、3はLOOKING状態ではなくなり、投票情報を変更しませんが、投票結果を交換します。サーバー3は3票、サーバー4は1票を持っています。この時点で、サーバー4は多数決に従い、投票情報をサーバー3の情報に変更し、状態をFOLLOWINGに変更します。
サーバー4と同様に、サーバー3が投票を受け取ります。この時点で、サーバー3の投票数は5票、サーバー5の投票数は0票です。その後、サーバー5のステータスは「フォロー中」に変更されます。
リーダーはサーバー3で、ステータスは「LEADING」です。残りのサーバーはフォロワーで、ステータスは「FOLLOWING」です。 3.2.2 ランタイムリーダー選出 マスターノードが動作中にクラッシュした場合、リカバリモードに移行します。新しいリーダーが選出されるまで、外部サービスを停止します。これは、大きく分けて選出、検出、同期、ブロードキャストの4つの段階に分けられます。
3.3 スプリットブレイン スプリットブレイン問題は、HadoopやSparkなどのクラスター展開において重要な考慮事項です。この問題に対処するために、ZABでは2N+1ノードのクラスターサイズが必要です。ネットワークが分割されると、一方のクラスターは常に過半数のノードを持ち、もう一方のクラスターはN+1ノード未満になります。リーダーの選出には過半数投票が必要であるため、以下の結論が導き出されます。 多数決ルールにより、Zookeeper クラスターにはリーダーが存在しないか、リーダーが 1 人だけ存在するため、スプリット ブレインの問題を回避できます。 4. ZABコンセンサスプロトコル まず「ビッグデータの簡単な紹介」(または「2PC、3PC、Paxos、Raft、ZAB についての簡単な説明」) を読むことをお勧めします。そうしないと、理解が難しくなる可能性があります。 4.1 ZABプロトコルの概要 ZAB(Zookeeper Atomic Broadcast)プロトコルは、分散調整サービスZooKeeper専用に設計された整合性プロトコルであり、クラッシュリカバリをサポートします。このプロトコルに基づいて、ZooKeeperはマスター・スレーブ方式のアーキテクチャを実装し、クラスター内のレプリカ間でデータの整合性を維持します。 分散システムでは、リーダーサーバーが外部クライアントからの書き込みリクエストを処理し、フォロワーサーバーが読み取りと同期を処理します。これにより、2つの課題が生じます。 リーダー サーバーがすべてのフォロワーにデータを更新する方法。 リーダー サーバーに突然障害が発生した場合、クラスターはどうなりますか? したがって、ZAB プロトコルは上記の 2 つの問題を解決するために 2 つの動作モードを設計し、Zookeeper 全体がこれらの 2 つのモードを切り替えます。
4.2 アトミックブロードキャストモード メッセージ ブロードキャスト メカニズムは、次のメカニズムを通じてトランザクションの連続的な一貫性を保証する 2PC プロトコルの簡略化されたバージョンと考えることができます。
4.3 クラッシュリカバリ リーダーがメッセージのブロードキャスト中にクラッシュした場合、データの一貫性は保証されますか?リーダーがクラッシュすると、クラッシュリカバリモードに入ります。これは主に以下の2つのシナリオの処理を伴います。
この問題に対処するために、ZAB は次の 2 つの原則を定義しました。
リーダーによってコミットされたトランザクションを確実にコミットし、スキップされたトランザクションを破棄する方法については、前述の ZXID に頼ることが重要です。 4.4 ZABの特性
信頼性の高い配信: トランザクション A が 1 つのサーバーによってコミットされると、最終的にはすべてのサーバーによってコミットされます。
2 つのトランザクション A と B があるとします。1 つのサーバーが最初に A を実行し、次に B を実行する場合、すべてのサーバーで常に A が B より先に実行されることを保証できますか?
トランザクション A がコミットされた後に送信者が B を送信すると、B は必ず A の後に実行されます。
過半数(正当な数)のノードが起動されている限り、システムは正常に機能します。
ノードがオフラインになった後に再起動する場合、現在実行中のトランザクションから再開できることを確認する必要があります。 4.5 ZABとPaxosの比較 類似点:
違い:
5 ZooKeeperの雑学 5.1 共通コマンド Zookeeper には 3 つのデプロイメント モードがあります。
展開後の一般的なコマンドは次のとおりです。
5.2 Zookeeperクライアント 5.2.1. Zookeeper ネイティブクライアント Zookeeperクライアントは非同期です。処理を進める前に、CountDownLatchを使用して接続が成功していることを確認する必要があります。ネイティブのZookeeper APIはパスの反復的な作成と削除をサポートしていないため、以下の欠点があります。 セッション接続は非同期なので、コールバック関数を使用する必要があります。 ウォッチには繰り返しの登録が必要です。ウォッチセッションごとに 1 回登録します。 セッション再接続メカニズム: セッションが切断された後に再接続する必要がある場合があります。 開発の複雑さは比較的高く、開発プロセスは比較的面倒です。 5.2.2. Zkクライアント ネイティブ API 上に構築されたオープンソースの ZooKeeper クライアントは、次のような最適化が施された、よりユーザーフレンドリーな ZooKeeper クライアントです。 最適化1: セッションの損失または期限切れ時に再接続するための新しいZooKeeperインスタンスを自動的に作成します。最適化2: 使い捨てウォッチャーを永続ウォッチャーとしてラップします。 5.2.3. キュレーター Curatorは、ネイティブAPIを基盤としたオープンソースのZooKeeperクライアントであり、Apacheトップレベルプロジェクトです。Netflixが開発したオープンソースのZooKeeperクライアントフレームワークです。ネイティブZooKeeper APIに精通している人なら、その複雑さは容易に理解できます。Curatorは、再接続、Watcherの繰り返し登録、NodeExistsExceptionの処理といった開発の詳細をカプセル化し、実装するのに役立ちます。現在Apacheトップレベルプロジェクトであり、最も人気のあるZooKeeperクライアントの一つです。 5.2.4. Zookeeper グラフィカルクライアントツール このツールは ZooInspector と呼ばれ、インストール手順は Baidu で見つかります。 5.3 ACLアクセス制御メカニズム ACLはアクセス制御リストの略で、リソースへのアクセス権限を制御するために使用されます。ZooKeeperはACLポリシーを使用して、ノードデータの読み取り/書き込み、ノードの作成、ノードの削除、子ノードリストの読み取り、ノード権限の設定など、ノードへのアクセス権限を制御します。 5.4 Zookeeperの使用に関する注意事項 クラスター内のマシンの数は、必ずしも多ければ多いほど良いというわけではありません。書き込み操作には半数以上のノードからの確認応答が必要となるため、クラスター内のノード数が多いほど、障害に対する信頼性は高まりますが、スループットは低下します。クラスター内のノード数は奇数である必要があります。 ZooKeeper はメモリに基づいて読み取りおよび書き込み操作を実行し、場合によってはメッセージをブロードキャストするため、ノードに大量のデータを保存したりアクセスしたりすることはお勧めしません。 dataDirディレクトリとdataLogDirディレクトリは時間の経過とともに大きくなり、ハードドライブの容量がすぐにいっぱいになってしまう可能性があります。最新のn個のファイルを保持するには、独自のスクリプトを作成するか、組み込みスクリプトを使用することをお勧めします。 デフォルトの最大接続数は 60 です。maxClientCnxns パラメータを設定して、単一のクライアント マシンが作成できる最大接続数を設定します。 |