緑の小さな点=ハートビート、紫=投票依頼(RequestVote)、白=投票。タイムアウトはノードごとにランダムなので、たいてい1台だけが先に立候補して一発で決まります。まれに同時立候補で票が割れても、次のランダムタイムアウトでやり直すだけ。落ちた旧リーダーは数秒後に復帰しますが、より高い term を見て黙って従います。
POINT — 同じ term にリーダーは高々1人
各ノードは 1つの term につき1票しか投じない。そして当選には過半数が要る。どの2つの過半数も必ず1台以上重なるから、同じ term で2人が当選することは数学的にあり得ない。term は「論理的な年号」で単調に増え、自分より高い term を見たら即座に従う(リーダーでも退位する) — この2つが Raft の安全性の土台。
過半数 = ⌊N/2⌋ + 1
N=5 なら 3票。どの2つの過半数も必ず重なるので、同じ term に2人のリーダーは生まれない
ネットワークが割れて、旧リーダーが少数派に取り残されたとします。旧リーダーは自分が置き去りにされたことに気づけず、書き込みを受け付け続けます — しかし過半数の ACK が集まらないので永遠にコミットできません。一方、多数派側ではタイムアウトから新しい選挙が起き、より高い term のリーダーが誕生してコミットを進めます。分断が直ると、旧リーダーは高い term を見て身を引き、コミットできなかった書き込みはリーダーのログで上書きされます。
分断と復旧 — 少数派のリーダーはコミットできない
分断中に「書き込む」を押すと、少数派の旧リーダー S1 は受け付けはするものの、エントリは破線(未コミット)のまま。多数派側の新リーダーはすぐコミット(実線)します。分断を解消すると、S1 は高い term のハートビートを受けて退位し、未コミット分は赤くフラッシュして新リーダーのログに置き換わります(クライアントにはエラーか再試行として見えます)。
セルの色は term(t1/t2/t3)。フォロワーは term 2 のまま余計なエントリを2件書いてしまった状態です。照合が index 5 で一致した瞬間、それ以降が削除され、リーダーの3件で上書きされます。実装では「食い違った term とその最初の index」をヒントで返し、1 term ぶんまとめて飛ばす高速化が定番です。