序文
Zookeeper は分散調整サービスとして、ネーミング サービス、構成管理、同期など、分散システム用のいくつかの基本サービスを提供し、開発者が分散問題をより簡単に処理できるようにします。
分散システムでは、調整が重要なタスクです。たとえば、独立したプロセスやマシンのグループにどのようなタスクを実行する必要があるかを知らせる方法、そのステータスを他のプロセスやマシンと同期する方法、障害や例外を処理する方法などです。これらの問題はすべて Zookeeper によって解決されます。
この記事では、Zookeeper の内部実装について、そのさまざまなコンポーネントとインターフェイスから始めて、その動作原理と設計思想を分析して深く理解することができます。このソース コード分析を読む過程で、Zookeeper の動作原理と設計思想を深く理解し、分散問題の解決に Zookeeper をより適切に使用できるようになることを願っています。
動物園の飼育員が始まります
どのようなコードを検討する場合でも、全体の構造と操作プロセスをよりよく理解できるように、プログラムのエントリ ポイントから始める必要があります。
スクリプトを通じてzkServer.sh
スタートアップ クラスを確認できますQuorumPeerMain
。
Zookeeper の起動が main メソッドを通じて開始され、最後にrunFromConfig
メソッドが呼び出されて ZooKeeper クラスター ノードをセットアップして起動していることがわかります。
上記のコードはQuorumPeer
、トランザクション ログとスナップショット ディレクトリのパス、選択アルゴリズムの選択、指定されたサーバー ID、定義されたクロック サイクルとデータ保存インスタンス、その他の構成を設定します。さらに、サーバーおよびクライアント接続用のファクトリ クラス (NIO/Netty) が作成されます。最後に、start メソッドを呼び出してサービスを開始します。
ではstart
、主に次の 4 つのタスクが完了します。
- ディスクからメモリにデータをロードして、後続の処理と応答に必要なデータを確保します。
- クライアントのリクエストを処理し、クライアントとの通信と対話を実装するためにソケットを確立します。
- リーダー選出の準備を行い、選出アルゴリズムを決定しました。。
- リーダーの選出を実施し、ノードのステータスを監視してそれに応じて処理し、ノードの障害や異常な状態をタイムリーに検出して処理し、システム全体の信頼性と安定性を確保します。
ディスクデータをロードする
ZooKeeper はメモリ レベルで動作します。信頼性を確保するために、データはトランザクション ログの形式でファイルに保存されるため、データは起動時に最初にメモリにロードされます。
このコードの主な目的は、Zookeeper データベースをディスクからメモリにロードし、関連epoch
情報を確認して処理することです。getDataTree().lastProcessedZxid
このコード行は、ZooKeeper サーバーで処理された最新のトランザクションを取得しますzxid
。ZxidUtils.getEpochFromZxid(lastProcessedZxid)
このコード行は、次zxid
からepoch
。このコード行は、readLongFromFile(CURRENT_EPOCH_FILENAME)
ファイルから現在のepoch
情報を読み取ります。zxid
所属する値がepoch
現在の値より小さい場合epoch
、IOException
例外がスローされます。
クライアントとのコミュニケーションと対話
cnxnFactory
サーバーはクライアント要求を受信して処理するために確立されますSocket
。下の図のコードは でNIOServerCnxnFactory
、別のコードがありますNettyServerCnxnFactory
。このオプションはNIO
引き続きNetty
構成ファイルで設定できます。詳しい方は、NIO
ネットワークプログラミングのコラムをお読みください。Netty
中心となるのはクライアント要求の処理であり、次のプロセッサがあります。
CommitProcessor
これはトランザクション送信プロセッサであり、プロポーザルが送信されるまで、クラスター内のプロポーザルに対する投票を待ちます。SyncRequestProcessor
ローカル ディスクへのトランザクション リクエスト (書き込みリクエスト) の永続化を担当します。AckRequestProcessor
これは、リーダーに固有のプロセッサです。その主な役割は、SyncRequestProcessor
プロセッサがトランザクション ログの記録を完了した後に、プロポーザルの投票コレクターに ACK フィードバックを送信し、現在のサーバーがプロポーザルのトランザクション ログの記録を完了したことを投票コレクターに通知することです。FollowerRequestProcessor
このプロセッサは、クライアントからの読み取り要求と書き込み要求の処理を担当し、書き込み要求をリーダー ノードに転送するなど、処理のために他のプロセッサに転送します。SendAckRequestProcessor
リーダー ノードに確認応答メッセージ (ACK) を送信して、要求が処理されたことをリーダー ノードに通知します。
リーダー選挙の準備
startLeaderElection
主な呼び出しは、createElectionAlgorithm
クラスタ間ネットワーク接続のマネージャを作成しQuorumCnxManager
、選択アルゴリズムを選択することです。これは構成ファイルを通じて構成され、デフォルトは ですFastLeaderElection
。
ノードステータス処理
super.start()
実行クラスQuorumPeer.java
のメソッドはrun()
主にノードのステータスを監視および処理するために使用されます。
Zookeeper の起動時は最初のLooking
状態であり、選出によってサーバーの 1 つがリーダーになり、他のサーバーがフォロワーになります。コードを理解するのが難しい場合は、 ZAB プロトコルを参照してください。
要約する
ソースコードを深く分析することで、そのシンプルさと機能実装の巧妙な設計に気づきました。コードで処理される機能は非常に複雑ですが、構成とコーディング スタイルが単純であるため、非常に読みやすく、理解しやすくなっています。ネットワーク プログラミングの広範な使用、接続のセキュリティと最適化の慎重な扱いには特に注意が払われています。また、ZAB プロトコルが分散一貫性の問題をどのように巧みに解決しているかについても説明されており、これらの繊細な設計概念は間違いなく分散システムの開発に貴重な参考資料を提供します。今後の作業でこれらのアイデアをコードに統合することを楽しみにしています。