MIT 6.824 講義 6:Raftとフォールトトレランス、パート 1
このページのタイトル、字幕、要約、読書メモは保存済みの AI 翻訳です。誤りが含まれる場合があります。タイムスタンプは原文と同じです。原文の字幕を開き、元の動画と照合できます。
MIT 6.824のRaftについて、パート 1:初期のシステムが単一マスターに依存する理由、多数決がスプリットブレインを防ぐ仕組み、およびターム、選挙、ログがどのように機能するか。
文字起こしの出典:Vidleafによる自動音声認識(誤りを含む可能性があります)。AIによる句読点はVidleafが追加しました。元の文言とタイムスタンプのアンカーは保持されています。元の文字起こしは以下でご覧いただけます。
AI生成の要約
この講義ではRaftとシングルマスターパターンを紹介します。これは部分的にラボをサポートするためであり、正しい状態機械複製のケーススタディとしてでもあります。MapReduce、GFS、VMware FTはすべて、プライマリを決定するために単一のエンティティに依存しており、それは自分自身と矛盾することはできませんが、それ自体が単一障害点であるため、中心的な問題はスプリットブレインを避けることであると指摘します。複製されたテストアンドセットサーバーはその難しさを示します。クライアントが両方のレプリカと通信することを要求するのはフォールトトレラントではなく、一方のみと通信するとネットワーク分断により二人のクライアントが両方ともロックを保持していると信じる可能性があります。代わりに自動フェイルオーバーは多数決を使用し、進行には全サーバーの過半数が必要であるため、最大で一つのパーティションのみが進行でき、2f+1台のサーバーでf個の障害を許容します。多数決の重複はRaftが正しい大きな理由の一部です。講義ではPaxosとビュースタンプ複製(VSR)を初期のコンセンサスシステムとして称賛し、Raftの設計はVSRに近いと述べ、Raftをサービスアプリケーションに含まれるライブラリとして説明します。アプリケーションコードはログを保持するRaft層の上にあり、同一構造の三つのレプリカがあり、外部クライアントはputやgetなどのリクエストを現在のリーダーのアプリケーション層に送信します。次に、リクエストがレプリカの過半数がログに持つまで複製され、その後リーダーがそれを実行して応答し、リーダーは次のappend entries RPCにコミットインデックスを相乗りさせる方法を説明します。Raftがログを保持する理由、フロー制御のギャップ、クラッシュリカバリ、applyチャネルインターフェース、任期番号と任期ごとに最大一人のリーダーを持つリーダー選出、分裂投票とタイマーのランダム化、リーダーが厄介な瞬間にクラッシュするエッジケースをカバーし、コミットされていない可能性のあるエントリはコミットされたものとして扱わなければならないことを含みます。
文字起こしから生成されました。リンクされた箇所を元の動画と照合して確認してください。
タイムスタンプ付きの章の要約
Raftと単一マスターパターン
- [0:07] 今日と明日のトピックはRaftで、部分的にはラボの実装を助けるため、またステートマシンレプリケーションを正しく行うためのケーススタディとしてです。
- [0:25] これまでに見てきたフォールトトレランスシステムは共通のパターンを共有しています。MapReduceは計算をレプリケートしますが、計算全体は単一のマスターによって制御されます。
- [0:49] GFSはプライマリバックアップ方式でデータをレプリケートしますが、すべてのデータ片に対してプライマリを選択するために単一のマスターに依存しています。
- [1:06] VMware FTはプライマリとバックアップの仮想マシンで計算を複製しますが、障害時に正確に一つが引き継ぐことを保証するために単一のテストアンドセットサーバーに依存しています。
- [1:27] 三つのケースすべてで、単一のエンティティが隅に隠れて、誰がプライマリであるかの重要な決定を行います。
- [1:46] 単一のエンティティがプライマリを決定することの良い点は、自分自身と矛盾できないことですが、悪い点はそれ自体が単一障害点であることです。
- [2:23] 全体のポイントはスプリットブレインを回避する方法であり、そのため障害後に誰がプライマリになるべきかを決定するには細心の注意が必要です。
レプリケートされたtest-and-setのスプリットブレイン
- [2:50] レプリケートされたtest-and-setサーバーは、スプリットブレインを正しく実装するのがなぜ難しいかの例として使用され、VMware FTがプライマリを選択するためにtest-and-setサーバーに依存していることに動機付けられています。
- [3:34] 両方のレプリカは状態ゼロから開始し、唯一のクライアント操作はtest-and-setであり、これは両方のコピーを一に設定して古い値を返し、簡略化されたロックサーバーとして機能します。
- [4:04] スプリットブレインは、クライアントが一方のサーバーと通信できるが他方とは通信できないときに発生するため、サーバーが応答しないように見えるときにシステムはどのように反応するかを決定しなければなりません。
- [4:47] クライアントがあらゆる操作に対して両方のレプリカと通信することを要求すると、不整合は回避されますが、両方のサーバーが稼働している必要があるため、まったくフォールトトレラントではありません。
- [5:53] クライアントが到達できるサーバーとだけ通信させるのも間違いです。なぜなら、到達できないサーバーもネットワークの問題によって実際には生きている可能性があるからです。
- [6:19] ネットワークケーブルの断線によってネットワークが二つに分断された場合、クライアント一はサーバ一には到達できるがサーバ二には到達できず、一方別のクライアントはサーバ二には到達できるがサーバ一には到達できない。
- [6:49] 「一つのサーバとだけ通信する」ルールの下では、クライアント一のテスト・アンド・セットはサーバ一を一に設定してゼロを返すので、クライアント一は自分がロックを取得したと考え、そのサーバが VMware FT のプライマリになり得ると考えるが、もう一方のレプリカは依然としてゼロを保持している。
- [7:07] 次にクライアント二もサーバ二を介してロックを取得するので、両方の VMware マシンがもう一方のサーバに問い合わせることなく自分をプライマリと見なし得る。これは完全な故障である。
二サーバのトレードオフとスプリットブレイン
初期のレプリケーションとスプリットブレインの回避
- [8:15] 電話交換機や銀行のコンピューターの運用者たちは、信頼性の高いサービスを実現するためにレプリケーションシステムへ多額の費用を費やすことを厭いませんでした。
- [8:34] 彼らはスプリットブレインを排除しつつレプリケーションを実現するために、いくつかの技法を用いました。
- [8:40] その一つは、故障しないネットワークを構築することでした。例えば、ラップトップ内部でCPUとDRAMを接続する配線のようなものです。
- [9:03] 妥当な前提、多額の費用、そして注意深く制御された物理的環境があれば、故障しないネットワークによってスプリットブレインを排除できます。
- [9:24] ネットワークが故障し得ないのであれば、クライアントがサーバ二と通信できないということは、サーバ二がダウンしているに違いないということを意味する。
- [9:42] もう一つの可能性は、人間が問題を解決することでした。クライアントはデフォルトで両方のレプリカの応答を待つのです。
- [9:57] 人間がマシンルームに呼び出され、一方のレプリカをオフにするか、一方がクラッシュして他方が生きていることを確認することで、タイブレーカーの役割を果たすことができました。
- [10:24] 人々は長い間、これらの方式のいずれかを用いてきました。人間はあまり素早く応答できず、故障しないネットワークは高価ですが実現可能です。
多数決投票とクォーラムシステム
- [10:41] 自動フェイルオーバーシステムは、故障や分断が起こり得る不安定なネットワークに直面しても正しく動作することができます。
- [11:03] スプリットブレインを回避する自動レプリケーションシステムを構築するための鍵となる洞察は、多数決投票という考え方です。
- [11:29] 最初のステップは奇数台のサーバーを使うことです。なぜなら、偶数での分割は対称的すぎて、両側が同じ行動をとってしまうからです。
- [12:06] Raftでは、何らかの進展(リーダーの選出やログエントリのコミット)には、全サーバーの半数を超える多数派を集める必要があります。
- [12:41] これが機能するのは、多数派を含むことができるパーティションは最大でも一つだけであり、もう一方のパーティションは進展できないからです。
- [13:08] 多数派は常に、稼働中のサーバーだけでなく全サーバーを基準に数えられます。
- [13:53] 2f+1 台のサーバがあれば、システムは f 個の故障に耐えられる。三台のサーバなら一つの故障に耐えられる。
- [14:20] これらはしばしばクォーラムシステムと呼ばれます。必要な多数派がクォーラムと呼ばれることがあるからです。
- [15:04] 任意の二つの多数派は少なくとも一つのサーバーで重なり合い、Raftはこの重なりに依拠してスプリットブレインを回避します。
多数派の重なりがWrappedの正しさを保証する
サーバーの追加と初期のコンセンサスシステム
- [16:30] サーバの集合を追加したり変更したりすることは可能であり、おそらく第六節で扱う。
- [16:43] 長期稼働するシステムでは、恒久的な故障、アップグレード、マシンルームの移転などのために、しばらくするとサーバーの交換が必要になります。
- [17:00] サーバー集合の変更は毎日行われるものではありませんが、長期的な保守性にとって極めて重要です。
- [17:07] Raftの著者たちは、これに対処する方式を自らの功績としていますが、それは複雑です。
- [17:21] 1990 年頃、スプリットブレインを回避するために、二台ではなく三台のサーバで多数決投票を用いる二つのシステムが提案された。
- [17:45] 初期のシステムの一つはPaxosと呼ばれ、Raftの論文で多く論じられています。
- [17:53] もう一つの初期のシステムは、MITの人々によって発明されたビュースタンプレプリケーション(VSR)でした。Raftの設計はPaxosよりもVSRに近いものです。
- [18:16] これらのシステムには数十年の歴史がありますが、実際に展開された大規模分散システムの最前線に登場したのは約15年前のことです。
ライブラリとしてのRaft
Raftレプリケーションサービスのアーキテクチャ
- [18:50] レプリケーションサービスは、RPCを受け取るアプリケーションコードとRaftライブラリから成り、Raftライブラリ同士が協調してレプリケーションを維持します。
- [19:11] 単一のRaftレプリカは、上部にアプリケーションコード(例えばキーバリューサーバー)を持ち、Raftが管理を助けるレプリケーション状態(例えばキーと値のテーブルなど)を持ちます。
- [19:38] アプリケーションの下にはRaft層があり、キーバリューサーバーはRaftへ関数呼び出しを行い、Raftは状態、最も重要なものとして操作のログを保持します。
- [20:06] 三つのレプリカを持つシステムでは、同一の構造を持ち、うまくいけば両方の層で同じデータを持つ三台のサーバが存在する。
- [20:33] クライアントは、現在のリーダーのアプリケーション層にリクエストを送信する外部コードであり、クライアントは複製されたサービスと通信していることを意識する必要がないことが望まれます。
- [21:13] キーバリューサーバーに対するアプリケーションレベルのリクエストには、put(キーと値を取り、テーブルを更新する)やget(キーの現在の値を返す)があります。
- [21:55] Raftで複製されたサービスでは、アプリケーション層はリクエストを実行せず、クライアントのリクエストをRaft層に渡して複製ログにコミットさせます。
- [22:16] Raftは、過半数のレプリカがその操作をログに持つまで操作を複製し、その後リーダーに通知し、リーダーが操作を実行してクライアントに応答します。
- [23:36] コミットには全レプリカではなく過半数が必要とされるため、一部のサーバーが故障しても耐障害システムは処理を進めることができます。
- [24:10] 操作がコミットされると、各レプリカのRaftライブラリはそれをローカルのアプリケーション層に渡し、アプリケーション層が自身の状態に適用するため、すべてのレプリカが同じ操作のストリームを目にします。
Raftの通常動作とコミットの伝播
- [24:33] 同じ順序で適用される決定的な操作により、複製された状態はすべてのレプリカで同一に進化します。
- [25:09] 時間図は、クライアントがリーダー(サーバ一)にリクエストを送り、リーダーが二つのレプリカに append entries RPC を送る様子を示している。
- [25:55] リーダーは自分自身を含む多数派からの肯定的な応答を待つ。三つのレプリカがあれば、他のレプリカ一つからの応答だけでよい。
- [26:14] 過半数を集めた後、リーダーはコマンドを実行し、応答をクライアントに返送します。
- [27:04] サーバ二は、その応答がネットワークによって失われた可能性があるため、リクエストがコミットされたことを知らない。
- [27:26] リーダーはリクエストがコミットされたことを知ると、他のレプリカに伝えなければなりません。Raftでは、これは明示的なコミットメッセージではなく、次のappend entries RPCにleader commitフィールドとして相乗りさせて行われます。
- [29:14] リーダーが更新されたコミットインデックスをいつ送信するかは実装者が決めます。リクエストがまれな場合はハートビートや特別なappend entries、リクエストが頻繁な場合は相乗りです。
- [29:56] レプリカがリクエストを実行する時刻は、少なくとも障害がなければ誰もそれを待っていないため、それほど重要ではありません。
レプリカの実行はクリティカルパス上にない
Raftがログを保持する理由とそのフロー制御のギャップ
- [30:43] なぜシステムがこれほどログに焦点を当てているのか、ログが何をしているのかを明示的に問いかけてください。
- [31:03] ログは、リーダーが操作を順序付ける仕組みであり、複製されたステートマシンにとって不可欠です。
- [31:07] レプリカは、同じクライアント操作だけでなく、同じ操作を同じ順序で適用しなければなりません。
- [31:41] ログ内の番号付きスロットは、リーダーが選択した順序を表現する方法の一部です。
- [32:06] フォロワーでは、ログはまだコミットされたことが知られていない操作が保留される場所であり、それらは破棄しなければならない場合があります。
- [32:32] リーダーは、メッセージを逃したフォロワーに再送信する必要があるかもしれないため、操作を自身のログに保持します。
- [33:28] 再起動したサーバーは、ディスクに永続化されたログを再生して、クラッシュした時点の状態を再構築するため、ログは永続化計画の一部です。
- [34:41] フォロワーはコマンドを実行する前に確認応答するため、その確認応答レートは実行レートによって制限されません。
- [34:56] フォロワーが実行よりも速く確認応答すると、無制限のログが蓄積され、最終的にメモリを使い果たします。
- [35:26] Raftには、これに対処するために必要なフロー制御がありません。
- [35:44] 本番システムでは、実行の進捗を報告する追加のメッセージが必要になる場合があり、リーダーが先を行き過ぎた場合にスロットリングできるようにします。
Raftにおけるクラッシュリカバリとログのコミット
- [36:37] クラッシュしたサーバは、図 2 のルールの一つに従って、自身のログをディスクに永続化している。
- [36:46] 再起動後、サーバーはログの実行がどこまで進んだかを知りません。
- [36:54] 図2の規則により、最初の再起動時には、ログのどこまでがコミットされているかさえ知りません。
- [37:03] 再起動してログを読んだ直後、サーバーはシステムがどこまでコミットしたかを知らないため、ログに対して何も行うことは許されません。
- [37:36] すべてのサーバーがクラッシュした場合、それらが持つのは図2で非揮発性とマークされた状態だけであり、これにはログとおそらく最新のタームが含まれます。
- [37:56] それらはリーダー選出を実行し、一つがリーダーに選ばれ、リーダーは最初のハートビートを送る副産物として状態を把握する。
リーダーのコミットポイントとログ複製
- [38:26] 過半数のレプリカが自身のログに合意することがコミットポイントです。
- [38:33] append entriesメカニズムを通じてリーダーが選ばれると、リーダーは他のすべてのレプリカに自身と同一のログを持たせます。
- [38:45] リーダーはすべてのレプリカが自身と同一のログを持つことを知っているため、過半数がそれらのエントリを保持しているはずであり、したがってそれらもコミットされているはずです。
- [39:13] 図二のリーダーの append entries のコードは、リーダーのコミットポイントを増加させる。
- [39:18] その後、全員がログ全体を最初から実行し、おそらく極めて骨の折れる作業で、状態をゼロから再構築できます。
- [39:30] ゼロから再実行することはあまり魅力的ではありませんが、基本的なプロトコルはそうしています。
効率的なバージョンとインターフェースの予告
Raftとキーバリューレイヤーのインターフェース
- [40:14] 各レプリカ上には、キーバリュー層と Raft 層の間のインターフェースとして主に二つの部分がある。
- [40:22] キーバリューレイヤーはstart関数を介してクライアントのリクエストをRaftに中継し、そのリクエストをログに組み込むよう要求します。
- [40:36] raft.go の start 関数は一つの引数、すなわちクライアントのコマンドを取り、それがコミットされたときにキーバリュー層に伝える。
- [40:53] Raftは、以前にstartコマンドで送信された操作がコミットされたことをキーバリューレイヤーに通知します。これは最新のstartではない可能性があります。
- [41:02] 百個のクライアントコマンドが到着し、それらのいずれかがコミットされる前に start の呼び出しを引き起こす可能性がある。
- [41:13] 上方向の通信は、Raftライブラリが送信しキーバリューレイヤーが読み取るGoチャネル上のメッセージという形を取ります。
- [41:27] applyチャネルはapplyメッセージを運び、キーバリューレイヤーはそれらを自身のstartの呼び出しと対応付けなければなりません。
- [41:48] startコマンドは、コミットされる場合にはそのコマンドがコミットされるログ内のインデックス(コミットされない可能性もあります)と、現在のtermを返します。
- [42:13] applyメッセージにはコマンドとインデックスが含まれ、すべてのレプリカがそれを受信してローカル状態にコマンドを適用します。
- [42:36] インデックスは実際にはリーダー上でのみ有用であり、リーダーはどのクライアントリクエストが話題になっているのかを把握できます。
レプリケートされたキーバリューRPCにおけるクライアント応答のタイミング
- [43:14] クライアントはリクエスト(putまたはget)を送信し、応答を待ちます。
- [43:31] リーダーは、コマンドがコミットされたことを知った後にのみ応答を送信します。
- [43:55] ソフトウェアスタックでは、キーバリューレイヤーがstart関数を呼び出し、それがキーバリューレイヤーに戻ります。
- [44:05] キーバリューレイヤーは、リクエストがコミットされるかどうかを知らないため、まだクライアントに応答しません。
- [44:18] startが戻った直後、applyメッセージを送信する前にキーバリューレイヤーがクラッシュした場合、リクエストはコミットされない可能性があります。
- [44:38] キーバリューサーバーは、対応するapplyメッセージがapplyチャネルに現れたときにのみリクエストを実行し、その後応答を送信します。
- [45:01] これは主に障害時に重要です。障害が発生したとき、クライアントが何を見たかが極めて重要になります。
Raftログの発散と収束
Raftのリーダー選出の基本
- [46:27] Raft には二つの大きな話題がある。リーダー選出(ラボ 2)と、特に故障後のレプリカのログをリーダーがどのように扱うかである。
- [46:50] リーダーは厳密には必要ではありません。リーダーレスのクラスタでもログの順序について合意でき、元々のPaxosにはリーダーがありませんでした。
- [47:17] Raft がリーダーを用いるのは主に、サーバが故障しない一般的な場合の効率のためであり、リクエストごとに一ラウンドのメッセージで合意を可能にする。
- [47:49] リーダーを用いることで、おそらくシステムは二倍高速になり、推論が容易になる。
- [48:07] Raftはリーダーを区別するためにterm番号を使用します。フォロワーは現在のterm番号だけを必要とし、リーダーの身元は必要としません。
- [48:20] 重要な性質:各任期には最大で一つのリーダーしか存在しない。存在しないことはあっても、同じ任期内に二つ存在することは決してない。
- [48:45] 各サーバーは選出タイマーを保持しており、現在のリーダーから連絡がないままタイマーが切れると、サーバーはリーダーが死んだとみなして選出を開始します。
- [49:31] 選出を開始するとは、termをインクリメントしてrequest-vote RPCを送信することを意味し、候補者は自分自身に投票します(n-1件のリクエスト)。
- [50:16] リーダーの故障がなくても、例えばネットワークの遅延やハートビートの欠落によって選出が発生する可能性があるため、正確性はこれを考慮しなければなりません。
- [50:46] 新しい選出の後でも、例えば少数派の分断において、古いリーダーが依然として自分がリーダーだと思っている可能性があるため、その振る舞いを扱わなければなりません。
Raftにおける一方向のネットワーク障害
- [51:53] 一方向のネットワーク通信が進行を妨げる病的なケースが起こり得ます。
- [51:55] リーダーの送信ハートビートは機能するがクライアントリクエストを受信できない場合、そのハートビートが他のサーバーによる選出の開始を抑制します。
- [52:20] 壊れた受信ネットワークにより、リーダーはクライアントコマンドを聞いて実行することができません。
- [52:28] Raftは、起こり得るあらゆる異常なネットワーク問題に対して耐性があるわけではありません。
- [52:37] 発表者は、自身が考えたケースは修正可能だと信じています。
- [52:45] 一つの修正方法は、フォロワーがハートビートに応答する双方向ハートビートを要求することである。
- [52:58] リーダーがハートビートの応答を見なくなった場合、一定時間後にリーダーは退任を決断します。
Raftの多数決によるリーダー選出
- [53:32] Raft は任期ごとに最大で一つのリーダーを保証しなければならない。
- [53:38] あるtermで当選するには、候補者はサーバーの過半数からの賛成票を必要とします。
- [53:45] 各サーバは任期ごとに一つの賛成票しか投じないので、二人の候補者がともに多数派を得ることはできない。
- [54:08] 多数決ルールにより、任期ごとに当選する候補者は最大で一人となる。
- [54:26] 多数決のルールにより、少数のサーバーがクラッシュしたり利用不能であっても、リーダーは選出され得ます。
- [54:34] 半数を超えるサーバーがクラッシュした場合、利用不能な場合、または別の分断にいる場合、システムは再試行を続け、リーダーを決して選出しません。
- [54:54] 選挙が成功すれば、誰もがそれを知ることができれば素晴らしいでしょう。
Raftサーバーが選挙結果をどのように知るか
- [55:00] すべての当事者は、選挙で何が起こったかを知る方法を必要とします。
- [55:16] 当選した候補者は、自分が過半数の票を獲得したことを直接知っていますが、他の誰も、誰が当選したか、あるいは誰かが当選したかどうかを直接知りません。
- [55:28] 候補者は、ハートビートAppendEntriesを介して他のサーバーに通知します。これは、選挙に勝利した直後に図2が要求するものです。
- [55:41] ハートビートは、誰が当選したか、どの任期かを明示的に示しません。信号は微妙です。
- [55:56] 任期のリーダーだけがAppendEntriesを送信できるため、任期19のAppendEntriesを受信すると、サーバーは誰かがその選挙に勝ったことを知りますが、誰が勝ったかはわかりません。
- [56:21] AppendEntriesはまた、全員の選挙タイマーをリセットし、リーダーが期待されるレートでハートビートを送信する限り、新しい立候補を抑制します。
- [56:51] ネットワークが失敗したりパケットがドロップされたりすると、それでも選挙が発生する可能性がありますが、すべてがうまくいけば選挙は起こりにくいです。
- [57:03] この方式は一つの任期に二人のリーダーを選出することはできないが、一つの任期にゼロ人のリーダーを選出することはあり得る。主に、あまりに多くのサーバが停止している、利用できない、またはネットワーク接続が不良であるために多数派を構成できない場合である。
Raftの選挙タイムアウトと票の分割
- [57:23] パケット損失がなくても、二人以上の候補者がほぼ同時にタイムアウトして票が割れると、選出は失敗し得る。
- [57:44] 三つのレプリカを持つシステムで、すべての選出タイマーが同時に発火すると、各サーバは自分自身に投票し、誰も多数派を得られない。
- [58:09] 選挙タイマーはAppendEntriesによってのみリセットされるため、リーダーがいないと再び発火し、票の分割を繰り返す可能性があります。
- [58:31] Raftは選挙タイマーをランダム化することで、票の分割を不可能ではないにしても起こりにくくします。
- [59:43] サーバが異なるランダムな時間を選ぶと、一つのタイマーが最初に発火し、その間隔が十分に大きければ、次のタイマーが発火する前に投票要求の完全なラウンドを送ることができる。
- [1:00:23] ランダム化により候補者の同期が解除されます。
- [1:00:41] 選出タイマーは、予想されるハートビート間隔以上でなければならない。パケットが落ちる可能性がある場合、最小値はハートビート間隔の数倍にすべきであり、例えば100 msのハートビートに対して300 msである。
- [1:02:00] 最大ランダムタイムアウトは、最初の選挙タイマーが発火するまでリーダーがいない状態でシステムが凍結するため、システムが障害から回復する速さに影響します。
選挙タイムアウトの調整とランダム化
- [1:02:36] 必要なパフォーマンスレベルと予想される障害頻度が、タイムアウト設定の重要性を決定します。
- [1:02:43] 故障が年に一度しか起きないのであれば、それほど問題にならないかもしれない。故障が頻繁であれば、大いに問題となる。
- [1:02:50] 回復時間も考慮事項です。
- [1:03:04] 最初のタイマーと二番目のタイマーが発火する間隔は、候補者が全員から票を集めるのに要する時間より長くなければならない。
- [1:03:12] そのギャップは、RPCの予想往復時間を超える必要があり、それは約10ミリ秒かもしれません。
- [1:03:25] 最大タイムアウトは、最小の乱数と次に小さい乱数の差が10ミリ秒である可能性がかなり高くなるように十分長くする必要があります。
- [1:03:53] テストコードは、リーダーの障害が数秒以内に回復しないと不機嫌になるので、リーダー選挙が数秒以内に完了する可能性が高くなるように最大値を調整する必要があります。
- [1:04:20] 選挙タイマーがリセットされるたびに新しいランダムタイムアウトを選択する必要があり、サーバー作成時に選択したものを再利用してはいけません。
- [1:04:39] 同じ乱数を再利用すると、二つのサーバが同じ値を選んでしまい、スプリット投票を何度も永久に引き起こす危険がある。
少数派パーティションの旧リーダー
- [1:05:02] 最後のリーダー選挙の問題:旧リーダーが少数のサーバーと数人のクライアントと共にパーティション化され、多数派が新しいリーダーを選出します。
- [1:06:08] 問題ではない点:多数派のない別のパーティションのリーダーはAppendEntriesを送信しますが、多数派から応答を得られないため、操作をコミットしたり実行したりすることはありません。
- [1:06:47] クライアントは古いサーバーにリクエストを送信するかもしれませんが、応答を決して受け取らないため、何も実行したと誤解されるクライアントはいません。
- [1:07:00] より微妙な問題:サーバーが一部のサーバーにAppendEntriesを送信し、コミット決定を行う前にクラッシュする可能性があります。
- [1:07:24] その問題について議論するにはおそらく約45分かかるでしょう。
リーダークラッシュ後のログの分岐
- [1:07:47] 新しく選出されたリーダーは、前のリーダーがクラッシュした後、一貫した状態を回復するために、レプリカ間で分岐したログを調整する必要があるかもしれません。
- [1:08:16] このトピックは主にサーバーがクラッシュした後に関心があります。サーバーが稼働していて多数派がいる間は、フォロワーはリーダーのログを受け入れなければならず、ほとんど問題は起こりません。
- [1:08:50] 問題は、旧リーダーがメッセージの送信中にクラッシュした場合、または新しいリーダーが選挙直後に何か有用なことをする前にクラッシュした場合に発生します。
- [1:09:48] 図では、ログエントリはクライアント操作ではなく任期番号として書かれ、スロットごとに整列されています。
- [1:10:03] この例では、三台のサーバすべてがスロット一に任期三のエントリを持つが、スロット二に任期三のエントリを持つのはサーバ 2 と 3 だけで、サーバ 1 にはそこに何もない。
- [1:11:03] これは、サーバ 3 が任期三でリーダーであり、全員にコマンドを送り、その後二番目のリクエストを受け取って三台すべてに送ったが、サーバ 1 へのメッセージが失われたかサーバ 1 がダウンしていた場合に生じ得る。
- [1:11:53] サーバー3がクラッシュし、別のリーダーが選ばれた場合、新しいリーダーはコミットされた可能性のあるコマンドを破棄してはならず、サーバー1に他のサーバーが持っていたのと同じコマンドで空白を埋めさせる必要があります。
Raftログ構成の実現可能性
- [1:12:28] メッセージが送信される前にクラッシュが発生したため、新しいリーダー選挙が行われる可能性があります。
- [1:12:43] ログ内のスロットには番号が振られており、10、11、12、13 はそれらを指すために用いられる。
- [1:13:03] スロット 12 では、サーバ 2 は任期四のコマンドを持ち、サーバ 3 は任期五のコマンドを持つ。
- [1:13:17] サーバが何をするかを分析する前に、そのような構成がそもそも発生し得るかどうかを問わなければならない。
- [1:13:25] 答えが「その構成は発生し得ない」であることもあり、その場合には心配する必要はない。
- [1:15:00] この構成は次のように生じ得る:サーバ 2 が任期四のリーダーに選出され、クライアントのリクエストを追加し、そしてクラッシュする。
- [1:15:25] その後サーバ 3 は任期五で選出され得る。なぜなら多数派、すなわちサーバ 1 とサーバ 3 からの投票要求応答だけでよく、それらのログは競合しないからである。
- [1:15:41] 次にサーバ 3 はクライアント要求を受け取り、それを自身のログに追加し、クラッシュする。これによりこの構成が生じる。
- [1:16:03] Raft がそのようなシナリオを処理しなければならないのか、それとも発生し得ないのかを判断するには、このようなシナリオを検討する必要がある。
Raft の許容可能な結果
- [1:16:26] Raft が妥当な動作をすることを確信したい。
- [1:16:42] Raft が何をするかを議論する前に、何が許容可能な結果であるかを把握する必要がある。
- [1:16:53] スロット 10 のコマンドはすべてのレプリカに知られているため、コミットされていた可能性があり、破棄することはできない。
- [1:17:01] スロット 11 のコマンドはレプリカの過半数に存在するため、コミットされていた可能性があり、破棄することはできない。
- [1:17:09] スロット 12 のコマンドはコミットされていた可能性がまったくないため、Raft は両方を破棄する権利がある。
- [1:17:27] スロット 12 のコマンドのいずれかを破棄することは許容される破棄であり、必須の破棄ではない。
Raft のログコミットの不確実性
- [1:17:31] 最終的なログの内容は同一でなければならないため、少なくとも一つのログエントリは破棄されなければならない。
- [1:17:47] ログだけからは、リーダーがクラッシュする前にどこまで進んだかを正確に知ることはできない。
- [1:17:58] 一つの可能性は、リーダーが新しいコマンドを含む追加メッセージを送信し、直ちにクラッシュして応答をまったく受け取らなかったというものである。
- [1:18:13] 応答がなければ、リーダーはコマンドを実行しておらず、増加したコミットインデックスも送信していないため、レプリカもそれを実行していない可能性がある。
- [1:18:28] そのエントリがコミットされていなかった可能性はあるが、Raft はそうでなかったことを証明できないため、コミット済みとして扱わなければならない。
- [1:18:57] リーダーは追加エントリの応答を受け取り、クラッシュする前にクライアントに応答した可能性があるため、そのエントリがコミットされていないとは断定できない。
- [1:19:07] ログを見る限り、どちらの可能性も排除できないため、そのエントリはコミット済みと仮定しなければならない。
簡単な継続の合図
[0:01] では、始めましょう。うん。今日、そして実際に今日と明日は、Raft について話します。ええと、ラボの実装に役立つことを願っているからでもあります。そして、単に状態機械レプリケーションを正しく実現する方法の詳細に関するケーススタディだからでもあります。問題の導入として、これまで見てきた耐障害性システムにはパターンがあることにお気づきかもしれません。
[0:35] ええと、一つは MapReduce が計算をレプリケートするが、そのレプリケーションは制御されており、計算全体が単一のマスターによって制御されるということです。ええと、もう一つ注目していただきたい例は、GFS がデータをレプリケートする、つまりファイルの実際の内容をレプリケートするためのプライマリ・バックアップ方式ですが、データの各部分について誰がプライマリであるかを選ぶために単一のマスターに依存しているということです。もう一つの例として、VMware FT はプライマリ仮想マシンとバックアップ仮想マシン上で計算をレプリケートします。しかし、次に何をすべきかを判断するために、どちらかが故障したように見える場合、単一のテスト・アンド・セット・サーバに依存しています。
[1:20] 何らかの障害が発生した場合に、プライマリかバックアップのどちらか一方だけが確実に引き継ぐように、選択を助け、保証するためです。したがって、これら三つのケースすべてにおいて、確かにレプリケーションシステムは存在しましたが、レプリケーションシステムの片隅に隠れる形で、単一のエンティティが重要な決定を下すことを要求する仕組みがありました。私たちが関心を持つケースでは、誰がプライマリであるかという決定です。では、最初のものから始めます。単一のエンティティが誰がプライマリになるかを決めることの非常に良い点は何でしょうか?
[1:52] それは自分自身と意見が食い違うことがないということです。それが一つしか存在せず、何らかの決定を下せば、それが下された決定です。ええと、しかし単一のエンティティが誰がプライマリであるかなどを決めることの悪い点は、それ自体が単一障害点になるということです。したがって、これまで見てきたこれらのシステムは、耐障害性機構の本当の中核を小さな片隅に押しやっていると見ることができます。つまり、障害が発生した場合に誰がプライマリになるかを決める単一のエンティティです。さて、このすべてはスプリットブレインを回避する方法に関するものです。障害が発生した場合に誰がプライマリであるべきかという決定を極めて慎重に行わなければならない理由は、そうでなければスプリットブレインの危険があるからです。
[2:35] ええと、そしてただ…この点を非常に明確にするために、思い出していただきます。問題は何であり、なぜそれが深刻な問題なのかを。たとえば、ええと、レプリケートされたテスト・アンド・セット・サーバを構築したいとします。つまり、VMware FT がプライマリを選ぶためにこのテスト・アンド・セット・サーバに依存していることを心配しているので、レプリケートされたテスト・アンド・セット・サーバを構築しましょう。そして、これをやりますが、それは壊れたものであり、スプリットブレイン問題を正しく扱うことがなぜ難しいかの単なる例示です。では、ネットワークがあり、おそらく二つのサーバがあり、それらはテスト・アンド・セット・サービスのレプリカであるはずで、接続されており、ええと、おそらく二つのクライアントが今誰がプライマリであるかを知る必要があると想像しましょう。あるいは、実際には、この場合のこれらのクライアントはプライマリとバックアップかもしれません。
[3:30] ええと、VMware FTで。つまり、これがテスト・アンド・セット・サービスだとすると、これらのデータベース、これらのサーバーは両方とも、このテスト・アンド・フライト・バッグの状態がゼロである状態から始まります。クライアントが送信できる唯一の操作はテスト・アンド・セット操作で、これはレプリケートされたサービスの値を一に設定することになっています。つまり、両方のコピーを設定するはずです。そして古い値を返します。つまり、本質的には一種の簡略化されたロックサーバーとして機能します。ええと、ありがとう。
[4:01] わかりました。問題の状況は?私たちが懸念しているのは、スプリットブレインが自動的に発生することです。クライアントが一方のサーバーとは通信できるが、もう一方とは通信できない場合に。つまり、クライアントがリクエストを送信するとき、両方に送信するという状況を想定しています。ええと、今はそれを仮定します。ほとんど問題ではありません。プロトコルは、クライアントが通常、任意のリクエストを両方のサーバーに送信することになっていると仮定しましょう。そして、何らかの方法で、一方のサーバーが応答しない場合にクライアントがどうすべきかを考える必要があります。
[4:32] または、サーバーの一つが応答しないように見える場合にシステムがどうすべきか。ええと、ありがとう。では、クライアント一がサーバー一には連絡できるがサーバー二には連絡できないと想像してみましょう。システムはどう反応すべきでしょうか?一つの可能性は、まあ、あなたも知っているように、ええと、我々は単にクライアントをサーバー一とだけ話させるのは絶対に避けたいと思うことです。なぜなら、この値を一に設定してもこの値を一に設定しなければ、二番目のレプリカが不整合なままになるからです。ですから、ルールとしては、クライアントは常に両方のレプリカと、両方のサーバーと、あらゆる操作について話すことが要求され、片方とだけ話すことは許されるべきではない、というべきかもしれません。
[5:05] では、なぜそれが間違った答えなのでしょうか?ルールが、ああ、我々のレプリケートされたシステムでは、クライアントは常に前進するために両方のレプリカと話すことが要求される、というものだとします。ありがとう。それは全くフォールトトレラントではありません。実際、もっと悪いです。単一のサーバーと話すよりも悪いのです。なぜなら、これらのサーバーのどちらかがクラッシュしたり、それと話せなくなったりすると、システムに問題が生じるからです。少なくとも非レプリケートのサーバーなら、一つのサーバーにのみ依存しています。しかしここでは両方のサーバーが生きている必要があります。クライアントに両方のサーバーと話すことを要求するなら、両方のサーバーが稼働していなければなりません。ですから、クライアントに実際に両方のサーバーの応答を待つことを要求することは不可能です。
[5:48] フォールトトレランスがなければ、先に進める必要があります。ですから、もう一つの明らかな答えは、クライアントが両方と話せないなら、話せる方とだけ話し、もう一方は死んでいると思う、というものです。では、なぜこれも正しい答えではないのでしょうか?厄介なシナリオは、もう一方のサーバーが実際には生きている場合です。ですから、我々が遭遇している実際の問題が、サーバーがクラッシュしたこと(それは我々にとっては良いことですが)ではなく、もっと悪い問題、つまりネットワークケーブルに何か問題が起きたことだと仮定しましょう。そして、このクライアントは、クライアント一はサーバー一と話せるがサーバー二とは話せないのです。
[6:27] そして、サーバー二とは話せるがサーバー一とは話せない別のクライアントがどこかにいるかもしれません。ですから、もし我々が、クライアントが両方のサーバーと話せない場合、フォールトトレラントであるためには片方とだけ話してもよい、というルールを作ると、必然的に何が起こるでしょうか。言ったように、このケーブルが壊れ、ネットワークが二つに切断されます。私はサーバー一にテスト・アンド・セット要求を送ります。サーバー一はその状態を一に設定します。前の値0をクライアント1に返します。そして、クライアント1はロックを取得したと思うでしょう。
[7:00] そして、VMware FTの場合、サーバーは自分がテイクオーバーのプライマリになれると思うでしょう。しかし、このレプリカにはまだゼロが入っています。そうです、では今度はクライアント二もテスト・アンド・セット要求を送るとします。ええと、我々は両方に送ろうとし、サーバー一がダウンしているように見えるのを確認し、話せる一つのサーバーにだけ送ればよいというルールに従うと、クライアント二もまた、ええと、取得したと思うでしょう。クライアント二もロックを取得したと思うでしょう。そして今、ええと、このテスト・アンド・セットサーバーがVMware FTで使われると想像していたなら、我々は、ええと、両方を持っています。
[7:31] ええと、レプリカ、これらのVMwareの両方の、ええと、マシンは、他のサーバーに相談することなく、単独でプライマリになれると思います。ですから、それは完全な失敗です。ですから、この設定と二つのサーバーでは、我々は選択を迫られているように見えました。両方を待てばフォールトトレラントではなく、片方だけを待てば正しくない。正しくないバージョンはしばしばスプリットブレインと呼ばれます。では、皆さんお分かりですか?ありがとう。
[8:03] うーん。まあ。ええと... つまり、これが基本的に状況でした。80年代後半まで。しかし、人々はレプリケートされたシステムを構築したいと思っていました。電話交換機を制御するコンピュータ、あるいは銀行を運営するコンピュータなどです。そういった場所では、信頼性の高いサービスを得るために莫大な金額を費やす用意があり、そのためレプリケートされたシステムを構築しました。そして、レプリケーションを持ちながらスプリットブレインを排除しようとする方法は、いくつかの技術です。一つは、故障しないネットワークを構築することでした。
[8:44] そして通常それが意味するのは、実際、皆さんは本質的に故障しないネットワークを常に使っています。ラップトップ内の、CPUとDRAMを接続する配線は、事実上故障しないネットワークです。CPUとDRAMの間の。ですから、合理的な仮定とたくさんのお金、そして注意深く制御された物理的状況、たとえば誰かが踏む可能性のあるケーブルが床を這っているのは避けたい、注意深く物理的に設計された設定があれば。故障しないネットワークがあれば、スプリットブレインを排除できます。それは少し仮定ですが、十分なお金があれば人々はこれにかなり近づきます。なぜなら、ネットワークが故障しないということは、基本的にクライアントがサーバー二と話せないなら、サーバー二はダウンしているに違いないということだからです。
[9:31] ネットワークの故障ではあり得ないからです。ですから、それが人々がスプリットブレインに悩まされないレプリケーションシステムを構築した一つの方法でした。ありがとう。ええ。もう一つの可能性は、人間に問題を解決させることです。つまり、自動的に何もせず、代わりにクライアントに。デフォルトでは、クライアントは常に、両方のレプリカが応答するのを待たなければならない、といった具合で、片方だけで進めることは決して許されません。しかし、誰かのポケベルを鳴らして、人間が機械室に行って二つのレプリカを見て、片方を確実に死んでいるようにするために電源を切るか、
[10:08] あるいは片方が本当にクラッシュし、もう片方が生きていることを確認します。ですから本質的に人間をタイブレーカーとして使っているわけで、その人間は、もしコンピュータだったらそれ自体が単一障害点になるでしょう。クラブ。長い間、人々はレプリケーションシステムを構築するためにこれらの方式のどちらかを使っていました。そしてそれは、動くように作ることはできます。人間はあまり素早く応答しません。故障し得ないネットワークは高価ですが、不可能ではありません。ええ、しかし、不安定なネットワーク、故障し得るネットワークに直面しても正しく動作する自動フェイルオーバーシステムを実際に構築できることが分かりました。
[10:50] 分断され得るネットワークです。つまり、ネットワークが半分に分かれ、両側が動作するが互いに通信できない、これは通常パーティションと呼ばれます。ええ。ありがとう。ありがとう。そして、スプリットブレインに悩まされない自動レプリケーションシステムを構築するために人々が思いついた大きな洞察は、多数決という考え方です。ですからこれは——ありがとう。ありがとう。ありがとう。Raftの論文では事実上他のあらゆる文に出てくる概念です。
[11:24] それは一種の基本的な、ええと、進め方です。最初のステップは、偶数のサーバーではなく奇数のサーバーを持つことです。たとえば、ここでの一つの欠陥は、少し対称的すぎることです。ここでの分割の両側は、同じに見えます。同じソフトウェアを実行し、同じことをするので、それは良くありません。しかし、奇数のサーバーがあれば、もう対称ではありません。そうです。少なくとも単一のネットワーク分割は、おそらく片側に二つのサーバー、もう片側に一つのサーバーとなり、全く対称ではありません。
[11:57] そしてそれが多数決方式が訴えかけるものの一部です。基本的な考え方は、奇数台のサーバーを持ち、何らかの進展を遂げるために、つまりRaftではリーダーを選出する、あるいはログエントリをコミットさせるために、各ステップで何らかの進展を遂げるために、サーバーの過半数を、半数超を、全サーバーの半数超を集める必要があり、そのステップを承認する、つまりリーダーに投票する、新しいログエントリを受け入れてコミットする必要があります。ええ、ですから、最も……
[12:29] ええと… 単純な方法は、何かを行うのに二台か三台のサーバーを必要とすることです。ええと、これがうまくいく理由の一つはもちろん、もし分断が起きた場合、サーバーの過半数を含む分断は一つしか存在し得ないからです。そういう見方もできます。分断に含まれるサーバーが一台だけなら、それは過半数ではありません。あるいは二台になることもありますが、一方の分断が二台なら、もう一方の分断はサーバーを一台しか持てません。したがって、過半数を集めることは決してできず、進行することもできません。
[13:03] ええと、そしてただ… はっきりさせておくと、過半数と言うときは、常に全サーバーの中での過半数です。稼働中のサーバーだけではありません。これは私が長い間混乱していた点です。三台のサーバーがあるシステムで、いくつかが故障しているかもしれない場合、過半数を集める必要があるなら、常に三台中二台です。一台が故障していると分かっていてもです。過半数は常に全サーバー数に対してです。ええと、これにはもっと一般的な定式化があります。三台中二台が必要という多数決システムのおかげで、一台のサーバーの故障に耐えられます。
[13:40] その通りです。どの二台のサーバーでも進行するのに十分です。もし必要なら、サーバーの信頼性が気になるなら、あるいは神よ、より多くのサーバーを持つシステムを構築できます。より一般的な定式化は、二f足す一のサーバーがあれば、f回の故障に耐えられるというものです。さようなら。つまり三台なら、fは一です。三台のサーバーのシステムでは、f台のサーバー、f1回の故障に耐え、なお稼働し続けます。
[14:16] ありがとう。ありがとう。ありがとう。よし。しばしばこれらはクォーラムシステムと呼ばれます。三台中二台が時にクォーラムと見なされるからです。ありがとう。さて、これらの多数決システムについて既に述べた一つの性質は、ええと、最大で一つの分断しか持てず、したがってネットワークが分断されると、ネットワークの両半分が同時に進行することはできないということです。ここで起きているもう一つのより微妙なことは、ええと、常に過半数が必要なら、
[14:49] サーバーの過半数が進む必要があります。そして一連の操作を経て、各操作で誰かが過半数を集めるということが起こります。たとえば、リーダーへの投票、Raftのリーダーへの投票としましょう。各ステップで、そのステップのために集める過半数には、前の過半数に含まれていたサーバーが少なくとも一台含まれていなければなりません。どの二つの過半数も少なくとも一台のサーバーで重なります。そして、Raftが頼りにしているのは、何よりもこの性質です。
[15:22] ええと、スプリットブレインを避けるために。たとえば、リーダーがいるとき、リーダー選出が成功し、リーダーが過半数から票を集めると、その過半数は前のリーダーの過半数と重なることが保証されます。したがって、たとえば、新しいリーダーは前のリーダーが使った任期番号を知っていることが保証されます。その過半数が前のリーダーの過半数と重なり、前のリーダーの過半数にいた全員が前のリーダーの任期番号を知っていたからです。同様に、前のリーダーがコミットできたものはすべて、Raftのサーバーの過半数に存在していなければならず、したがって新しいリーダーの過半数は少なくとも一台のサーバーと重ならなければなりません。
[16:01] 前のリーダーからのすべてのコミット済みエントリとともに。これは、Raftが正しい理由の大きな部分です。多数決システムの一般的な概念について質問はありますか?はい?サーバーを追加するのも一般的ですか?処理を追加するような?ジョナサン・グルーバー:サーバーを追加することは可能ですか?可能だと思います。可能です、ええと、セクション何とか、おそらく六で、サーバーの集合を追加または変更する方法についてです。
[16:41] 可能です。長期稼働するシステムではそれを行う必要があります。システムを五10年動かすなら、しばらくしたらサーバーを交換する必要が出てきます。一台が永久に故障したり、アップグレードしたり、マシンルームを別のマシンルームに移したりします。サーバー集合の変更をサポートできる必要が本当にあります。そういうことです。毎日起こることでは確かにありませんが、これはこれらのシステムの長期的な保守性の重要な部分です。ええと、そしてRaftの著者たちは少し自画自賛しています。以上です。
[17:12] これを扱う仕組みで、複雑なので彼らがそうするのももっともです。ありがとう。ありがとう。よし、このアイデアを使って、およそ1990年ほど前に、ほぼ同時に二つのシステムが提案されました。スプリットブレインを避けることの見かけ上の不可能性を、基本的に二台ではなく三台のサーバーを使い、多数決を取ることで回避できると気づいたのです。
[17:44] ええと、これらの非常に初期のシステムの一つはPaxosと呼ばれていました。Raftの論文はこれについて多くを語っています。ええと、もう一つの非常に初期のシステムはビュースタンプレプリケーションと呼ばれていました。チャオ。ビュースタンプレプリケーションの略でVSRです。そして、Paxosがこの分野でははるかに広く知られたシステムであるにもかかわらず、Raftは実際には設計においてビュースタンプレプリケーションに近いのです。それはMITの人々によって発明されました。
[18:15] ええと、そしてこれらのシステムには数十年にわたる長い歴史があり、それらが実際に前面に出てきて、展開される大規模分散システムで多く使われ始めたのはおよそ 15 年前のことです。最初に発明されてから優に 15 年後のことです。では……では、ここから Rath について話しましょう。Raft は、何らかのサービスアプリケーションに組み込まれることを意図したライブラリの形をとります。
[18:50] したがって、複製サービスがある場合、サービス内の各レプリカは、RPCなどを受け取るアプリケーションコードと、Raftライブラリから成ります。そしてRaftライブラリ同士が協力して、ええと、複製を維持します。つまり、単一のRaftレプリカのソフトウェア概要は、一番上にレプリカがアプリケーションコードを持っていると考えることができます。ラボ三ならキーバリューサーバーでしょう。たとえばキーバリューサーバーがあるとします。
[19:22] そして状態を持ち、アプリケーションはRaftが管理を助ける状態、複製された状態を持ちます。キーバリューサーバーなら、キーと値のテーブルになります。ええと… *ノック* 次の層はRaft層です。キーバリューサーバーはRaftに関数呼び出しを行い、両者は少しやり取りします。Raftは少しの状態を保持します。図二で確認できます。そして我々の目的では、本当に最も重要な状態は、Raftが操作のログを持っていることです。
[20:01] ありがとう。よし。ありがとう。アーメン。そして、三つのレプリカを持つシステムでは、実際にはまったく同じ同一の構造を持ち、できればまったく同じデータが入っている三つのサーバーを持つことになります。両方の層に存在しているのです。ありがとう。アーメン。ありがとう。ありがとう。ありがとう。ありがとう。ありがとう。
[20:31] ありがとう。そう。この外側には、クライアントが存在することになります。そしてゲームはこうです。つまり、クライアント一、クライアント二、たくさんのクライアントがいます。クライアントは実際には知りません。クライアントは、ご存じのとおり、サービスを利用できる必要がある外部コードです。そして、期待されるのは、クライアントが複製されたサービスと通信していることを実際には意識する必要がないことです。クライアントにとっては、ほとんど単一のサーバーのように見え、一つのサーバーと通信するのです。そして、クライアントは実際にクライアントリクエストをアプリケーション層に送信します。
[21:05] 現在のリーダー、Raft における現在のリーダーであるレプリカの。そして、これらはデータベース、キーバリューサーバーに対するアプリケーションレベルのリクエストになり、put と get のリクエストかもしれません。put はキーと値を取り、テーブルを更新し、get はサービスに、あるキーに対応する現在のキー、現在の値を取得するよう要求します。ですから、これは Raft とはほとんど関係ありません。これは、私たちが構築しているどんなサービスであれ、単なるクライアントとサーバーのやり取りです。
[21:39] ええと、しかし、これらのコマンドの一つがリクエストから送信され、クライアントからサーバーへ送信されると、実際に何が起こるかというと、複製されていないサーバーでは、アプリケーションコードがこのリクエストを実行し、putに応答してテーブルを更新するといった具合です。しかし、RAFTで複製されたサービスではそうではありません。代わりに、クライアントがリーダーにリクエストを送信すると仮定すると、実際に起こるのは、アプリケーション層が単にそのリクエスト、クライアントのリクエストをRAFT層に送り込んで、「ほら、ここにリクエストがある」と言うのです。
[22:10] これを複製ログにコミットしてください。終わったら教えてください。そしてこの時点で、raft同士がやり取りします。ええと。すべてのレプリカ、または過半数のレプリカがこの新しい操作を自分のログに取り込むまで。そうして複製され、そしてリーダーがすべてのレプリカがこのコピーを持っていることを知ったときだけ、通知がラップされてキーバリュー層に送り返され、「ああ、さっき送ってきたあの操作は、今すべてのレプリカにコミットされた。だから安全に複製されており、この時点でその操作を実行してよい」と言うのです。
[22:53] それはraftです。クライアントはキーバリュー層にリクエストを送りますが、QDialyLayerはまだそれを実行しません。なぜなら、まだ複製されていないので確信が持てないからです。すべてのレプリカのログに入ったときだけです。さようなら。そしてRaftがリーダーに通知し、今度はリーダーが実際にその操作を実行します。これはつまり、putならキーバリューテーブルを更新し、getならテーブルから正しい値を読み出し、最後にクライアントへ返信を送るということです。
[23:26] これがその通常の操作です。ありがとう。過半数に入っていればサブミットされます。繰り返しますが、すべてでなければならない理由は、フォールトトレラントシステムを構築したいなら、一部のサーバーが故障しても進展できなければならないからです。なので——ええと、そうです。過半数に入ったときにコミットされます。ありがとう。はい。ですからリーダーがリクエストを実行する前に、マーケット、devalueのプロパティです。
[24:00] ええと……複製されたものについて。ありがとう。わあ。——すみません。ありがとう。リーダーたち、ええ、わかりました。そして。さらに、操作が最終的にコミットされると、各レプリカはその操作を上に送ります。各Raftライブラリ層はその操作をローカルのアプリケーション層に送り、ローカルのアプリケーション層はその操作を自分の状態に適用します。そうしてそれらはすべて……ですから、願わくばすべてのレプリカが同じ操作のストリームを見ることになります。
[24:31] それらはこれらのアップコールに同じ順序で現れ、同じ順序で状態に適用され、そして、操作が決定的であると仮定すれば——そうあるべきですが——ええと、複製された状態の状態は……すべてのレプリカで同一に進化します。ですから通常、このテーブルが論文で「状態」について語るときに指しているものです。ありがとう。この相互作用を別の見方で捉える方法があり、このコースでよく出てくる記法として、ええと、時間図、メッセージがどう流れるかの時間図を描いてみましょう。
[25:12] では、クライアントがいて、サーバー一がリーダーで、さらにサーバー二もあると想像しましょう。ありがとう。サーバー三、そしてこの図では時間は下方向に流れます。クライアントが元のリクエストをサーバー一に送信するのを想像します。ありがとう。その後、サーバー一のラップされた層が、ええと、append entryのRPCを、ええと、二つのレプリカそれぞれに送信します。ありがとう。これはただの普通の、たとえばputリクエストです。
[25:45] これは、これらはPENDエントリのリクエストです。ありがとう。サーバーは今、サーバーからの、他のレプリカからの返信を待っています。多数派からの返信が返ってき次第、リーダー自身を含めてです。つまり、三つのレプリカしかないシステムでは、リーダーは他の一つのレプリカがappend entryに肯定的に応答するのを待つだけでよいのです。多数派からの肯定的な応答が揃い次第、ええと、リーダーはコマンドを実行し、答えがどうなるかを把握します、たとえばforgetのように。
[26:20] ええと、そして返信を…に送り返します。そしてその間、もちろん、ご存じのとおり、もしS2が実際に生きていれば、それも、ご存じのとおり、返信を送り返しますが、私たちはそれを待っていません。ありがとう。図二で知っておくと役立ちます。ありがとう。よし、みんなこれ見える?ありがとう。これがシステムの通常の動作です。ここでは障害はありません。ああ、よし。ああ、そうだね。私は…
[26:53] 重要なステップを省いていました。この時点で、リーダーは知っています、ああ、多数派がそれをログに入れた、先に進んで実行し、クライアントにyesと返信できると。なぜならサーバー二はまだ何も知らないからです。それはただ、ええと、ご存じのとおり、このリクエストを…から受け取った、しかしそれがコミットされたかどうかはわからない、ということだけを知っています。たとえば、私の返信がリーダーに届いたかどうかにかかっています。サーバー2が知り得る限りでは、その返信はネットワークによって落とされたかもしれません。リーダーが返信を聞かず、このリクエストをコミットすることを決めなかったかもしれません。実際にはもう一段階あります、サーバーが…
[27:24] あるリクエストがコミットされたと気づくと、その事実を他のレプリカに伝える必要があります。アーメン。ですから……ええと……ここに追加のメッセージがあります。そのメッセージが正確に何であるかは、他に何が進行中かによって少し変わります。少なくともRAFTでは、明示的なコミットメッセージはありません。代わりに、その情報はリーダーが次に送るAppendEntriesの中に相乗りします。次に送るAppendEntries RPCは、何であれその理由で送られます。
[27:58] たとえば、そのRPCにはcommit、leaderCommitといったフィールドがあります。そして次にリーダーがハートビートを送る必要があるとき、あるいは別のクライアントが何かをリクエストしたために新しいクライアントリクエストを送る必要があるとき、ええと、新しい、より高いleaderCommit値を送り、その時点で、ええと、そうです、レプリカはその操作を実行し、自分の状態に適用します。はい。
[28:29] ありがとう。ありがとう。ああ、はい。では、これは、これはかなり雑談の多いプロトコルです。ええと、そしてそれは、超太ったものではありません。確かに、ええ、クライアントがリクエストを送り、リクエストはサーバーに届かなければならず、サーバーは少なくとも、ええ、別の…と話します。複数のメッセージを送り出し、応答を待たなければならず、何かを返します。つまり、たくさんのメッセージの往復時間が一種あるわけです。
[29:02] ここに埋め込まれています。教員の後半部分には意味があったでしょう。ありがとう。ええ、では…もし…では、これは実際には実装者であるあなた次第で、リーダーが正確にいつ更新されたコミットインデックスを送り出すかは決まります。もし——クライアントのリクエストが、ええと、ごくたまにしか戻ってこないなら。その場合、リーダーはハートビートを送るか、特別な append entries メッセージを送りたいと思うかもしれません。
[29:34] ええと、もしクライアントのリクエストがかなり頻繁に来るなら、それは問題ではありません。もし来るなら、ええと、毎秒千件到着するなら、もう、すぐに次のものがやってくるでしょう。ですから、相乗りできます。つまり、余分なメッセージを生成することなく、それはいくらか高コストですが。とにかく次に送るメッセージに情報を載せることができます。ええと、実際、レプリカがリクエストを実行する時刻は——少なくとも障害がなければ、誰もそれを待っていないので、重要ではないと思います。障害がなければ、レプリカがリクエストを実行することは、実はクリティカルパス上にはありません。
[30:12] クライアントはそれらを待っておらず、クライアントはリーダーが実行するのを待っているだけです。ですから、それはそれほど重要ではないかもしれません。ええと、これが正確にどう段階付けされるかは、クライアントが知覚するレイテンシに影響しないかもしれません。ええと。さようなら。ありがとう。ありがとう。ありがとう。ありがとう。ありがとう。ありがとう。では。あなたが尋ねるべき一つの質問は、なぜこのシステムはこれほどログに焦点を当てているのか、ということです。ログは何をしているのでしょうか?
[30:51] そして、それに対する明確な答えを考え出そうとすることには、ある種の価値があります。なぜこのシステムが完全にログに焦点を当てているのかへの一つの答えは、ログが、リーダーが操作を順序付ける仕組みの一種であるということです。これらの複製された状態機械にとって、すべてのレプリカが同じクライアント操作を最初に適用するだけでなく、同じ操作を同じ順序で適用することが不可欠です。しかし、それらはすべて、クライアントから来るこれらの操作を同じ順序で適用しなければなりません。そしてログは、多くの他のものの中で、リーダーが入ってくるクライアント操作に順序を割り当てる仕組みの一部です。
[31:32] ええ、10 クライアントは操作をリーダーに送ります。同時に、リーダーは順序を選ばなければならず、全員が、すべてのレプリカがその順序に従うことを確実にしなければなりません。そしてログは——ログに番号付きのスロットがあるという事実は——リーダーが選んだ順序を表現する方法の一部です。ええと、ありがとう。ログのもう一つの用途は、この点とこの点の間で、サーバー 3 が、まだコミットされたと確信できない操作を受け取っているということです。そしてそれをまだ実行できません。この操作をどこかに脇に置かなければなりません。
[32:06] リーダーのコミット値への増分が届くまで。そして、ログがしているもう一つのことは、フォロワー上では、ログがフォロワーがまだ暫定的な操作を脇に置く場所であるということです。それは到着したがまだコミットされたと知られていないものです。そして、これから見るように、それらは捨てなければならないかもしれません。ええと、それがもう一つの用途です。リーダー側でのその用途の裏返しのようなものは、リーダーがそのログ内の操作を覚えておく必要があるということです。なぜならそれらを再送信する必要があるかもしれないからです。
[32:38] フォロワーに対してです。もしあるフォロワーがオフラインで、たぶんネットワーク接続に一時的な何かが起こったか何かで、いくつかのメッセージを取りこぼしたとします。リーダーは、フォロワーが見逃したログメッセージを再送できる必要があります。そしてリーダーには、クライアントリクエストのメッセージのコピーを、すでに実行したものも含めて、脇に取っておける場所が必要です。それをクライアントに再送できるようにするためです。つまり、その操作を取りこぼしたレプリカに送るのです。そして、すべてのサーバーがログを保持する最後の理由は、少なくとも図二の世界では、サーバーがクラッシュして再起動し、再参加したいと思った場合、ええと、クラッシュしたサーバーが実際に再起動して再参加してほしいからです。
[33:20] ラップされたクラスタに、さもなければ今や三つのうち二つのサーバーだけで運用しており、それ以上障害に耐えられません。失敗して再起動したサーバーを再び組み込む必要があり、ログは、再起動したサーバーが使う場所のようなものです。ログはそのディスクに永続化されます。なぜなら、ルールの一つとして、各Raftサーバーはそのログをディスクに書き込む必要があり、クラッシュして再起動した後もそこに残っているからです。そのログをサーバーが使い、そのログ内の操作を最初から再生して、クラッシュした時点の状態をいわば作り出すのです。
[33:52] そしてそこから続けます。ですからログは永続化計画の一部としても使われます。状態を再構築するためのコマンドの列として。はい。では、ワーカーがそれに追いつこうとするようなシナリオはどんなものがあるのでしょうか。ええと…では、結局、わかりました。質問は、リーダーが毎秒千件のクライアントコマンドを実行でき、フォロワーは毎秒百件のクライアントコマンドしか実行できないとします。そのような持続的な速度で全力で。
[34:32] ええと、一つ注意すべきことは、レプリカ、つまりフォロワーは、コマンドを実行する前にそれを承認するということです。ですから、それらが承認してログに蓄積する速度は制限されません。ですから、ええ、たぶん毎秒千件のリクエストを承認できるでしょう。もしそれを永遠に続けるなら、それらは蓄積します。無制限のサイズのログになります。なぜなら、私たちのゲームのルールの下では、それらの実行速度は、リーダーがメッセージを渡した速度より無限に遅れていくからです。
[35:06] そしてそれが意味するのは、最終的にメモリを使い果たすということです。ある時点で、十億の、十億のログエントリに遅れた後、彼らはただ、新しいログエントリのための領域をメモリアロケータと呼ばれるものに要求し、それが失敗するでしょう。ええと、そう、そしてRAFTは、ええと、RAFTにはこれに対処するために必要なフロー制御がありません。ですから私は…実際のシステムでは、おそらくピギーバックする必要があり、リアルタイムである必要はありませんが、おそらくここで何らかの追加の通信が必要で、「ああ、実行でここまで進んだ」と言うのです。
[35:47] そうすれば、リーダーは「フォロワーが実行した地点より何千件も先に進みすぎている」と判断できます。ええ、ですから、限界まで性能を引き出そうとする本番システムでは、リーダーが先に進みすぎた場合にそれを抑制するための追加メッセージが必要になるかもしれません。ありがとうございます。では。
[36:33] - では質問は、これらのサーバーの一つがクラッシュした場合、そのサーバーはディスクに永続化したこのログを持っている、なぜならそれが図二のルールの一つだからです。ええと、そのサーバーはディスクからログを読み戻すことができるでしょうが、もちろん、そのサーバーはログの実行でどこまで進んだかを知りません。そしてまた、少なくとも最初に再起動したときには、図2のルールによって、ログがどれだけコミットされているかさえ知りません。ですからあなたの質問への最初の答えは、再起動直後、サーバーがクラッシュして再起動し、このログを読んだ直後には、そのログを使って何もすることを許されないということです。
[37:09]。なぜなら、システムがログの中でどこまでコミットしたかを知らないからです。おそらくこのログには千個の未コミットのエントリがあり、コミット済みのエントリはゼロかもしれません。だから... もしリーダーが死んだとしても、もちろんそれも助けにはなりません。彼ら全員がクラッシュしたとしましょう。これは話が先に進みすぎています... 少し先に進みすぎていますが、彼ら全員がクラッシュしたと仮定すると、彼らが持っているのは図二で不揮発性としてマークされた状態だけで、それにはログとおそらく最新のタームが含まれます。
[37:43]。ええと、そして彼らは知りません。だからもしクラッシュが起きたら、もし彼ら全員がクラッシュして全員が再起動したら、誰も知りません。最初はクラッシュの前にどこまで実行していたかを。そこで何が起こるかというと、彼らはリーダー選挙を行い、そのうちの一人がリーダーに選ばれます。そしてそのリーダーは、図二が追加エントリがどのように機能すべきかについて述べていることを追っていくと、実際には最初のハートビートを送り出すことの副産物としてそれを把握するのです。
[38:14] ええ、それは基本的に最新の地点、つまりレプリカの過半数が自分のログについて同意している地点を把握します。なぜならそれがコミットポイントだからです。別の見方をすれば、リーダーを選んだ後、AppendEntriesの仕組みを通じて、リーダーは他のすべてのレプリカにリーダーと同一のログを持たせます。そしてその時点で、さらに…
[38:45]。少し余分なこととして、論文が説明しています。その時点で、リーダーは自分がすべてのレプリカに自分と同一のログを持たせたことを強制したと知っているので、こう知るのです、ああ、すべてのレプリカもまた持っているに違いない——今や同一となったログ内のそれらすべてのログエントリは、レプリカの過半数に保持されているのだから、コミット済みでもあるに違いない、と。ええと、その時点で、図二で説明されているリーダー向けの追加エントリのコードはリーダーのコミットポイントを増加させ、そして誰もが今や最初からログ全体を実行できるのです。
[39:22]。そして自分たちの状態をゼロから再構築します。おそらく極めて骨の折れる作業で。ええと... それが図二の述べていることです。明らかにこのゼロからの再実行はあまり魅力的ではありませんが、基本的なプロトコルはそうするのです。そして明日見るでしょう。このバージョンはより効率的で、チェックポイントを使います。それについては明日話します。ありがとう。では、これは通常の、障害のない運用における一連の流れでした。
[39:53]。ええと、ええと... もう一つ簡単に触れたいのは、このインターフェースがどのようなものかということです。ラボに取り組んでいるので、皆さんおそらく少しは見たことがあるでしょう。しかし大まかに言えば、例えばこのキーバリューレイヤーがあり、その状態があり、その下にラフトレイヤーがあるとすると、各レプリカには実際に二つの主要な部分があります。それらの間のインターフェースの。これがあります... ええと、キーバリューレイヤーが中継できる方法です。もしクライアントがリクエストを送ってきたら、キーバリューレイヤーはそれをラフトに渡して言わなければなりません、「どうか、このリクエストをどこかログに組み込んでください」と、そしてそれがスタート関数です。
[40:34]。ええと。raft.goで見るでしょう。そして実際には引数を一つだけ取ります、クライアントコマンドです。ありがとう。キーバリューレイヤーは言っています、「どうか、このコマンドを受け取りました。それをログに組み込んで、コミットされたら教えてください」と。そしてインターフェースのもう一つの部分は、やがてラフトレイヤーがキーバリューレイヤーに通知することです、ああ、少し前にスタートコマンドで私に送ったあの操作は、必ずしも最新のスタートではないかもしれません。百個のクライアントコマンドが来て、それらのどれかがコミットされる前にスタートへの呼び出しを引き起こすかもしれません。
[41:09] やがて、ええと、この上向きの通信は、Raftライブラリが送信し、キーバリューレイヤーが読み取ることになっているGoチャネル上のメッセージという形を取ります。ええ、ですからこのapply、ありがとうございます。ありがとうございます。それはapplyチャネルと呼ばれ、その上でapplyメッセージを送ります。ありがとうございます。わかりません。ありがとうございます。ありがとうございます。ありがとうございます。このstartと、もちろんキーバリューレイヤーは、Applyチャネルで受け取るメッセージを、自分が行ったstartの呼び出しと照合できる必要があります。
[41:47] ええと、それで start コマンドは実際にそのマッチアップが成立するのに十分な情報を返します。start 関数が基本的に返すのはログ内のインデックスで、このコマンドがコミットされた場合——されるとは限りませんが——このインデックスでコミットされることになります。ええと、それに現在のタームと、あまり気にしないその他の情報も返すと思います。そしてこの apply メッセージには、インデックスが含まれます。コマンドの両方と。
[42:20] ええと。ありがとう。ありがとう。ありがとう。ありがとう。ありがとう。そしてインデックスです。そしてすべてのレプリカがこれらの apply メッセージを受け取るので、みんな「ああ、このコマンドを適用すべきだ」と分かり、このコマンドが何を意味するのかを理解して自分のローカル状態に適用します。そして彼らはインデックスも受け取ります。インデックスが本当に役立つのはリーダー上だけで、リーダーはどのクライアントのリクエストについて話しているのかを把握できます。ありがとう。次のことが気になります。クライアントはリクエストをバック、ラフトのリーダーにどこでも送っているのですか。
[42:59] そこで——クライアントは get を行うことで。そうです。それについて。OK。OK。ええと、私は少し違う質問に答えた気がします。クライアントが何らかのリクエストを送るとしましょう。それが put でも get でも構いません。put でも get でもいいのです。実際にはあまり関係ありません。get としましょう。ええと、その時点で——つまりクライアントは再び送信して応答を待ちます。リーダーがそもそも応答を送る時点は、リーダーがそのコマンドがコミットされたことを知った後です。
[43:40] つまりこれは一種の get の返信になります。バイ。*ノック* バイ。つまりクライアントには何も返ってきません。つまり、それで、ええと、それは実際のソフトウェアスタックの観点では、キーバリューの RPC が到着し、キーバリューレイヤーが start 関数を呼び出すということです。start 関数はキーバリューレイヤーに戻りますが——キーバリューレイヤーはまだクライアントに返信しません。なぜならそれが実際に——まだクライアントのリクエストを実行していないからです。それが今後実行されるかどうかさえ分かっていません。
[44:14] なぜならリクエストがコミットされるかどうか確信が持てないからです。コミットされない可能性がある状況とは、キーバリューレイヤーがリクエストを受け取り、start を呼び出し、start が戻った直後にクラッシュする場合です。確かに apply、pen メッセージなどは送信していません。まだ何もコミットされていません。ええと、つまりゲームは、start が戻り、時間が経過し、そのクライアントリクエストに対応する該当の apply メッセージが apply チャネル上でキーバリューサーバーに現れ、その時点で初めてキーバリューサーバーがリクエストを実行し、返信を送るのです。
[44:52] ありがとう。ありがとう。ありがとう。ありがとう。ありがとう。そしてそれは——これらすべては、すべてがうまくいく場合にはあまり重要ではありません。しかし障害がある場合、私たちは今——障害について心配し始める時点で、障害があった場合にクライアントが何を見たかに非常に興味を持つでしょう。ええと、ありがとう。よし。そして、出てきたことの一つは……ええと、皆さんよくご存じだと思いますが、少なくとも最初は、ログについての興味深い点の一つは、それらが同一でないかもしれないということです。
[45:30] 少なくとも短時間の間、異なるレプリカのログの末尾が分岐する可能性がある状況はたくさんあります。例えば、リーダーが append メッセージのラウンドを送り始めたが、すべてを送り終える前にクラッシュした場合です。つまり、append メッセージを受け取ったレプリカの一部はその新しいログエントリを追加し、その pin メッセージを RPC として受け取らなかったレプリカは追加しないということになります。ですからログが時々分岐するのは容易に理解できます。良い知らせは、Raft の仕組みが実際にはしばらくするとログを同一に強制するということです。
[46:07] 一時的な差異はあるかもしれませんが、長期的にはすべてのログはリーダーによって修正され、リーダーがそれらすべてが同一であることを保証し、その後にのみ——ええと。OK。次は、Raft についてここで話すべき大きなトピックが実際に二つあると思います。一つはリーダー選出がどのように機能するかで、これは Lab 2 です。もう一つは、リーダーが異なるレプリカのログを、特に障害後にどのように扱うかです。
[46:38] まずリーダー選出について話したいと思います。アーメン。ありがとう。問うべき質問は、なぜこのシステムにそもそもリーダーがいるのか、なぜリーダーが必要なのかということです。その答えの一部は、このようなシステムを構築するのにリーダーは必要ないということです。指定されたリーダーを一切持たずに、サーバーのクラスタがログ内のエントリの順序について合意する合意システムを構築することは可能です。実際、論文が言及している元々の Paxos システム、元々の Paxos にはリーダーがありませんでした。
[47:11]。ええと、だから可能です。ラフトにリーダーがいる理由は基本的に、ええと、おそらく多くの理由がありますが、最も重要な理由の一つは、すべてのサーバーが故障しないという一般的なケースにおいて、より効率的なものを構築できるということです。リーダーがいれば、より効率的なシステムを構築することが可能です。指定されたリーダーがいれば、誰もがリーダーが誰かを知っており、基本的にリクエストごとに一往復のメッセージでリクエストについて合意を得ることができます。一方、リーダーのいないシステムは、どちらかというと、まず一時的なリーダーに合意するための第一ラウンドがあり、次に実際にリクエストを送り出すための第二ラウンドが必要という性格が強いのです。
[47:49]。ですから、リーダーの使用がシステムを二倍速くするというのはおそらく事実でしょう。ありがとう。そしてそれは何が起こっているかを考えるのをいくらか容易にします。ありがとう。ええと、ラフトは一連のリーダーを経て進み、そしてどのリーダーについて話しているかを曖昧さなくするためにこれらのターム番号を使います。結局のところ、フォロワーはリーダーの身元を実際には知る必要がないことが分かります。彼らが本当に必要とするのは、現在のターム番号が何かということだけです。
[48:20]。各タームには最大で一人のリーダーがいます。それだけです。極めて重要な性質です。ご存じのとおり、各タームについて、そのタームの間にリーダーがいないこともあれば、一人のリーダーがいることもありますが、同じタームの間に二人のリーダーがいることはできません。各タームには最大で一人のリーダーがいます。ええと、ありがとう。ありがとう。そもそもリーダーはどのようにして生まれるのでしょうか?すべての... ラップされたサーバーはこの選挙タイマーを保持しており、それは基本的に、記録しているある時刻にすぎず、その時刻になれば何かをするつもりだと言っているようなものです。
[48:55] ええと、そしてそれが行うことの一つは、リーダー選挙期間が完全に経過しても、そのサーバーが現在のリーダーから何のメッセージも受け取らなかった場合、そのサーバーはおそらく現在のリーダーは死んだとみなし、選挙を開始するということです。つまり、この選挙タイマーがあるわけです。そしてそれが期限切れになると、選挙を開始します。ありがとう。.
[49:26]。ありがとう。ええと、そして選挙を開始するというのは基本的に、タームを増加させることであり、候補者、つまり自分が候補者になると決めたサーバーは、一種の新しい選挙を強制し、まずこのタームを増加させます。なぜなら、ご存じのとおり、新しいリーダー、すなわち自分自身を望んでいるからです。そして一つのタームは二人以上のリーダーを持つことができないので、新しいリーダーを持つためには新しいタームを始めなければなりません。そしてその後、これらのリクエスト投票のRPCを送り出します。
[49:57]。ありがとう。私はリクエスト投票の完全な一巡を送り出そうとしています。そしてn引く一のリクエスト投票を送るだけで済むかもしれません。なぜなら、一つの規則として、新しい候補者は選挙で常に自分自身に投票するからです。ええと、ですから。これについて注意すべき一つのことは、リーダーが故障しなかったなら選挙は行われない、とか、リーダーが故障したなら他のサーバーが稼働していると仮定して選挙が行われる、というのは必ずしも成り立たないということです。なぜならいつか他のサーバーの選挙タイマーが発火するからです。
[50:28] しかし、リーダーが故障しなかった場合でも、残念ながら選挙が起こる可能性があります。つまり、ネットワークが遅い場合や、いくつかのハートビートを落とした場合など、選挙タイマーが発動してしまい、完全に正常なリーダーがいたにもかかわらず、それでも新しい選挙が起こる可能性があります。ですので、正確性について考える際には、このことを念頭に置く必要があります。ええと、そしてそれがひいては意味するのは、新しい選挙が起こった場合、古いリーダーがまだ存在し続けていて、自分がまだリーダーだと思っている可能性が容易にあり得るということです。例えばネットワーク分断があった場合などです。そして古いリーダーが少数派のパーティション内でまだ生きて元気に動いている場合です。
[51:02] 多数派のパーティションは選挙を実行し、実際に選挙に成功して、新しいリーダーを選出するかもしれません。それは以前のリーダーには全く知られていません。ですので、私たちはまた、あの以前のリーダーは、新しい選挙があったことを知らないので、何をするのだろうか、ということも心配しなければなりません。ありがとう。どうもありがとう。ありがとう。
[51:43] では質問は、例えば一方向のネットワーク通信がシステムの前進を妨げるような病的なケースが存在し得るか、ということです。答えはイエスだと思います。確かに。例えば、現在のリーダーのネットワークが何らかの形で半故障し、現在のリーダーはハートビートを送信できるがクライアントのリクエストを受信できない場合です。その場合、送信されるハートビートは、送信側のネットワーク接続が機能しているので配信されます。その送信ハートビートは、他のサーバーが選挙を開始するのを抑制します。
[52:20] しかし、受信側のネットワーク回線が明らかに壊れているという事実により、クライアントのコマンドを聞いて実行することができなくなります。Raftがあらゆる突飛なネットワーク問題に対して耐性があるという証明にはならないことは、確実に言えます。私が考えたものについては、修正可能だと思います。つまり、この問題は、双方向のハートビートを要求するような仕組み、すなわちリーダーがハートビートを送信するが、フォロワーは既に要求されているように何らかの形でハートビートに応答することが求められる、という仕組みによって解決できるでしょう。
[52:58] しかし、リーダーが自分のハートビートへの応答を見なくなった場合、ある程度の時間が経過した後、リーダーは退任を決意します。これは特定の問題だと思います。修正可能です。そして他の多くの問題も同様です。しかし、ええと、ご指摘の通りです。ネットワークには非常に奇妙なことが起こり得ます。プロトコルが準備していないものを含めて。ありがとう。ありがとう。ありがとう。
[53:29] では、これらの選挙が行われます。私たちは、各任期において最大で一人のリーダーしか存在しないことを保証する必要があります。Raft はそれをどうやって実現するのでしょうか。ええと、Raft では、ある任期で当選するためには、候補者がサーバーの過半数から賛成票を得る必要があります。サーバーは、各サーバーが各任期につき賛成票を一度だけ投じます。ですから、任意の任期において、基本的には、各サーバーは一つの候補者にしか一度しか投票しないということになります。ええと、二人の候補者が両方とも過半数の票を得ることはあり得ません。なぜなら、全員が一度しか投票しないからです。
[54:06] ええと、ですから過半数、過半数ルールによって、当選する候補者は最大で一人になります。ええと、そしてその結果、各任期で当選する候補者は最大で一人となります。ええと… さらに、決定的に重要なこととして、過半数ルールは、一部のサーバーがクラッシュしていても当選できることを意味します。少数のサーバーがクラッシュしていたり利用不能だったり、ネットワーク問題を抱えていたりしても、リーダーを選出できます。半数を超えるサーバーがクラッシュしていたり、利用不能だったり、別のパーティションにいたりする場合には、実際のところ、システムはリーダーを選出しようと何度も何度も試み続けるだけになります。
[54:46] そして決してリーダーを選出できません。実際、稼働中のサーバーの過半数が存在しない場合には。ええと、ありがとうございます。選挙が成功したなら、全員がそれを知ることができれば素晴らしいです。7 分ほどで。私たちは、すべての当事者が何が起こったのかをどうやって知るのかを自問する必要があります。選挙に勝ったサーバーは、クラッシュしないと仮定すれば、選挙に勝ったサーバーは実際に、他のサーバーの過半数から自身のリクエスト投票に対して過半数または賛成票を得たことを確認します。選挙を実施して勝った候補者、つまり選挙に勝った候補者は、自分が過半数の票を得たことを直接知ることになります。
[55:23] しかし他の誰も、勝者が誰だったか、あるいは誰かが勝ったかどうかを直接知りません。ええと、そこで候補者が他のサーバーに知らせる方法は、そのハートビートです。図2のルールはこう言っています、ああ、選挙に勝ったら、すぐに他のすべてのサーバーにappend entriesを送信する義務があると。さて、append entries、つまりハートビートのappend entriesは、明示的に「私は選挙に勝った、ええと、私はターム23のリーダーだ」とは言いません。ええと、それはもう少し微妙です。情報が伝達される方法は、ええと、そのタームのリーダーでない限り、誰もappend entriesを送信することは許されないということです。
[56:02] つまり、私が、ええと、私はサーバーであり、ああ、ターム19の選挙があるのを見たという事実です。そして次第に、私はターム19のappend entriesを送ります、それは私に誰かが、誰かは分からないが、誰かが選挙に勝ったことを伝えます。ええと、それが他のサーバーが知る方法です、つまり彼らはそのタームのappend entriesを受信していたのです。そしてそのappend entriesはまた、全員の選挙タイマーをリセットする効果もあります。ですから、リーダーが稼働していて、少なくとも想定されるレートでハートビートメッセージやappend entriesを送信している限り、サーバーがappend entryを受信するたびに、その選挙タイマーをリセットし、誰かが新しい候補者になるのをある程度抑制します。
[56:46] ですから、すべてが正常に機能している限り、繰り返されるハートビートによってそれ以上の選挙は防止されます。もちろん、ネットワークが故障したりパケットがドロップされたりすれば、それでも選挙が行われる可能性があります。しかし、すべてがうまくいけば、選挙が行われる可能性は低いと言えます。ええと、この方式は、ある意味では失敗する可能性があります。つまり、ある任期に対して二人のリーダーを選出するという意味では失敗し得ませんが、ある任期に対してゼロ人のリーダーを選出するという意味では失敗し得ます。ええと、失敗する主な方法は、あまりにも多くのサーバーが停止していたり、利用不能だったり、ネットワーク接続が不良だったりする場合です。ですから、過半数を集められなければ、当選できず、何も起こりません。
[57:22] ええと、選挙が失敗するより興味深い方法は、全員が稼働している場合です。つまり、障害もなく、パケットもドロップされていません。しかし、二人のリーダーが十分に近い時間に候補者となったため、二人の間で票が割れる場合です。あるいは三人のリーダーがそうなる場合です。ええと、三人のリーダーがいると仮定しましょう。三つのレプリカからなるシステムがあると仮定します。ええと、それらの選挙タイマーがすべて同時に発動します。
[57:53] すべてのサーバーが自分自身に投票します。そして、それぞれが別のサーバーからリクエスト投票を受け取ると、すでに自分自身に投票してしまっているので、ノーと答えます。つまり、三つのサーバーがそれぞれ一票ずつ得て、誰も過半数を得られず、誰も当選しません。ええと、それから、彼らの選挙タイマーが再び発動します。なぜなら、選挙タイマーは append entries を受け取ったときにのみリセットされますが、リーダーがいないからです。彼らは皆、選挙タイマーが再び発動します。そして運が悪ければ、全員が同時に発動します。全員が自分自身に投票します。誰も過半数を得られません。ええと、そういうわけです。
[58:24] ですから明らかに、皆さんはこの時点でもうお気づきだと思いますが、この話にはまだ続きがあります。そして、Raftが票の分裂の可能性を不可能ではないにしても低くする方法は、これらの選挙タイマーをランダム化することです。ですから、これを考える方法は、そしてランダム化は、ええと、これを考える方法は、あるタイムラインがあり、そこにイベントを描きます。全員が最後のappend entriesを受信したある時点があります。
[58:56] そして、おそらくサーバーが停止したのでしょう。ここでは、サーバーが最後のハートビートを送信してから停止したと仮定しましょう。さて、すべてのフォロワーは、おそらく全員が同時に append entries を受け取ったため、同時に選挙タイマーをリセットしました。全員が選挙タイマーをリセットしたのです。将来のある時点で、将来のある時点で発火するように。それぞれが将来の異なるランダムな時刻を選び、それが発火することになっていました。つまり、停止したリーダーはサーバー一だとすると、ここでサーバー二とサーバー三が、将来のランダムな時点に選挙タイマーを設定します。たとえば、サーバー二は、ええと、このあたりでタイマーが発火するように設定したとしましょう。
[59:38] そしてサーバー三は、選挙タイマーがそこで発火するように設定しました。そして、この図の重要な点は、異なるランダムな数を選んだと仮定すると、一方が先で、もう一方が後になるということです。そうですよね?ここで起きているのはそういうことです。そして先になる方、この間隔が十分に大きいと仮定すれば、先になる方の選挙タイマーが、もう一方の選挙タイマーより先に発火します。運が悪くなければ、完全な一回分の投票要求を送信する時間が得られます。
[1:00:10] そして、他のどのサーバーの二番目の選挙タイマーが発動する前に、全員が稼働している状態で全員から回答を得ることができます。ええと、それでは。ランダム化がこれらの候補者の同期をどのように崩すか、皆さんお分かりいただけますか。残念ながら、これらの選挙タイマーの定数を設定するには少し職人芸的なところがあります。満たしたい要件がいくつか競合する場合があります。ええと、明らかな要件の一つは、選挙タイマーがハートビート間の予想間隔以上でなければならないということです。
[1:00:48] リーダーが100ミリ秒ごとにハートビートを送信するのは明らかですから、誰の選挙タイマーも100ミリ秒で発火する意味はないことを確実にしておくべきです。なぜなら、新しい append entry が期待できるよりも前に発火してしまうからです。したがって下限は確実に、下限は一ハートビート間隔です。実際、ネットワークはパケットを落とす可能性があるので、選挙タイマーの最小値はハートビート間隔の数倍にした方がよいでしょう。つまり、100ミリ秒のハートビートなら、選挙タイマーの最短値は例えば300ミリ秒にした方がよいでしょう。
[1:01:25] ハートビート間隔の三倍です。ええと、それが最小値のようなもので、ええと……。ハートビートがこれくらい頻繁なら、最小値はその数倍か、ここくらいにしたいところです。ええと、では最大値はどうでしょう?おそらく、ある範囲の時間にわたって一様にランダム化することになるでしょう。ええと、最大値をどこに設定すべきでしょうか。ありがとう。ランダム化する範囲の最大値です。そして、いくつか……。
[1:01:55] 実際のシステムではここで考慮すべき点があります。ええと、この最大時間は、システムが障害からどれだけ早く回復できるかに影響します。なぜなら、サーバーが故障した時点から最初の選挙タイマーが発火するまでの間、システム全体が凍結することを覚えておいてください。リーダーがいません。クライアントのリクエストはリーダーがいないため捨てられています。そして、おそらく他のサーバーは稼働しているにもかかわらず、新しいリーダーを割り当てていません。
[1:02:26] この最大値を大きくするほど、回復が起こるまでにクライアントに課す遅延が長くなります。それが重要かどうかは、このシステムにどれだけ高い性能が必要か、そして障害がどれくらいの頻度で起きると思うかによります。障害が年に一度なら、誰も気にしません。ええと、障害が頻繁に起きると予想するなら、回復にかかる時間を非常に気にするかもしれません。はい、それが一つの考慮点です。もう一つの考慮点は、この間隔、つまり最初のタイマーが発火してから二番目のタイマーが発火するまでの予想される時間間隔です。
[1:03:03] ええと、この間隔は、役に立つためには、候補者が全員から票を集めるのにかかる時間より長くなければなりません。つまり、予想される往復時間、RPCを送信して応答を得るのにかかる時間より長くなければなりません。ええ、おそらく10ミリ秒かかるでしょう。RPCを送信して応答を得る、ええと、他のすべてのサーバーから応答を得るのに。そしてそうなら、最小の乱数と次に小さい乱数の間に10ミリ秒の差がかなり高い確率で生じるように、最大値を十分長くする必要があります。
[1:03:35] ええと、ありがとう。そしてあなたにとって、ええと、テストコードは、ええと、ありがとう、リーダーの故障から数秒以内に回復しないと不機嫌になります。ですから、実用的には、この最大値を小さく調整して、数秒以内にリーダー選挙を完了できる可能性を高くする必要があります。それはそれほど厳しい制約ではありません。
[1:04:09] 選挙タイムアウトについて質問はありますか?小さな点は、ええと、選挙タイマーをリセットするたびに、新しいランダムなタイムアウトを選ぶべきだということです。つまり、サーバーが最初に作成されたときに乱数を選んで、その同じ数を何度も再利用しないでください。なぜなら、運の悪い選択をしてしまうからです。つまり、同じものを選んでしまうのです。
[1:04:39] あるサーバーが不運にも別のサーバーと同じ乱数を選んでしまうと、それは分裂投票を何度も何度も、永遠に繰り返すことになります。だからこそ、タイマーをリセットするたびに、選挙タイムアウト値としてほぼ確実に異なる、新しい、新鮮な乱数を選ぶべきなのです。ありがとう。では、リーダー選挙に関する最後の問題です。旧リーダーが分断されたこの状況にいるとします。
[1:05:10] ネットワークケーブルが切れて、旧リーダーが数人のクライアントと少数のサーバーとともに取り残されているとします。ネットワークのもう半分には多数派がいて、ネットワークの新しい半分の多数派が新しいリーダーを選出します。旧リーダーはどうなるのでしょう?なぜ旧リーダーは……ありがとう。誤った実行を引き起こさないのでしょうか。ありがとう。たぶんそれは……はい、そこのあなた。
[1:05:56] そうなるのは…… - 喜んで。では。そしてすべて終わりました。まったく。ありがとう。ええ。二つの潜在的な問題があります。あるいは、一つのいわば問題でないものは、別のパーティションにリーダーがいて過半数を持たない場合、次にクライアントがそれに要求を送ると、ええと、そのリーダーは、ご存知の通り、少数派とのアバカシオンで、ええ、append entries を送信しますが、少数派のパーティションにいるため、自分自身を含む過半数のサーバーから応答を得られません。したがって決して……。
[1:06:34] その操作をコミットすることはなく、決して実行しません。クライアントに実行したと応答することも決してありません。つまり、別のパーティションにいる古いサーバーに、クライアントが要求を送るかもしれませんが、決して応答を得られません。ええと、ですからどのクライアントも、その古いサーバーが自分のために何かを実行したと騙されることはありません。もう一つのより厄介な問題は、実際に数分後に話しますが、サーバーが故障する前に append entries を一部のサーバーに送信する可能性です。
[1:07:14] サーバーの。そしてコミットの決定を行う前にクラッシュする。そしてそれは非常に興味深い質問で、ええと、おそらく45分ほどじっくり話すことになるでしょう。それで、実際、後ろに移る前に、全般的な話題について。リーダー選出についてさらに質問があります。ありがとう。OK。ええと、では、ログの内容について、特に新しく選出されたリーダーが前任リーダーの厄介なクラッシュの後にどうやって残骸を拾い集めるのか、新しく選出されたリーダーは異なるレプリカ上でおそらく分岐しているログをどうやって整理するのか?
[1:08:01] システム内で一種の一貫した状態を回復するために。ええと、では、最初の質問は、何が起こりうるか、この話題全体は実際にはサーバーがクラッシュした後でしか興味深くないのです、そうですよね?サーバーが稼働し続けるなら、比較的起こりうることは少ないです。稼働中で過半数を持つサーバーがあれば、稼働中で過半数を持つ期間中は、ええと、単にフォロワーにログがどうあるべきかを伝えるだけです。
[1:08:36] そしてフォロワーは反対することは許されません。受け入れることが要求されます。図二の規則により、多かれ少なかれ追いついていれば、ただそれに従います。ご存知の通り、リーダーが送ってくるものをそのまま受け取り、append entries をログに追加し、コミットメッセージに従い、実行します。ほとんど何も問題は起きません。Raft で問題が起きるのは、古いリーダーがメッセージを送信している途中でクラッシュしたときや、新しいリーダーが選出された直後、何か非常に有用なことをする前にクラッシュしたときなどです。
[1:09:08] そこで、私たちが非常に興味を持っていることの一つは、いくつかのクラッシュの連続の後、ログがどのようになり得るかということです。ええと……。はい、例を挙げましょう。ここに三つのサーバーがあります。ありがとう。ありがとう。ええと、そしてこれらの図を描く方法ですが、ログがこのようになる多くの状況を見ていくことになり、それが可能かどうか、そしてもしそうなったら何が起きるかを考えます。ですから、私の記法は、ええと、各サーバーのログエントリを、スロットを示すように揃えて書き出すというものです。
[1:09:46] ログの対応するスロットです。そしてここに書く値は、クライアントの操作ではなく任期番号です。ご存知の通り、これがスロット一、これがスロット二です。ええと、全員がスロット一で任期三のコマンドを見ました。サーバー2とサーバー3は、二番目のスロットで、同じく任期三のコマンドを見ました。サーバー一にはそこに何もありません。ええと、そしてこの最初の質問は、この状態が起こり得るかということです。
[1:10:18] これは...この状況は起こりうるのか、そしてどうやって?おお。どうやって?ありがとう。ええ、では。ありがとう。では。
[1:11:03] ですから、たぶんサーバー三がリーダーだったのでしょう、ただあなたの言ったことを繰り返すと、たぶんサーバー三が第三期のリーダーです。それは全員に送られるコマンドを受け取りました。全員がその依存関係をログとして受け取りました。そしてサーバー三が、クライアントから二番目のリクエストを受け取りました。そして、それを三つのサーバーすべてに送ったかもしれませんが、メッセージはサーバー一への途中で失われたか、あるいはその時サーバー一がダウンしていたか何かで、それでサーバー二だけが受け取ったのでしょう。ええと、リーダーは常に新しいコマンドを送信する前に自分のログに追加します。ええと、そして追加エントリRPCはサーバー二にしか届かなかったのかもしれません。ですからこの状況は、ご存知の通り、実際にログが今異なっている最も単純な状況のようなものです。
[1:11:38] そしてそれがどのようにして起こり得るかはわかっています。ですから、もしリーダーであるサーバー三が今クラッシュしたら、次のサーバーはサーバー一を確実にしなければならないでしょう。まず第一に、もしサーバー3がクラッシュするか、選挙が行われて別のリーダーが選ばれた場合、二つのことが起こらなければなりません。新しいリーダーは、これが、ええと、コマンドがコミットされた可能性があることを認識しなければなりません。それを捨てることは許されません。そして、サーバー一がこの空白を、他の全員がそのスロットに持っていたまさに同じコマンドで埋めることを確実にしなければなりません。
[1:12:15] ええと、ありがとう。では、クラッシュの後、誰か、つまりサーバーが、この問題が起こり得る別の方法として、サーバー三がサーバー二に追加エントリを送ったが、サーバー三に追加エントリを送る前にクラッシュしたのかもしれません。ですから、もし新しいリーダーを選出しているなら、それはメッセージが送られる前のクラッシュが原因かもしれません。では、考えるべき別のシナリオがあります。ええと、また三つのサーバーです。ありがとう。ありがとう。ありがとう。ええと、今度はログのスロットに番号を振ります。
[1:12:47] そうすればそれらを参照できます。ええと、スロット10、11、12があります。ありがとう。13。もう一度。それは...ありがとう。同じ設定ですが、今度はスロット12に、サーバー2が第四期からのコマンドとしてあり、サーバー三は第五期からの用語コマンドを持っています。ありがとう。ありがとう。ですから、これらを分析して何が起こるかを理解する前に、サーバーがこれを見たらどうするかを考える前に、これがそもそも起こり得るのかを問う必要があります。
[1:13:25] 時には、ああ、もしこの構成が生じたら何が起こるだろうかという質問への答えは、時には答えは、それは生じえないので心配する必要はない、というものです。ええと、では質問は、これは起こりうるのか、そしてどうやって?ええ。いいえと言う、なぜなら私たちにはたくさんの...があるからです。OK。ありがとう。ありがとう。ええと、では。
[1:14:00] そしてどんな...では。ありがとう。最初の状況が起こります。アーメン。見ています。友よ。- さて、トロイ。バイ。ロジャー。ありがとう。何?ああ...そう、先生。
[1:14:32] 皆さん。ありがとう。- ああ、なんてこった。よし。戻ります。ええ。どこまで?では、それを繰り返します。手短に。この構成が起こり得ることはわかっています。そして、ここで四と五を得る方法は、次のリーダー選挙でサーバー2がリーダーに選ばれると仮定しましょう。
[1:15:09] さて、第四期のために。リーダーを選びます。クライアントからリクエストを受け取り、それを自分のログに追加し、クラッシュします。ですから今これがあります。そうです、リーダーがちょうどクラッシュしたので、新しい選挙が必要です。さて、この選挙で、ありがとう。そして今、誰が選ばれ得るかを問わなければなりません、あるいは心に留めておかなければなりません、ああ、誰が選ばれ得るのか?ええと、サーバー三が選ばれ得ると主張します。それが選ばれ得る理由は、過半数のサーバーから投票応答を得るだけでよいからです。その過半数はサーバー一とサーバー三です。
[1:15:41] ご存知の通り、問題はありません、これら二つのログの間に競合はありません。ですからサーバー三は第五期のために選ばれ、クライアントからリクエストを受け取り、自分のログに追加し、クラッシュすることができます。そしてそれがこの構成を得る方法です。ええと、この構成を。ですから、これらのことを理解し進める必要があります。はい、これは起こり得ると言う段階に到達するために、それゆえRaftは何か賢明なことをしなければならない、それが起こり得ないのとは対照的に。なぜなら起こり得ないこともあるからです。
[1:16:12] ええと、ありがとう。では……。さて、今何が起こり得るでしょうか?これが起こり得ることは分かっています。願わくば、Raftが実際に分別のあることをするのだと自分たちで納得できるようにしましょう。さて、物事の範囲については、Raftが実際に何をするかを話す前に、何が許容できる結果なのかについてある程度の感覚を持つ必要があります。
[1:16:47] いいですか?そしてこれをざっと見るだけで、ええと、スロット10のコマンドは、すべてのレプリカに知られているので、コミットされていた可能性があります。したがって、それを捨てることはできません。同様に、スロット11のコマンドは、レプリカの過半数に存在するので、我々の知る限りではコミットされていた可能性があり、捨てることはできません。しかしスロット12のコマンドは、どちらもコミットされていた可能性はありません。したがって我々にはその権利があります。我々は知りません、Raftが実際に何をするかは見ていませんが、Raftは10や11のどちらのコマンドも落とす権利はないものの、両方を落とす権利はあります。
[1:17:26] ええと、これは許されるドロップです。どちらか一方を落とすことは必須ではありません。そして、少なくとも一方は確実に落とさなければならないことは分かっています。なぜなら、最終的には同一のログ内容を持たなければならないからです。これはコミットされていた可能性があります。ログを見ただけでは、リーダーがクラッシュする前にどこまで進んだかを正確に知ることはできません。したがって一つの可能性は、このコマンドあるいはこのコマンドについてさえ、リーダーが新しいコマンドを含むappendメッセージを送信し、その直後にクラッシュしたという可能性です。
[1:18:04] ですから、クラッシュしたため応答を一切受け取っていません。つまり旧リーダーはそれがコミットされたかどうかを知りませんでした。そして応答を受け取らなかったということは、それを実行しておらず、送信もしておらず、つまり、インクリメントされたコミットインデックスを送信していなかったということです。ですからレプリカもそれを実行しなかったかもしれません。したがって、これがコミットされていなかった可能性は実際にあります。ですから、Raftは知らないにもかかわらず、ええと、Raftにとって合法的であり得るのです、ありがとう。
[1:18:36] もしRaftが実際に知っている以上のことを知っていたなら、このログエントリを落とすことは合法的であり得ます。なぜならコミットされていなかったかもしれないからです。しかし証拠に基づけば、この証拠からそれがコミットされていたことを反証する方法はありません。コミットされていた可能性があります。そしてRaftはそれがそうでなかったことを証明できません。したがって、それをコミット済みとして扱わなければなりません。いいですか、リーダーがそれを受け取ったかもしれず、appendエントリの返信を受け取った直後にクラッシュしたかもしれないからです。そしてクライアントに返信したのです。ですから、これを見ただけでは、どちらの可能性も排除できません。
[1:19:11] リーダーがクライアントに応答した場合、その場合にはクライアントがそれを知っているので、このエントリを捨てることはできません。あるいはリーダーが決して応答しなかった可能性もあり、その場合は、ええ、捨てることができました。ですから、そう仮定しなければなりません。それはコミットされていました。質問は? ええと、ああ……。
[1:19:46] いいえ、ありません——つまり、この状況では、サーバーが受け取る前にクラッシュしたのかもしれません。では、これを続けましょう。木曜日に。
英語の原文字幕を見る
[0:01] All right, let's get started. Mm-hmm. Today, and indeed today and tomorrow, I'm going to talk about Raft. Um, both because I hope it will be helpful for you in implementing the labs. And also because You know, it's just a case study in the details of how to get state machine replication correct. So, by way of introduction to the problem, you may have noticed a pattern in the fault tolerance systems that we've looked at so far.
[0:35] Um, One is that MapReduce replicates computation but The replication is controlled, the whole computation is controlled by a single master. Um, Another example I'd like to draw your attention to is that GFS, replicates data, right, as this primary backup scheme for replicating the actual contents of files, but It relies on a single master. to choose who the primary is for every piece of data. Another example, VMware FT replicates computational right on a primary virtual machine and a backup virtual machine. But in order to figure out what to do next, if one of them seems to fail, it relies on a single test and set server.
[1:20] to help it choose, to help it ensure that exactly one of the primary or the backup takes over if there's some kind of failure. So in all three of these cases, Sure there was a replication system but sort of tucked away in a corner in the replication system there was some scheme where a single entity was required to make a critical decision about. who the primary was in the cases we care about. So, I'm going to start with the first one. a very nice thing about having a single entity decide who's gonna be the primary?
[1:52] is that it can't disagree with itself. There's only one of it, make some decision, that's the decision it made. Um, But the bad thing about having a single entity decide, like, who the primary is, is that it itself has a single point of failure. And so you can view these systems that we've looked at as sort of... pushing the real heart of the fault tolerance machinery into a little corner. That is the single entity that decides who's gonna be the primary. if there's a failure. Now, This whole thing is about how to avoid split brain. The reason why we have to have, have to be extremely careful about making the decision about who should be the primary, if there's a failure, is that otherwise we risk split brain.
[2:35] Um, And just... make this point super clear, I'm going to just remind you. what the problem is and why it's a serious problem. So, supposing for example we're um, We want to build ourselves a replicated test and set server. That is, we're worried about the fact that VMware FT relies on this test and set server to-- choose who the primary is, so let's build a replicated test and set server. And I'm going to do this, it's going to be broken, it's just an illustration for why why it's difficult to get the split brain problem correctly. So, you know, we're gonna imagine we have a network, and maybe two servers, which are supposed to be replicas of our Test and set service connected and you know, maybe two clients that need to know who's the primary right now? or actually, maybe these clients in this case are a The primary and the backup.
[3:30] um, in VMware FT. So, If it's a test and set service, then both these databases, both these servers start out with their state, that is the state of this test and flight bag being zero. the one operation their clients can send is the test and set operation which is supposed to set the of the replicated service to one, so it should set both copies. and then return the old value. So it essentially acts as a kind of simplified lock server. Um, Thank you.
[4:01] OK. The problem situation? What we worry about, split brain arises automatically. when a client can talk to one of the servers but can't talk to the other. So we're imagining either that when clients send a request, they send it to both. Um, I'm just gonna assume that now, it almost doesn't matter. So let's assume that the protocol is that the client's supposed to send ordinarily any request to both servers, And Somehow, we need to think through what the client should do if one of the servers doesn't respond.
[4:32] or what the system should do if one of the servers seems to be unresponsive. Um, Thank you. So let's imagine now the client one can contact server one but not server two. How should the system react? One possibility is that we think, well, you know, gosh, We certainly don't want to just talk to client to server one, because that would leave the second replica inconsistent if we set this value to one, but didn't also set this value to one. So maybe the rule should be that a client is always required to talk to both replicas. to both servers. for any operation and shouldn't be allowed to just talk to one of them.
[5:05] So why is that the wrong answer? Supposing the rule is, oh, in our replicated system, the client's always required to Talk to both replicas. in order to make progress. Thank you. That's not fault tolerant at all. In fact, it's worse. It's worse. than talking to a single server because now the system has a problem if either of these servers is crashed or you can't talk to it. At least with a non-replicated server, you're only depending on one server. But here we have both servers have to be alive. If we require the client to talk to both servers then. Both servers have to be live. So we can't possibly require the client to actually you know, wait for both servers to respond.
[5:48] If we don't have fault tolerance, we need it to be able to proceed. So another obvious answer is that, If the client can't talk to both, well, it just talks to the one it can talk to and figures the other one's dead. So why is that also not the right answer? The troubling scenario is if the other server is actually alive. So suppose the actual problem we're encountering is not that the server crashed, which would be good for us, but the much worse issue that something went wrong with the network cable. And that this client can talk to, client one can talk to server one but not server two.
[6:27] And there's maybe some other client out there that can talk to server two but not server one. So, If we make the rule, that if a client can't talk to both servers, that it's okay in order to be fault tolerant, that it just talked to one, then what's-- inevitably going to happen. said, this cable's going to break, thus Cutting the network in half. I'm going to-- send a test and set request to server one, Server one will set its state to one Return the previous value of 0 to client 1. And so that means client 1 will think it has the lock.
[7:00] and if it's a VMware FT, server will think it can be takeover's primary. But this replica still has zero in it. Right, so now if client two also sends a test and set request, to You know, we-- tries to send them to both, sees that server one appears to be down, follows the rule that says, well, you just send to the one server you can talk to, then it will also think that Um. it acquired, client two will also think that it acquired the lock. And so now, You know, if we were imagining this test and set server was going to be used with VMware FT, we have, you know, Both.
[7:31] uh, replica, both of these VMware, uh, machines I think they could be primary by themselves. Um, without consulting the other server. So that's a complete failure. So with this setup and two servers, It seemed like we had this, we just had to choose, either you wait for both and you're not fault-tolerant, or You wait for just one and you're not correct. And the not correct version is often called split-brain. So. Everybody see this? Thank you.
[8:03] Mm-mm. Well. Um... So this was basically where things stood. until the late 80s. And But people did want to build replicated Systems. the computers that control telephone switches, or the computers that ran banks, you know. Those places are willing to spend a huge amount of money in order to have reliable service, and so they would replicate, they would build replicated systems, and the way they would deal The way that they would-- have replication but try to rule out split brain. It's a couple of techniques. One is They would build a network that could not fail.
[8:44] And so usually what that means, and in fact you guys use networks that essentially cannot fail all the time. the wires inside your laptop you know, connecting the CPU to the DRAM are effectively a network that cannot fail. between the-- between your CPU and DRAM. So, you know, with reasonable assumptions and lots of money, and that, you know, sort of carefully controlled physical situation, like you don't want to have a cable snaking across the floor that somebody can step on, you know, it's got to be carefully physically designed setup. With a network that cannot fail, you can rule out split-brain. It's a bit of an assumption, but with enough money people get quite close to this because If the network cannot fail, that basically means that the client can't talk to server two, that means server two must be down.
[9:31] because it can't have been the network malfunctioning. So that was one way that people sort of built replication systems that didn't suffer from split-brain. Thank you. Um. Another possibility would be to have some human beings sort out the problem, that is, don't automatically do anything, instead have the clients By default, clients always have to wait for you know, both replicas respond or something, I'm never allowed to proceed with just one of them. But you can, you know, call somebody's beeper to go off, some human being goes to the machine room and sort of looks at the two replicas and, either turns one off, to make sure it's definitely dead.
[10:08] or verifies that one of them has indeed crashed, and that the other is alive. And so you're essentially using the human as a as the tiebreaker, and the human is a you know. if they were a computer, it would be a single point of failure themselves. club. So for a long time, people used one or the other of these schemes in order to build replicated systems, and it's not, you know, They can be made to work. The humans don't respond very quickly. And the network that cannot fail is expensive, but it's not not doable. Um, But it turned out that you can actually build automated failover systems Um, that can work correctly in the face of flaky networks, of networks that could fail.
[10:50] that can partition. So this split of the network in half where the two sides operate but can't talk to each other, That's usually called a partition. Um. Thank you. Thank you. And the big insight that people came up with in order to build automated replication systems that don't suffer from split-brain is the idea of a majority vote. And so this is-- Thank you. Thank you. Thank you. a concept that shows up in like every other sentence practically in the Raft paper.
[11:24] It's a sort of fundamental-- um way of proceeding. The first step is to have an odd number of servers instead of an even number of servers. Like, one flaw here is that it's a little bit too symmetric. The two sides of the split here, they just look the same. They run the same software, they're going to do the same thing, and that's not good. But if you have an odd number of servers, Then, It's not symmetric anymore. Right. At least a single network split will be presumably two servers on one side and one server on the other side and they won't be symmetric at all.
[11:57] And that's part of what majority voting schemes are. appealing to. So, basic idea is you have an odd number of servers, in order to make progress of any kind, so in Raft, elect a leader, or cause a log entry to be committed, in order to make any progress at each step, You have to assemble a majority... of the servers, more than half, more than half of all the servers, in order to sort of approve that step, like vote for a leader, accept a new log entry and commit it. Um, So, you know, the most...
[12:29] uh... Straightforward way is to have two or three servers required to do anything. Um, One reason this works, of course, is that If there's a partition, There can't be more than one partition with a majority of the servers in it. That's one way to look at this. A partition can have one server in it, which is not a majority. Or maybe you can have two, but if one partition has two, then the other partition has to have only one server in it. and therefore will never be able to assemble a majority and won't be able to make progress.
[13:03] Um, And just... To be totally clear, When we're talking about a majority, it's always a majority out of all of the servers. not just the live servers. This is a point that confused me for a long time, If you have a system with three servers, and maybe some of them have failed or something, If you need to assemble a majority, it's always two out of three. even if you know that one has failed. The majority is always out of the total number of servers. um, There's a more general formulation of this. Because of majority voting system in which two out of three are required to make progress, it can survive the failure of one server.
[13:40] Right. Any two servers are enough to make progress. If you need to be able to, if you're, you know, you're worried about how reliable your servers are or God. you can build systems that have more servers, and so the more general formulation is If you have two f plus one servers, then you can withstand F failures. Bye. So if it's three, That means f is one. In a system with three servers, you tolerate F servers, F1 failure and still keep going.
[14:16] Thank you. Thank you. Thank you. All right. Often these are called quorum systems because the two out of three is sometimes held a quorum. Thank you. Okay, so one property I've already mentioned about these majority voting systems is that Um, At most one partition can have a and therefore if the network's partitioned, We can't have both halves of the network making progress. Another more subtle thing that's going on here is that Um, If you always need a majority.
[14:49] of the servers to proceed. And you go through a sort of succession of operations in which reach operation somebody assembled a majority like. you know, votes for leaders or Let's say votes for leaders for Raft. At every step, the majority you assemble for that step must contain at least one server that was in the previous majority. any two majorities overlap in at least one server. And it's really that property, more than anything else that Raft is relying on.
[15:22] Um, to avoid split brain. It's the fact that, for example, when you have a leader, a successful leader election, and a leader assembles votes from a majority, its majority is guaranteed to overlap with the previous leader's majority. So, for example, the new leader is guaranteed to know about the term number used by the previous leader. because its majority overlaps with the previous leader's majority and everybody in the previous leaders majority knew about the previous leaders term number. Similarly, anything the previous-- leader could have committed must be present in a majority of the servers in Wrapped, and therefore any new leader's majority must overlap at at least one server.
[16:01] with every committed entry. from the previous leader. This is a big part of Why it is that... Wrapped is correct. Any questions about... the general concept of majority voting system. Yeah? Is it also common to add servers? Like add the processing ? JONATHAN GRUBER: Is it possible to add servers? I think it's possible. It's possible, you know, section something, maybe six in the how to add or change the set of servers.
[16:41] It's possible. You need to do it in a long running system. If you're running your system for five, 10 years, you're going to need to replace the servers after a while. you know, one of them fails permanently, or you upgrade, or you move machine rooms to a different machine room. You really do need to be able to support changing sets of servers. So that's it. It certainly doesn't happen every day, but it's a critical part of this, or long-term maintainability of these systems. Um, And the RAF authors sort of pat themselves on the back There you have it.
[17:12] a scheme that deals with this, which as well they might because it's complex. Thank you. Thank you. All right, so using this idea, in about 1990 or so, there were two systems proposed at about the same time. that realize that You could use this majority voting system to kind of get around the apparent impossibility of avoiding split brain. by using, basically by using three servers instead of two, and taking majority votes.
[17:44] Um, in the one of these very early systems was called Paxos The Raft paper talks about this a lot. Um, And another of these very early systems was called view stamp replication. Ciao. abbreviated as VSR for view stamp replication. And even though Paxos is by far the more widely known system in this department, Raft is actually closer to design in design to view step by few stamp replications. which was invented by people at MIT.
[18:15] Um, And so there's sort of a long, many decade history of these systems and they only really came to the forefront and started being used a lot in deployed big distributed systems about 15 years ago. a good 15 years after they were originally invented. Okay, so... So let me talk about Rath now. Raft takes the form of a library intended to be included in some service application.
[18:50] And so if you have a replicated service, each of the replicas in the service is going to be some application code which receives RPCs or something, plus a raft library. And the raft libraries cooperate with each other Um, to maintain replication. So, a sort of software overview of a single-raft replica is that at the top we can think of the replica as having the application code. So it might be for lab three, a key value server. So maybe we have some key value server.
[19:22] And it has state, the application has state that raft is helping it manage, replicated state. And for a key value server, it's going to be a table of keys and values. Um... *knocking* The next layer down is a raft layer. So the key value server is going to make function calls into RAPT, and they're going to chit chat back and forth a little bit. raft keeps a little bit of state. You can see it in figure two. And for our purposes, really the most critical piece of state is that raft has a log of operations.
[20:01] Thank you. Okay. Thank you. Amen. And in a system with three replicas, we're actually going to have three servers that have exactly the same identical structure and hopefully the very same data sitting in. sitting at both layers. Thank you. Amen. Thank you. Thank you. Thank you. Thank you. Thank you.
[20:31] Thank you. Right. Outside of this, there's going to be clients. And the game is that So we have client one, client two, a whole bunch of clients. The clients don't really know, the clients are, you know, External code that needs to be able to use the service. and The hope is the clients won't really need to be aware that they're talking to a replicated service. That to the clients it'll look almost like it's just one server and they talk to one server. And so the clients actually send client requests to The key to the application layer.
[21:05] of the current leader, the replica that's the current leader in Raft. And so these are going to be application level requests for a database for a key value server, these might be put and get requests. put takes a key and a value and updates the table and get ask the service to get the current key, current value corresponding to Some key. So this has nothing much to do with Raft. It's just client-server interaction for whatever service we're building.
[21:39] Um, But once one of these commands gets sent from the request, gets sent from the client to the server, what actually happens is on a non-replicated server, the Application code would like execute this request and say update the table in response to a put. but not in a RAPT-replicated service. Instead, if assuming the client sends a request to the leader, what really happens is the application layer. simply sends the request, the client's request, down into the RAFT layer to say, "Look, here's a request.
[22:10] Please get it committed. into the replicated log and tell me when you're done. And so at this point, the rafts chit chat with each other. Um. until all the replicas or a majority of the replicas get this new operation into their logs So it is replicated, and then when it's And the leader knows that all of the replicas of a copy of this only then is wrapped send a notification up, back up to the key value layer saying, "Aha, that operation you sent me a minute ago, It's been now committed into all the replicas And so it's safely replicated and at this point it's okay to execute that operation.
[22:53] It's a raft. The client sends a request to the key value layer, QDialyLayer does not execute it yet. So we're not sure. because it hasn't been replicated. Only when it's in the logs of all the replicas. Bye. Then Raph notifies the leader, and now the leader actually executes the operation, which corresponds to... you know, for a put, updating the key value table for a get, reading the correct value out of the table, and then finally sends the reply back to the client.
[23:26] So that's an ordinary operation of the Thank you. . It's submitted if it's in a majority. And again, the reason why I can't be all is that if we want to build a fault tolerance system, It has to be able to make progress even if Some of the servers have failed. So-- Um, Yeah. It's committed when it's in a majority. Thank you. Yes. So before the leader executes the request markets, devalue properties.
[24:00] Um... that have been replicated. Thank you. Wow. - I'm sorry. Thank you. leaders Yeah, I got that. And so. In addition, when the operations finally committed, each of the replicas sends the operation up. Each of the wraths Library layer sends the operation up to the local application layer, and the local application layer applies that operation to its state. And so they all... So hopefully all the replicas seem the same stream of operations.
[24:31] they show up in these up calls in the same order, they get applied to the state in the same order, and you know, assuming the operations are deterministic, which they better be, Um, The state... of the replicated state will evolve. in identically on all the replicas. So typically this table is what the paper is talking about when it, Talks about state. Thank you. a different way of viewing this interaction and one that'll sort of notation that will come up a lot in this course is that Um, A sort of time diagram, I'll draw you a time diagram of how the messages work.
[25:12] So let's imagine we have a client, and Server one is the the leader, and we also have server two. Thank you. Server three, and time flows downward on this diagram. We imagine the client sending the original request. to server one Thank you. After that, server one's wrapped layer. Um, sends an append entry, it's RPC. Um, to each of the two replicas. Thank you. This is just an ordinary, let's say, put request.
[25:45] This is, these are PEND entries requests. Thanks. The server's now waiting for replies. from the servers, from the other replicas, as soon as replies from a majority, a ride back, including the leader itself. So in a system with only three replicas, the leader only has to wait for one other replica. to respond positively to an appendentary as soon as it assembles. positive responses from a majority. Um, the Leader executes the command, figures out what the, Answer is like forget.
[26:20] um and sends the reply back to the... And meanwhile, of course, you know, if S2 is actually alive, it'll, you know, Sendback gets response too, but we're not waiting for it. Thank you. It's useful to know in figure two. Thank you. All right, everybody see this? Thank you. This is the sort of ordinary operation of the system. No failures here. Oh, okay. Gosh, yeah. I like...
[26:53] I left out-- important step. At this point, the leader knows, oh, I got a majority of put it in their log, I can go ahead and execute it and reply yes to the client because it's Server two doesn't know anything yet. It just knows, well, you know, I got this request from the, but I don't know if it's committed yet. Depends on, for example, whether my reply got back to the leader. For all Server 2 knows, its reply was dropped by the network, Maybe the leader never heard the reply and never decided to commit this request. There's actually another stage, once the, Server.
[27:24] realizes that a request is committed, it then needs to tell the other replicas that fact. And Amen. So there's... Uh... There's an extra message here. Exactly what that message is depends a little bit on what else is going on. at least in RAF, there's not an explicit commit message. Instead, the information is piggybacked inside the next append entries that the leader sends out. The next append entries RPC it sends out for whatever reason.
[27:58] Like there's a, commit, leader commit or something field in that RPC. and The next time the leader needs to have to send a heartbeat or something, needs to send out a new client request because some different Client. request something, it'll send out the Um, New, higher things. leader commit value and at that point the, uh, Um, yeah. replicas will execute the operation and apply it to their state. Yes.
[28:29] Thank you. Thank you. Oh, yes. So this is a, This is a protocol that has quite a bit of chit-chat in it. Um, and it's not, Super fat. Indeed, you know, yeah, the client sends in a request, the request has to get to the server, the server talks to at least, you know, another... It sends out multiple messages, has to wait for the responses, sends something back. So there's a bunch of message round-trip times kind of.
[29:02] embedded here. would have made sense to the second part of the faculty. Thank you. Yeah, so... If... So, This is up to you as the implementer actually exactly when the leader, sends out the updated commit index. If-- Client requests a um, come back only very occasionally. then the leader may want to send out a heartbeat or send out a special append entries message.
[29:34] Um, If client requests come quite frequently, then it doesn't matter, If they come, you know, if there's a thousand arrive per second, then, geez, there'll be another one along very soon. And so you can piggyback. So without generating an extra message, which is somewhat expensive. you can get the information out on the next message you are going to send anyway. Um, In fact, I don't think the, time at which the replicas execute the request - It's critical because nobody's waiting for it, at least if there's no failures. If there's no failures, the replicas executing the request isn't really on the critical path.
[30:12] Like the client isn't waiting for them, the client's only waiting for the leader to execute. So it may not be that important. um It may not affect client perceived latency, sort of exactly how this gets staged. Um. Bye. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. All right. One question you should ask is why is the system so focused on logs? What are the logs doing?
[30:51] And it's sort of worth trying to come up with explicit answers to that. One answer to why the system is totally focused on logs. is that The log is, the kind of mechanism by which the leader orders operations. It's vital for these replicated state machines that all the replicas apply not just the same client operations to their start, but the same operations in the same order. But they all have to apply these operations coming from the clients in the same order. And the log, among many other things, is part of the machinery by which the leader assigns an order to the incoming client operations.
[31:32] you know, 10 clients send operations to the leader. At the same time, the leader has to pick Pick an order, make sure everybody, all the replicas obey that order. And the log is The fact that the log has numbered slots. is part of how the leader expresses the order it's chosen. Um, Thank you. Another use of the log is that between this point and this point, Server 3 has received an operation that it is not yet sure is committed. and it cannot execute it yet. It has to put this operation aside somewhere.
[32:06] until the increment to the leader commit value comes in. And so, another thing that the log is doing is that, on the followers, the log is the place where the follower sort of sets aside operations that are still tentative. that have arrived but are not yet known to be committed. And they may have to be thrown away, as we'll see. Um, So that's another use. On the sort of dual of that use on the leader side is that the leader needs to remember operations in its log because it may need to retransmit them.
[32:38] to followers. If some follower is offline, maybe it's something briefly happened to its network connection or something, misses some messages. The leader needs to be able to resend blog messages that any followers miss. And so the leader needs a place where I can set aside copies of messages of client requests, even ones that it's already executed. in order to be able to resend them to the client. I mean, we send them to replicas that missed miss that operation. And a final reason for all of them to keep the log is that at least in the world of figure two, If a server crashes and restarts and wants to rejoin um You really want a server that crashes to in fact restart and rejoin.
[33:20] the wrapped cluster, otherwise you're now operating with only two out of three servers and you can't survive any more failures. We need to reincorporate failed and rebooted servers, and the log is sort of where, what a server, a rebooted server uses. The log persisted to its disk. Because one of the rules is that Each Rath server needs to write its log to its disk, where it will still be after it crashes and restarts. That log is what the server uses, it replays the, operations in that log from the beginning to sort of create its state as of when it crashed.
[33:52] and then it carries on from there. So the log is also used as part of the persistence plan. as a sequence of commands to rebuild the state. Yes. So I'm wondering what scenarios would arise where the workers are trying to follow up with it. Uh... Well, ultimately, Okay, so the question is, Suppose the leader is capable of executing a thousand client commands a second and the followers are only capable of executing a hundred client commands per second. That sort of sustained rate at full speed.
[34:32] um The, so one thing to note is that the, the The replicas, the followers, acknowledge commands before they execute them. So the rate at which they acknowledge and accumulate stuff in their logs is not limited. So, you know, maybe they can acknowledge it, a thousand requests per second. If they do that forever, then they will build up. unbounded size logs because their execution rate falls will fall an unbounded amount behind the rate at which the leader has given the messages, sort of under the rules of our game.
[35:06] And so what that means is it will eventually run out of memory. At some point, after they have a billion, after they fall a billion log entries behind, they'll just like, they're called a memory allocator. for space for a new log entry and it will fail. Um, So yeah, and RAF doesn't, um RAP doesn't have the flow controls that's required to cope with this. So I think... in a real system, you would actually need probably piggybacked and doesn't need to be real time, but you probably need some kind of um, additional communication here that says, "Oh, here's how far I've gotten in execution.
[35:47] So that the leader can say, well, I'm too many thousands of requests ahead of the point at which the followers have executed. Yeah, so I think there's probably in a production system that you're trying to push to the absolute max. you might well need an extra message to throttle the leader if it got too far ahead. Thank you. Okay.
[36:33] - So the question is, If one of these servers crashes, It has this log that it persisted to dis, 'cause that's one of the rules of figure two. um So the server will be able to be just logged back from disk, but of course, That server doesn't know how far it got in executing the log. And also it doesn't know, at least when it first reboots, by the rules of Figure 2. It doesn't even know how much the log is committed. So the first answer to your question is that immediately after a restart, after a server crashes and restarts and reads this log, it is not allowed to do anything with the log.
[37:09] because it does not know how far the system has committed in its log. Maybe this log has a thousand uncommitted entries and zero committed entries for all So... If the leader dies, of course, that doesn't help either. Let's suppose they've all crashed. This is getting ahead of... It's getting a bit ahead of me, but we'll suppose they've all crashed, and so all they have is the state that was marked as non-volatile in figure two, which includes the log and maybe the latest term.
[37:43] Um, And so they don't know. So if there's a crash, if they all crash and they all restart, None of them knows. initially how far they had executed before the crash. So what happens is, they do leader election, one of them gets picked as a leader. And that leader, if you sort of track through what figure two says about how append entries are supposed to work. the leader will actually figure out as a byproduct of sending out the first heartbeat really.
[38:14] Um, It'll figure out what the latest point is basically that that Amen. all of the, that a majority of the replicas agree on their law. Because that's the commit point. Another way of looking at it is that once you choose a leader, through the append entries mechanism, the leader forces all of the other replicas to have identical logs to the leader. And at that point, plus...
[38:45] A little bit of extra, the paper explains. At that point, since the leader knows that it's forced all the replicas to have a have logs that are identical to it. Then it knows that, oh, all the replicas must also have a-- There must be a majority of of replicas with- that all those log entries in the logs which are now identical must also be committed because they're held on a majority of replicas. Um, And at that point, the leader-- append entries code described in figure two for the leader will increment the leader's commit point and and everybody can now execute the entire log from the beginning.
[39:22] and recreate their state from scratch. possibly extremely laboriously. Um... So that's what figure two says. It's obviously this re-executing from scratch is not very attractive, but That's what the basic protocol does. And we'll see tomorrow. version of this is more efficient, uses checkpoints and We'll talk about it tomorrow. Thank you. Okay, so this was a sequence in sort of ordinary, non-failure operation.
[39:53] Um, um... Another thing I want to briefly mention is what this interface looks like. You've probably all seen a little bit of it. due to working on the labs, but roughly speaking, if you have, let's say, this key value layer, with its state. and the raft layer underneath it, there's On each replica there's really two main pieces. of the interface between them. There's this... Um, method by which the key value layer can relay. If a client sends in a request, the key value layer has to give it to Rath and say, "Please, you know, fit this request into the log somewhere, and that's the start function.
[40:34] Um. that you'll see in raft.go. And really it just takes one argument, the client command. Thank you. The key value layer is saying, "Please, I got this command. Stick it into the log and tell me when it's committed." And the other piece of the, interface is that by and by, The raf layer will notify the key value layer that, aha, that operation that you sent to me in a start command a while ago, which may well not be the most recent start. A hundred client commands could come in and cause calls to start before any of them are committed.
[41:09] by and by Um, this-- upward communication is takes the form of a message on a Go channel that the Raph library sends on and the key value layer. is supposed to read from. Um. So there's this apply, Thank you. Thank you. It's called the apply channel, and on it you send an apply message. Thank you. I don't know. Thank you. Thank you. Thank you. this start and of course you need the Key value layer needs to be able to match up messages it receives on the Apply channel with calls to start that it made.
[41:47] Um, And so the start command actually returns enough information for that matchup to happen. It returns the index the start functions basically returns the index in the log where if this command is committed, which it might not be, it'll be committed at this index. Um, And I think it also returns the current term, and some other stuff we don't care about very much. And then this apply message is going to, contain the index. both the Command.
[42:20] Um. Thank you. Thank you. Thank you. Thank you. Thank you. and the index. And all the replicas will get these apply messages, so they'll all know, "Oh, I should apply this command." um figure out what this command means and apply it to my local state. And they also get the index. The index is really only useful on the leader so it can, figure out. what client requests we're talking about. Thank you. I'm curious about the following. The client is sending their request to the back, rock leader any place.
[42:59] at which-- clients by making a get-go. Right. about that. OK. OK. Um, I think I answered a slightly different question. Let's suppose the client sends any request in, Let's say it's a put or a get. It could be a put or a get. It doesn't really matter. I'll take it to get. Um, the point at which the So the client sends in again and waits for a response. The point at which the leader will send a response at all is after the leader knows that command is committed.
[43:40] So this is going to be a sort of get reply. Bye. *knocking* Bye. So the client doesn't see anything back. I mean it, and so, um, That means in terms of the actual software stack, That means that the key value, the RPC will arrive, the key value layer will call the start function. The start function will return to the key value layer But-- The key value layer will not yet reply to the client because it does not know if it's Actually, it hasn't executed the client's request now. It doesn't even know if it ever will.
[44:14] because it's not sure if the request is going to be committed. And the situation in which it may not be committed is if the key value layer, you know, gets a request, calls start, and immediately after start returns, it crashes. It certainly hasn't sent out its apply, pen messages, or whatever. Nothing's been committed yet. Um, So the game is start returns. time passes, the relevant, apply message corresponding to that client request appears to the key value server on the apply channel and only then and that causes the key value server to execute the request And-- Send a reply.
[44:52] Thank you. Thank you. Thank you. Thank you. Thank you. And that's like-- all this is It's very important when it It doesn't really matter if everything goes well. But if there's a failure, we're now-- At the point where we start worrying about failures, we'll be extremely interested in, if there was a failure, what did the client see? Um, Thank you. All right. And so one thing that has come up is... that's, um, all of you should be familiar with is that, at least initially, one interesting thing about the logs is that they may not be identical.
[45:30] There are a whole bunch of situations in which, at least for brief periods of time, the ends of the different... replica's logs may diverge, like for example, if a leader starts to send out a round of append messages, but crashes before it's able to send all of them out. That'll mean that some of the replicas that got the append message will append you know, that new log entry, and the ones that didn't get that pin message as RPC, won't have appended them. So it's easy to see that the logs are going to diverge sometimes. The good news is that, the The way Raft works actually ends up forcing the logs to be identical after a while.
[46:07] 'cause there may be transient differences, but in the long run, all the logs will sort of be modified by the leader until the leader ensures they're all identical and only then Um. Okay. I think the next, there's really two big topics. to talk about here for Raft. One is how leader election works, which is Lab 2. And the other is, how the leader deals with the different replicas logs, particularly after failure.
[46:38] So first I want to talk about leader election. Amen. Thank you. Question to ask is how come the system even has a leader? Why do we need a leader? that Part of the answer is you do not need a leader to build a system like this. It is possible to build. an agreement system by which a cluster of servers agrees on, you know, the sequence of entries in a log without having any kind of designated leader. And indeed, The original Paxos system, which the paper refers to, original Paxos did not have a leader.
[47:11] Um, So it's possible. The reason why Raft has a leader is basically that Um, There's probably a lot of reasons, but one of the foremost reasons is that you can build a more efficient in the common case in which all The servers don't fail. It's possible to build a more efficient system if you have a leader. Because with a designated leader, everybody knows who the leader is, You can basically get agreement on requests with one round of messages per request. Whereas leaderless systems have more of the flavor of, well, you need a first round to kind of agree on a temporary leader, and then a second round to actually send out the request.
[47:49] So, It's probably the case that use of a leader speeds up the system by a factor of two. Thank you. And it also makes it sort of easier to think about what's going on. Thank you. Um, Raft goes through a sequence of leaders, And It uses these term numbers in order to sort of disambiguate which leader we're talking about. It turns out the followers don't really need to know the identity of the leader. They really just need to know what the current term number is.
[48:20] Each term has at most one leader. That's it. critical property You know, for every term, there might be no leader during that term, or there might be one leader, but there cannot be two leaders. during the same term. Every term has at most one leader. Um, Thank you. Thank you. How do the leaders get created in the first place? Every... wrapped server. keeps this election timer, which is just a It's basically just a time that it has recorded that says, well, if that time occurs, I'm going to do something.
[48:55] um And something that it does is that if an entire leader election period expires, without the server having heard any message from the current leader then the server sort of assumes probably that the current leader is dead and starts an election. So we have this election timer. And if it expires, start an election. Thank you. .
[49:26] Thank you. Um, And what it means to start an election is basically that you increment the term the candidate, the server that's decided it's going to be a candidate and sort of force a new election, first increments this term because, you know, wants her to be a new leader, namely itself, And a term can't have more than one leader, so we've got to start a new term. in order to have a new leader. And then it sends out these request votes, RPCs.
[49:57] Thank you. I'm going to send out a full round of request votes. And you may only have to send out n minus one request votes, because one of the rules is that a new candidate always votes for itself. in the election. Um, So. One thing to note about this is that It's not quite the case that if a leader didn't fail, we won't have an election. or if the leader does fail, then we will have an election assuming any other server is up, because someday the other server's election timers will go off.
[50:28] But if the leader didn't fail, we might still, unfortunately, get an election. So if the network is slow or drops a few heartbeats or something, we may end up having election timers go off, and even though there was a perfectly good leader, we may nevertheless have a new election. So we have to sort of keep that in mind when we're thinking about correctness. Um, And what that in turn means is that if there's a new election, it could easily be the case that the old leader is still hanging around and still thinks it's the leader. Like, if there's a network partition, for example, And the old leader is still alive and well in a minority partition.
[51:02] The majority partition may run an election, and indeed a successful election, and choose a new leader. totally unknown to the previous leader. So we also have to worry about, you know, oh, what's that previous leader going to do since it does not know there was a new election? Thank you. Very much. Thank you. Thank you.
[51:43] So the question is, Are there, can there be pathological cases in which, for example, One way network communication can prevent the system from making progress. I believe the answer is yes. Certainly. So for example, if the current leader, If its network somehow half fails in a way the current leader can send out heartbeats but can't receive any client requests. then the heartbeats that it sends out, which are delivered because it's outgoing network connection works. It's outgoing heartbeats will suppress any other server from starting an election.
[52:20] But the fact that it's incoming network wire apparently is broken will prevent it from hearing and executing any client commands. It was absolutely the case that RAPT is not proof against all um sort of all crazy network problems that can come up. I believe the ones I've thought about, I believe are fixable in the sense that the We could solve this one by having a sort of requiring a two-way heartbeat in which if the leader sends out heartbeats but in which Followers are required to reply in some way to heartbeats, like as they are already required to reply.
[52:58] But if the leader stops seeing replies to its heartbeats, Then after some amount of time in which the season was replaced, the leader decides to step down. I feel like that's specific issue. can be fixed. and many others can too, but I, but, Yeah. you know You're absolutely right. Very strange things can happen to networks, including some that the protocol is not prepared for. Thank you. Thank you. Thank you.
[53:29] Okay, so we got these meter elections. We need to ensure that there is at most, at most, one leader per term. How does RAF do that? Well, RAF requires, in order to be elected for a term, RAF requires a candidate to get yes votes from a majority of the servers. The servers and each server will only cast one yes vote per term. So in any given term, you know, it basically means that in any given term, each server votes only once for only one candidate, Um, You can't have two candidates both get a majority of votes because Everybody votes only once.
[54:06] Um, So the majority's-- The majority rule causes there to be at most one winning candidate. Um, and So then we get at most one. candidate elected per turn. Um... And in addition, critically, the majority rule means that you can get elected even if some servers have crashed. If a minority of servers are crashed or unavailable, have network problems, we can still elect a leader. If more than half have crashed or are not available or are in another partition or something, then Actually, the system will just sit there trying again and again to elect a leader.
[54:46] and never elect one. if it cannot in fact, if they're not a majority of live servers. um Thank you. If an election succeeds, Everybody, it'd be great if everybody learned about it. 7 minutes or so. We need to ask ourselves how do all the parties learn what happened? The server that wins an election, assuming it doesn't crash, The server that wins election we'll actually see a majority or positive votes for its request vote from a majority of the other servers. The candidate that's running the election that wins it, the candidate that wins the election will actually know directly, I got a majority of votes.
[55:23] But nobody else directly knows who the winner was or whether anybody won. Um, So the way that the candidate informs other servers is that heartbeat. the rules in Figure 2 say, oh, if you win an election, you're immediately required to send out independentries. to all the other servers. Now, dependentries that heartbeat dependent entries doesn't explicitly say, I won the election, you know, I'm a leader for term 23. Um, It's a little more subtle than that. the way the information is communicated is that Um, No one is allowed to send out and append entries unless they're a leader for that term.
[56:02] So the fact that I'm a, you know, I'm a, Server and I saw, oh, there's an election for term 19. And then by and by, I send in append entries whose term is 19, That tells me that somebody, I don't know who, but somebody won the election. Um, so that's how the other servers know, is they were receiving append entries for that term. And that append entries also has the effect of, resetting everybody's election time. timer. So as long as the leader is up and it sends out heartbeat messages or append entries at least, you know, at the rate it's supposed to, Every time a server receives an append entry, it'll reset its selection timer and sort of suppress anybody from being a new candidate.
[56:46] So as long as everything's functioning, the repeated heart beats will prevent any further elections. Of course, if the network fails or packets are dropped, there may nevertheless be an But if all goes well, we're sort of unlikely to get an election. Um, This scheme could fail in the sense, well, it can't fail in the sense of electing. two leaders for a term, but it can fail in the sense of electing zero leaders for a term. Um, The sort of morning way it may fail is that if too many servers are dead or unavailable or have bad network connections. So if you can't assemble a majority, you can't be elected, nothing happens.
[57:22] Um, The more interesting way in which an election can fail is if Everybody's up. You know, there's no failures, no packets are dropped. But-- two leaders become candidate close together enough in time that they split the vote between them. or say three liters. Um, So supposing we have three leaders. Supposing we have a three replica system Um, All their election timers go off at the same time.
[57:53] Every server votes for itself. And then when each of them receives a request vote from another server, well it's already cast its vote for itself and so it says no. So that means that all three of the servers each get one vote each, nobody gets a majority, and nobody's elected. Um, So then-- Their election timers will go off again because The election timer is only reset if it gets an append entries, but there's no leader, They'll all have their election timers go off again. And if we're unlucky, they'll all go off at the same time. They'll all vote for themselves. Nobody will get a majority. uh So.
[58:24] So clearly, I'm sure you're all aware at this point, there's more to this story. And the way raft D-- makes the possibility of split votes unlikely, but not impossible, is by randomizing these election timers. So the way to think of it And the randomization, well, The way to think of it is that, so we have some timeline, I'm going to, um, draw events on. There's some point at which everybody received the last append entries.
[58:56] And then maybe the server died. Let's just assume the server sent out a last heartbeat and then died. Well, all of the followers have-- or reset their election timers when they received, at the same time, because they probably all received the append entries at the same time. They all reset their election timers. for some point in the future, to go off at some point in the future. they chose different random times in the future which then were gonna go off. So I suppose the dead leader is server one, So now server two and server three at this point, set their election timers for a random point in the future. Let's say server two set their, um, I'd like some timer to go off here.
[59:38] and server three set. It's election timer to go off there. and The crucial point about this picture is that assuming they pick different random numbers, One of them is first and the other one is second. Right? That's what's going on here. And the one that's first, assuming This gap is big enough. the one that's First, this election timer will go off first before the other one's election timer. as long as we're not unlucky, it'll have time to send out a full round of Vote requests.
[1:00:10] and get answers from everybody where everybody's alive before the second election. timer goes off from any other server. Um, So. Does everybody see? how the randomization desynchronizes these candidates. Unfortunately, there's a bit of art in setting the constants for these election timers. There's some sort of competing requirements you might want to fulfill. Um, So one obvious requirement is that the election timer has to be at least as long as the expected interval between heartbeats.
[1:00:48] This is pretty obvious that the leader sends out heartbeats every 100 milliseconds you better make sure, you know, there's no point in having the election timer anybody's election timer ever go off for 100 milliseconds. because then it will go off before we could even have expected a new append entry. So the lower limit is certainly the lower limit is one heartbeat interval. In fact, because the network may drop packets. You probably want to have the minimum election timer value be a couple of times the heartbeat interval. So for 100 millisecond heartbeats, you probably want to have the very shortest possible election timer be say, 300 milliseconds.
[1:01:25] three times the heartbeat interval. Um, So that's the sort of minimum is the... Um, See if the heartbeats are this frequent, you want the minimum to be a couple of times that or here. Um, so what about the maximum? You know, you're gonna presumably randomize uniformly over some range of times. You know, where should we set the-- kind of maximum. Thank you. that we're randomizing over. And there's a couple of...
[1:01:55] considerations here in a real system. um, you know, this maximum time, uh... affects how quickly the system can recover from failure because Remember, from the time at which the server fails, until the first election timer goes off, The whole system is frozen. There's no leader. You know, the client's requests are being thrown away because there's no leader. and we're not assigning a new leader even though you know Presumably these other servers are up.
[1:02:26] So the bigger we choose this maximum, the longer delay we're imposing on clients before recovery occurs. You know, whether that's important, depends on sort of how high performance we need this to be, and how often we think there will be, Failure. If failure's happening once a year, then who cares? Um, If we're expecting failures frequently, we may care very much. how long it takes to recover. Okay, so that's one consideration. The other consideration is that this gap That is the expected gap in time between the first timer going off and the second timer going off.
[1:03:03] Um, This gap really, in order to be useful, has to be longer than the time it takes for the candidate to assemble votes from everybody. That is... longer than the expected round trip time, the amount of time it takes to send an RPC and get the response. Yeah, maybe it takes 10 milliseconds. to send in RPC and get a response, get a response from, um, all the other servers. And if that's the case, we need to make maximum release long enough that there's pretty likely to be 10 milliseconds difference between the smallest random number and the next smallest random number.
[1:03:35] Um, Thank you. And for you, Um, the test code will get upset if you, uh, um Thank you. if you don't recover from a leader failure in a couple seconds. And so, just pragmatically, you need to tune this maximum down so that It's highly likely that. You'll be able to complete a leader election within a few seconds. That's not a very tight constraint.
[1:04:09] Any questions about the election timeouts? One tiny point is that, um, You want to... Choose new random timeouts. every time there's, every time you Every time I know-- resets its election timer. That is, Don't choose a random number when... server is first created and then reuse that same number over and over again. Because you make an unlucky choice that is You choose the same.
[1:04:39] one server happens by ill chance to choose the same random number as another server. That means that you're gonna have split votes over and over again. forever. So that's why you want to almost certainly choose a different, a new, a fresh random for the election timeout value every time You reset the timer. Thank you. All right, so, a final issue about leader election. Suppose we are in this situation where the old leader's partitioned.
[1:05:10] You know, the network cable is broken, and the old leader is sort of out there with a couple clients. and a minority of servers. There's a majority in the other half of the network, and the majority in the new half of the network elects a new leader. What about the old leader? Why won't the old leader... Thank you. cause incorrect execution. Thank you. Maybe it's Yeah, right there.
[1:05:56] That's how that's gonna... - I'm glad to. Bye. and that's all done. God. Thank you. Yeah. two potential problems. Or one sort of non-problem is that if there's a leader off in another partition and it doesn't have a majority, then the next time a client sends it a request, Um, that leader that, you know, an abarctuation with a minority, yeah, it'll send out append entries, but Because it's in the minority partition, it won't be able to get responses back from a majority of the servers, including itself. And so it will never...
[1:06:34] commit the operation, it'll never execute it. It'll never respond to the client. saying that it executed it either. And so that means that, yeah, an old server off in a different partition People may, clients may send a request, but they'll never get responses. um, So no client will be fooled into thinking that the, that old server executed anything for it. The other sort of more tricky issue, which actually I'll talk about in a few minutes, is the possibility that before a server fails, it sends out append entries to a subset.
[1:07:14] of the servers. and then crashes before making a commit decision. And that's a very interesting question, which um We'll probably spend a good 45 minutes talking about that. And so, actually, before I turn to the back, topic in general. more questions about leader election. Thank you. OK. um Okay, so how about the contents of the logs and how in particular how a newly elected leader possibly picking up the pieces after an awkward crash of the previous leader, How does a newly elected leader sort out the possibly divergent logs on the different replicas?
[1:08:01] in order to restore sort of consistent state in the system. Um, All right, so the first question is, What can things, this whole topic is really only interesting after a server crashes, right? If the server stays up, then relatively few things can go wrong. If we have a server that's up and has a majority, you know, during the period of time when it's up and has a majority, Um, just tells the followers what the log should look like.
[1:08:36] And the followers are not allowed to disagree. They're required to accept. They just do by the rules of figure two if they've been more or less keeping up. You know, they just take whatever the leader sends them, and append entries, and append it to the log, and obey commit messages, and execute. Hardly anything to go wrong. The things that go wrong in rap go wrong when the old leader crashes sort of midway through you know, sending out messages or a new leader crashes, you know, sort of just after it's been elected, Um... before it's done anything very useful.
[1:09:08] So, one thing we're very interested in is what can the logs look like after some sequence of crashes? Um... Okay. Here's an example. So then we have three servers. Thank you. Thank you. Um, And the way I'm gonna draw out these diagrams, 'cause we're gonna be looking at a lot of, sort of situations where the logs look like this, and we're going to be wondering, is that possible, and what happens if they do look like that? So, my notation's going to be, I'm going to write out log entries for, um, Each of the servers sort of aligned to indicate slots.
[1:09:46] corresponding slots in the log. And the values I'm gonna write here are the term numbers rather than client operations. I'm going to, you know, this is slot one, this is slot two. Um, Everybody saw a command from term three in slot one, Server 2 and Server 3 saw command from also from term three, In the second slot, the server one has nothing there at all. Um, And so the question for this, like the very first question is, can this arrive?
[1:10:18] Could this... set up Arise and how? Oh. How? Thank you. Yeah, so . Thank you. So.
[1:11:03] So maybe server three was the leader for, just repeating what you said, maybe server three is the leader for term three. It got a command that sent out to everybody. Everybody received the dependent as the log. And then I got a server three, Got a second request from a client. and Maybe it sent it to all three servers, but the message got lost on the way to server one, or maybe server one was down at the time or something, and so only server two Well, the leader always appends new commands to its log before it sends out append entries. Um, and maybe the append entry RPC only got to server two. So this situation, you know, It's like the simplest situation in which actually the logs are now different.
[1:11:38] And we know how it could possibly... arise. And so if server three, which is the leader, should crash now, you know, the next server they're going to need to make sure server one Well, First of all, If server 3 crashes, or we get an election and some other leader is chosen, You know, two things have to happen. The new leader... It's got to recognize that This. Um, a command could have committed. It's not allowed to throw it away. and it needs to make sure server one fills in this blank here with indeed this very same command that everybody else had in that slot.
[1:12:15] Um, Thank you. All right, so after a crash, somebody, you know, a server suppose, another way this can come up is server three might have sent out the append entries to server two, but then crashed before sending the append entries to server three. So if we're electing a new leader, it could be because We got a crash. before the message was sent. All right, here's another scenario to think about. Um, Three servers again. Thank you. Thank you. Thank you. Um, Now I'm going to number the slots in the lawn.
[1:12:47] So we can refer to them. Um, We've got slot 10, 11, 12. Thank you. 13. Again. That's... Thank you. same setup except Now we have in slot 12, we have Server 2 as a command from term four and server three has a term command from term five. Thank you. Thank you. So-- Before we analyze these to figure out what would happen, what would a server do if it saw this, we need to ask Could this even occur?
[1:13:25] Sometimes the answer to the question, oh geez, what would happen if this configuration arose? Sometimes the answer is, It cannot arise, so we do not have to worry about it. um So the question is, Could this arise and how? Yeah. say no, because we have a lot of . Okay. Thank you. Thank you. Um, All right.
[1:14:00] And any-- All right. Thank you. The first situation happens. Amen. watching. friends. - Now, Troy. Bye. Roger. Thank you. What? Uh... Right, sensei.
[1:14:32] guys. Thank you. - Oh my God. All right. back up. Yeah. How far? So let me just repeat that. Brief. we know this configuration can arise, and so the way we can then get a four and a five here is, Let's suppose in the next leader election, server 2 is elected leader.
[1:15:09] Now for term four. Select the leader. You get a request from a client, it appends it to its own log and crashes. So now we have this. Right, we need a new election because the leader just crashed. Now, in this election, Thank you. And so now we have to ask whether who could be elected, or we have to keep in the back of our heads, oh gosh, who could be elected? Um, so we're gonna claim server three could be elected. The reason why it could be elected is because it only needs request vote responses from a majority. That majority is server one and server three.
[1:15:41] You know, there's no problem, no conflict between these two logs. So server three can be elected for term five, get a request from a client. appended to its own log and crash. And that's how you get this. uh, this configuration. So you need to be able to-- Bye. to work through these things. in order to get to the stage of saying, yes, this could happen, and therefore, Raft must do something sensible, as opposed to, it cannot happen. Because some things can't happen.
[1:16:12] Um, Thank you. All right, so... Um, So what can happen now? We know this can occur. Hopefully we can convince ourselves that Raft actually does something sensible. Now, As for the range of things, before we talk about what Raph would actually do. We need to have some sense of what would be an acceptable outcome.
[1:16:47] Right? and just eyeballing this, Um, We know that The command in slot 10, since it's known by all All the replicas, it could have been committed. so we cannot throw it away. Similarly, the command in slot 11, since it's in a majority of the replicas, it could, for all we know, have been committed, so we can't throw it away. The command in slot 12, however, neither of them could possibly have been committed. So we're entitled. We don't know, we haven't Looked at what Raft will actually do, but Raft is entitled to drop both of the even though it is not entitled to drop in either of the commands in the 10 or 11.
[1:17:26] Um, This is an entitled drop. It's not required. to drop either one of them. And we know it certainly must drop one, at least one, because You have to have identical log contents in the end. This could have been committed. the We can't tell by looking at the logs. exactly how far the leader got before crashing. So one possibility, is that for this command or even this command, One possibility is that a leader send out the append messages with a new command and then immediately crashed.
[1:18:04] So it never got any response back because it crashed. So the old leader did not know if it was committed. And if it didn't get a response back, That means it didn't execute it and it didn't send out but, you know, it didn't send out the incremented commit index. And so maybe the replicas didn't execute it either. So it's actually possible that this wasn't committed. So, Even though Raft doesn't know, Um, It could be legal for Raft Thank you.
[1:18:36] If RAP knew more than it does know, It might be legal. to drop this log entry, because it might not have been committed. but because on the evidence, There's no way to disprove it was committed based on this evidence. It could have been committed. and Raft can't prove it wasn't. So it must treat it as committed. Right, because the leader might have received it, might have crashed just after receiving the append entry replies. and replying to the client. So just looking at this, we can't rule out the possibility either possibility.
[1:19:11] that the leader responded to the client, in which case we cannot throw away this entry because a client knows about it. Or the possibility the leader never did, and yeah, we could. you know So we have to assume that. It was committed. Question? . um, Uh...
[1:19:46] No, there's no--I mean, in this situation, maybe the server crashed before getting the All right, let's continue this. on Thursday.
Vidleafワークベンチで開く
トランスクリプトを検索し、行を選択し、タイムスタンプ付きの引用をコピーし、翻訳します。
帰属
MIT 6.824: Distributed Systems(https://www.youtube.com/@6.824)による「講義6: フォールトトレランス: Raft(1)」、CC BY 3.0(https://creativecommons.org/licenses/by/3.0/)の下でライセンスされています。ソース動画: https://www.youtube.com/watch?v=64Zp3tzNbpE。このページは、段落区切りとタイムスタンプを加えた動画のテキスト文字起こしです。制作者はVidleafと提携しておらず、Vidleafを推奨していません。VidleafはAIによる句読点とAI生成の要約を追加しました。元の文言はこのページで引き続き参照できます。
あなたは制作者または権利者ですか?訂正や削除をリクエストする:copyright@vidleaf.app(これらのページについてを参照)。
最終更新