今日のゴール
- Raft合意アルゴリズムの概念を理解する
- 強整合性が必要なケースを知る
- NindaでのRaft使用方法を学ぶ
なぜRaftが必要か
CRDTは結果整合性を提供しますが、以下のケースでは強整合性が必要です:
| ユースケース | 問題になる理由 |
|---|---|
| 金融取引 | 残高の一時的な不整合は許容できない |
| 在庫管理 | 過剰販売を防ぐ必要がある |
| 設定変更 | クラスタ全体に即座に反映が必要 |
| 分散ロック | 排他制御が正確でないと破綻 |
Raftの基本概念
Raftは合意アルゴリズムです。複数ノードが同じ決定を下すことを保証します。
3つの状態
| 状態 | 役割 |
|---|---|
| Follower | リーダーに従う(初期状態) |
| Candidate | リーダー選挙に立候補 |
| Leader | クライアント要求を処理、ログを複製 |
リーダー選出
リーダーがいなくなると、自動的に新しいリーダーが選出されます。
ポイント:
- 過半数(majority)の投票が必要
- タイムアウトはランダム化して衝突を防止
ログレプリケーション
クライアントの要求はログとして複製されます。
| ステップ | 説明 |
|---|---|
| 1. Append | リーダーがログに追記 |
| 2. Replicate | フォロワーに送信 |
| 3. ACK | 過半数からACKを受信 |
| 4. Commit | ログをコミット、状態に適用 |
| 5. Response | クライアントに応答 |
NindaでのRaft使用
import ninda/distributed/consensus
# Raftノードを作成
let raft = newRaftNode("node-1", @["node-2", "node-3"])
# 開始
await raft.start()
# リーダーかチェック
if raft.isLeader():
# 強整合性での書き込み
let result = await raft.proposeWrite(
toTuple(strVal("critical"), intVal(100))
)
if result.committed:
echo "Write committed to majority"
await raft.stop()
注意点
- 書き込みはリーダーのみが処理
- フォロワーに書き込むとリダイレクトまたはエラー
- 過半数のノードが必要(3ノードなら2台以上)
障害時の動作
| 障害 | 動作 |
|---|---|
| Follower障害 | 他ノードで継続(過半数あれば) |
| Leader障害 | 新Leader選出後に継続 |
| ネットワーク分断 | 多数派でサービス継続 |
| 過半数未満 | 書き込み不可(読み取りのみ) |
CRDTとRaftの使い分け
| 観点 | CRDT | Raft |
|---|---|---|
| 遅延 | 低い(ローカル応答) | 高い(過半数ACK待ち) |
| 可用性 | 高い(単独でも動作) | 過半数必要 |
| 整合性 | 結果整合 | 強整合 |
| スループット | 高い | 中程度 |
| 用途 | 一般データ | クリティカルデータ |
選択の指針
まとめ
学んだこと
| トピック | ポイント |
|---|---|
| Raft | 強整合性のための合意アルゴリズム |
| Leader選出 | 障害時の自動回復 |
| ログレプリケーション | 過半数への複製で一貫性を保証 |
| 使い分け | クリティカルデータにはRaft |
いつ使うか
| 場面 | 推奨 |
|---|---|
| 金融取引 | Raft |
| 在庫管理 | Raft |
| 分散ロック | Raft |
| ログ収集 | CRDT |
| メトリクス | CRDT |
演習問題
問題19-1: リーダー選出シミュレーション
3ノードクラスタを起動し、リーダーノードを停止して新しいリーダーが選出されることを確認してください。
ヒント
- 3つのターミナルで3ノードを起動
-
isLeader()でリーダーを特定 - リーダーを
Ctrl+Cで停止 - 残り2ノードで再選出を確認(数秒かかる)
- 新リーダーで
proposeWriteが成功することを確認
問題19-2: 過半数テスト
3ノードクラスタで2ノードを停止し、残り1ノードでは書き込みができないことを確認してください。
ヒント
- 3ノード起動後、2ノードを停止
- 残り1ノードは過半数(2以上)を満たせない
-
proposeWriteがタイムアウトまたはエラーになる - 読み取り(ローカルデータ)は可能な場合がある
問題19-3: ハイブリッドアーキテクチャ
CRDTとRaftを組み合わせたアーキテクチャを設計してください。一般データはCRDT、クリティカルデータはRaftで処理します。
ヒント
- 2つのスペースを用意:
general(CRDT)とcritical(Raft) - タプルの種類に応じて書き込み先を振り分け
- 例:
("log", ...)はCRDT、("balance", ...)はRaft - ルーティングロジックを実装
前回: CRDT入門 | 目次 | 次回: クラスタ構成