[分散ロック] 分散整合性アルゴリズム Raft

分散型登録サービスセンター等の代表的なアプリケーション、アーキテクチャ、Raftコンセンサスアルゴリズムの詳細説明

1. 分散型コンセンサスアルゴリズム Raft の概要

1.1 いかだの背景

分散システムでは、コンセンサス アルゴリズムが重要です。すべてのコンセンサス アルゴリズムの中で、Paxos が最も有名です。1990 年に Leslie Lamport によって提案されました。これは、メッセージ パッシング ベースのコンセンサス アルゴリズムであり、同様のアルゴリズムの中で最も効率的であると考えられています。

Paxos アルゴリズムは非常に効果的ですが、その複雑な原理により実装が非常に困難です。これまでのところ、Paxos アルゴリズムを実装するオープン ソース ソフトウェアはほとんどありません。より有名なものには、Chubby や libpaxos などがあります。さらに、Zookeeper で採用されている ZAB (Zookeeper Atomic Broadcast) プロトコルも Paxos アルゴリズムに基づいて実装されていますが、ZAB は Paxos に多くの改良と最適化を加えています。また、両者の設計目標には違いがあります。ZAB プロトコルは主に可用性の高い分散データ マスターおよびバックアップ システムを構築するために使用され、Paxos アルゴリズムは分散整合性ステート マシン システムを構築するために使用されます。

Paxos アルゴリズムはあまりにも複雑で実装が難しいため、その応用が大きく制限されています。分散システムの分野では、効率的で実装が簡単な分散コンセンサス アルゴリズムが緊急に必要とされています。この文脈で、Raft アルゴリズムが登場しました。時間が必要です。

Raft アルゴリズムは、2013 年にスタンフォード大学の Diego Ongaro と John Ousterhout によって「理解可能なコンセンサス アルゴリズムを求めて」として出版されました。Paxos と比較して、Raft は論理的な分離により理解と実装が容易であり、現在、Raft アルゴリズム実装フレームワークは 10 以上の言語で存在しており、より有名なものには etcd と Consul があります。

1.2 ラフトの役割

Raft クラスタには複数のノードが含まれています。Raft はこれらのノードを 3 つの状態 (リーダー、フォロワー、候補) に分割します。各状態は異なるタスクを担当します。通常の状況では、クラスター内のノードにはリーダーとフォロワーの 2 つの状態しかありません。

  • リーダー: ログ同期管理、クライアントからのリクエストの処理、フォロワーとのハートビート連絡の維持を担当します。
  • フォロワー: リーダーのログ同期リクエストに応答し、候補者のチケット招待リクエストに応答し、クライアントからフォロワーにリクエストされたトランザクションをリーダーに転送 (リダイレクト) します。
  • Candidate (候補者) : 選挙の投票を担当します。クラスタが起動したばかりの場合、または Leader がダウンしている場合、Follow ステータスのノードは Candidate に変わり、選挙を開始します。選挙に勝利した後 (半数以上の票を獲得した場合)、 ; ノードの)、ステータスは候補者からリーダーに変わります。

1.3 ラフトの概要

通常、Raft クラスターにはリーダーが 1 つだけ存在し、他のノードはフォロワーになります。フォロワーは受動的です。彼らはリクエストを送信せず、単にリーダーまたは候補者からのリクエストに応答します。リーダーは、すべてのクライアント リクエストを処理する責任があります (クライアントがフォロワーに連絡すると、フォロワーはリクエストをリーダーにリダイレクトします)。ロジックと実装を単純化するために、Raft は一貫性の問題を 3 つの比較的独立したサブ問題に分解します。

  • 選挙 (リーダー選挙) : リーダーがダウンするかクラスターが開始されると、新しいリーダーを選出する必要があります。
  • ログ レプリケーション: リーダーはクライアントからリクエストを受信し、ログ エントリの形式でクラスター内の他のノードにコピーし、他のノードのログが自分のログと強制的に一致するようにします。
  • 安全性: いずれかのサーバー ノードが特定のログ エントリをそのステート マシンに適用した場合、他のサーバー ノードは同じログ インデックス位置に異なる命令を適用できません。

2. Raftアルゴリズムのリーダー選出原理

Raftプロトコルによると、Raftプロトコルを適用したクラスタの初回起動時は、全ノードの状態がFollowerとなっており、Leaderが存在しないため、FollowerはLeaderとのハートビートを維持することができず、FollowerはLeaderだと認識することになります。ダウンしている場合は、候補ステータスに切り替えます。次に、候補者はクラスター内の他のノードに自分自身をリーダーにアップグレードすることに同意するための投票を要求します。候補者が半分以上のノード (N/2 + 1) から投票を受け取った場合、候補者が勝利してリーダーになります。

フェーズ 1: すべてのノードがフォロワーになる

Raft プロトコルによれば、Raft プロトコルを適用したクラスタが起動したばかりのとき (またはリーダーがダウンしたとき)、すべてのノードのステータスは Follower であり、初期 Term は 0 です。同時に選挙タイマーを開始します。各ノードの選挙タイマーのタイムアウトは 100 ~ 500 ミリ秒であり、一貫性がありません (選挙の同時開始を避けるため)。

ここに画像の説明を挿入します

フェーズ 2: フォロワーが候補者になり、投票を開始します。

リーダーが存在しないため、フォロワーはリーダーとのハートビートを維持できません。ノードが起動後、選挙タイマー期間内にハートビートまたは投票リクエストを受信しない場合、状態は候補候補状態に変更され、Term がインクリメントされ、ノードはがクラスターに追加され、すべてのノードが投票リクエストを送信し、選挙タイマーをリセットします。

注: 各ノードの選挙タイマーのタイムアウトは 100 ~ 500 ミリ秒であり、一貫性がないため、すべてのフォロワーが候補者になり、同時に投票リクエストを開始することを回避できます。言い換えれば、最初に候補者になって投票リクエストを開始したノードは、リーダーになるという「先行者利益」を得ることができます。

ここに画像の説明を挿入します

フェーズ 3: 投票戦略

投票リクエストを受信した後、ノードは次の条件に基づいて投票リクエストを受け入れるかどうかを決定します。

  1. 要求元ノードの期間が自身の期間より大きく、他のノードにまだ投票していない場合は、要求を受け入れて投票します。
  2. 要求側ノードの期間が自身の期間より小さく、まだ投票していない場合、要求は拒否され、投票はノード自体に与えられます。

ここに画像の説明を挿入します

第4段階:候補者がリーダーに変わる

選挙ラウンドの後、通常の状況では、候補者はノード (n/2 + 1) の半分以上から票を受け取り、勝利してリーダーにアップグレードされ、定期的に他のノードにハートビートを送信します。他のノードはフォロワーとなり、リーダーと歩調を合わせるようになり、このようにしてこのラウンドの選挙は終了します。

注: 1 回の選挙でノード投票の半分を超える候補者がいない場合、次の選挙が行われる可能性があります。

ここに画像の説明を挿入します

3. Raftアルゴリズムのログ複製原理

Raft クラスターでは、リーダー ノードのみがクライアントのリクエストを処理できます (クライアントのリクエストがフォロワーに送信された場合、フォロワーはリクエストをリーダーにリダイレクトします)。クライアントからの各リクエストには、複製されたノードによって実行される命令が含まれています。ステートマシン。リーダーは、この命令を新しいログ エントリとしてログに追加し、追加のエントリを並行してフォロワーに送信し、フォロワーがログ エントリをコピーできるようにします。このログ エントリがフォロワーによって安全にコピーされると、リーダーはこのログ エントリをそのステート マシンに適用し、実行結果をクライアントに返します。フォロワーがクラッシュしたり動作が遅くなったり、ネットワーク パケットが失われた場合、リーダーは、すべてのフォロワーが最終的にすべてのログ エントリを保存するまで、ログ エントリの追加を繰り返し試みます (クライアントにすでに応答しているにもかかわらず)。これにより、強力な一貫性が確保されます。

フェーズ 1: クライアントのリクエストがリーダーに送信されます

次の図に示すように、リーダーはクライアントのリクエストを受信します。たとえば、データ 5 を保存します。リーダーはリクエストを受信した後、それをログ エントリとしてローカル ログに書き込みます。この時点のエントリのステータスはコミットされておらず、リーダーはローカル データを更新しないため、読み取ることができないことに注意してください。
ここに画像の説明を挿入します

フェーズ 2: リーダーが他のフォロワーにエントリーを送信します

リーダーはフロアワーとのハートビート関係を維持します。ハートビートを使用して、リーダーは追加のエントリ (AppendEntries) を他のフォロワーに並行して送信し、ログ エントリをコピーさせます。このプロセスはレプリケーションと呼ばれます。注意すべき点がいくつかあります。

1. リーダーからフォロワーに送信されるエントリが AppendEntries になるのはなぜですか?

リーダーとフォロワー間のハートビートは周期的であり、リーダーはサイクル中に複数のクライアント要求を受信する可能性があるため、ハートビートとともに複数のエントリ、つまり AppendEntries がフォロワーに送信される可能性が高くなります。もちろん、この例では、リクエストが 1 つだけあると想定しており、当然のことながらエントリは 1 つです。

2. リーダーは、単に追加のエントリ (AppendEntries) をフォロワーに送信するだけではありません。

追加のログ エントリを送信する場合、リーダーには、前のエントリの直後にある新しいログ エントリのインデックス位置 (prevLogIndex) とリーダー ターム番号 (term) が含まれます。フォロワーがログ内で同じインデックス位置と用語番号を含むエントリを見つけることができない場合、この状況はフォロワーとリーダーに一貫性がないことを示すため、新しいログ エントリの受け入れを拒否します。

3. リーダーとフォロワーの不一致の問題を解決するにはどうすればよいですか?

通常の状況では、リーダーとフォロワーのログは一貫しているため、追加されたログの一貫性チェックが失敗することはありません。ただし、リーダーとフォロワーで一連のクラッシュが発生すると、ログが矛盾した状態になります。フォロワーは、新しいリーダーにあるログ エントリの一部を失うか、リーダーにはないログ エントリをいくつか持つか、あるいはその両方を行う可能性があります。欠落しているログ エントリまたは余分なログ エントリが複数の期間にわたって存続する可能性があります。

フォロワーのログとリーダーのログを一致させるには、リーダーは 2 人が合意した最後の場所を見つけて (率直に言うと、2 人の間の最新の合意点を見つけるために後戻りすることを意味します)、それ以降のログ エントリをすべて削除する必要があります。ポイントして独自のログをフォロワーに送信します。これらの操作はすべて、追加されたログの整合性チェックを実行しながら実行されます。

リーダーは、フォロワーごとに nextIndex を維持します。これは、フォロワーに送信する必要がある次のログ エントリのインデックス アドレスを表します。リーダーが最初に権限を獲得すると、すべての nextIndex 値がその最後のログのインデックスに 1 を加えた値に初期化されます。フォロワーのログがリーダーのログと矛盾している場合、次回ログを追加するときに整合性チェックが失敗します。フォロワーによって拒否された後、リーダーはフォロワーに対応する nextIndex 値を減らして再試行します。

最終的に nextIndex はリーダーとフォロワーのログを特定の位置で一致させます。これが発生すると、ログの追加は成功し、競合するフォロワーのログ エントリがすべて削除され、リーダーのログが追加されます。ログが正常に添付されると、フォロワーのログはリーダーのログと一致し、次の期間にわたって維持され続けます。

ここに画像の説明を挿入します

フェーズ 3: リーダーはフォロワーの応答を待ちます

フォロワーがリーダーからコピー要求を受け取った後、考えられる応答は 2 つあります。

  1. ローカル ログに書き込み、成功を返します。
  2. 整合性チェックが失敗し、書き込みが拒否され、false が返されました。理由と解決策は上記で詳しく説明しています。

この時点では、エントリのステータスもコミットされていないことに注意してください。上記の手順を完了すると、フォロワーはリーダーに応答 (成功) を送信します。リーダーがほとんどのフォロワーからの応答を受信すると、最初の段階で書き込まれたエントリを送信済み (コミット済み) としてマークし、このログ エントリをその状態に適用します。機械。

ここに画像の説明を挿入します

フェーズ 4: リーダーがクライアントに対応する

最初の 3 つのフェーズが完了すると、リーダーはクライアントに「OK」と応答し、書き込み操作は成功します。

ここに画像の説明を挿入します

第 5 段階: リーダーがフォロワーにエントリーが送信されたことを通知します。

リーダーがクライアントに応答すると、次のハートビートをフォロワーに通知し、フォロワーが通知を受信した後、エントリを送信済みとしてマークします。この時点で、Raft クラスター内のノードの半分以上が整合性のある状態に達し、強い整合性が確保されています。なお、ネットワーク、性能、障害等の様々な理由により「応答が遅い」「不整合」などの問題を抱えているノードは、最終的にはリーダーと合意に達します。

ここに画像の説明を挿入します

4. Raftアルゴリズムの安全性

前の章では、Raft アルゴリズムがリーダーを選出し、ログを複製する方法について説明しました。ただし、これまでに説明したメカニズムは、各ステート マシンが同じ命令を同じ順序で実行することを完全に保証するものではありません。たとえば、リーダーがいくつかのログ エントリを送信している間、フォロワーが利用できない状態になる可能性があります。その後、フォロワーが回復し (まだリーダーと合意に達していない)、リーダーは失敗します。フォロワーがリーダーとして選出され、ログ エントリが上書きされた場合問題が発生します。異なるステート マシンは異なる命令シーケンスを実行します。

これを考慮して、Raft アルゴリズムを改善するには、リーダー選出中にいくつかの制限を追加する必要があります。これらの制限により、任意のリーダーが、指定されたターム番号 (ターム) について、前のタームの送信されたすべてのログ エントリ (リーダーのいわゆる完全な特性) を確実に保持するようになります。この選挙に関する制限については、以下で詳しく説明します。

4.1 選挙の制限

リーダー メカニズムに基づくすべてのコンセンサス アルゴリズムでは、リーダーは送信されたすべてのログ エントリを保存する必要があります。これを確実にするために、Raft はシンプルだが効果的な方法を使用して、前期に提出されたすべてのログ エントリが選挙中に新しいリーダーに確実に表示されるようにします。言い換えれば、ログ エントリの送信はリーダーからフォロワーへのみの一方向であり、リーダーが自身のローカル ログ内の既存のエントリを上書きすることはありません。

Raft は投票を使用して、候補者にコミットされたログ エントリがすべて含まれていない限り、候補者が選挙に勝つことを防ぎます。選挙に勝つためには、候補者はクラスター内の過半数のノードに接続する必要があります。つまり、送信されたすべてのログ エントリがこれらのサーバー ノードの少なくとも 1 つに存在する必要があります。候補のログが少なくとも大多数のサーバー ノードと同じくらい新しい場合 (この新しい定義については後述します)、コミットされたすべてのログ エントリを保持する必要があります (多数派の考え方)。投票リクエストの制限: リクエストには候補者のログ情報が含まれているため、有権者は独自のログを持たない新しい投票リクエストを拒否します。

Raft は、2 つのログの最後のログ エントリのインデックス値とターム番号を比較して、どちらのログが新しいかを判断します。2 つのログの最後のエントリのターム番号が異なる場合、ターム番号が大きい方のログがより新しいものになります。2 つのログの最後のエントリが同じ用語番号を持つ場合、長いログの方が新しいことになります。

4.2 以前の用語のログエントリをコミットする

セクション 4.1 で紹介したように、リーダーは、大多数のフォロワーにコピーされる限り、今期のログ記録を送信できることを知っています (多数派のアイデア)。ログ エントリをコミットする前にリーダーがクラッシュした場合、後続のリーダーは引き続きログ エントリの複製を試行します。ただし、リーダーは、前の期間のログ エントリがフォロワーの大多数に保存されている場合、そのログ エントリがコミットされたと結論付けることはできません。これは、ログ複製プロセスから明らかです。

上記を考慮すると、Raft アルゴリズムは、レプリカの数を数えることによって前の期間のログ エントリをコミットしません。レプリカの数を数えることによってコミットできるのは、リーダーの現在の期間のログ エントリのみです。この方法で現在の期間のログ エントリがコミットされると、ログ マッチング機能により、以前のすべてのログ エントリも間接的に送信されます。場合によっては、リーダーは古いログ エントリがコミットされたかどうかを安全に知ることができます (エントリがすべてのノードに保存されているかどうかを判断するだけで) が、Raft は問題を単純化するためにより保守的なアプローチを使用します。

リーダーが以前の用語からログをコピーすると、Raft はすべてのログの元の用語番号を保持するため、送信ルールがさらに複雑になります。ただし、この戦略では、時間の経過やログの変更に応じてログの同じ用語番号が維持されるため、ログの識別が容易になります。さらに、この戦略により、新しいリーダーが送信するログ エントリが少なくなります。

著者:Love Little Idiot
リンク:https ://www.jianshu.com/p/8a4dc6d900cf

おすすめ

転載: blog.csdn.net/weixin_52622200/article/details/131723062