More Related Content More from Sho Nakazono (11) 詳説データベース輪読会: 分散合意その22. 14.4 Raft
• (Paxosにくらべて) 理解しやすく実装しやすい合意アルゴリズム.
• NSDIのReviewerは “Paxosを理解できるのは世界で5人もいないだろう” と述べていた.
• Raftのauthorsはpaxosをある程度理解して,paxosのforkを作るまで1年かかった
• USENIX ATC’14 にて “In Search of an Understandable Consensus Algorithm” という論文で発表された.
• そこに至るまでに3年間rejectされ続けたらしい.
• NSDI 2013, SOSP 2013, NSDI 2014…
• “理解しやすく実装しやすい” がContributionとして弱かったとか.
• 論文のほうも,5章に入るまでずっとイントロのような感じの記述が続いていて,苦労が伺える
• リファレンス実装は “LogCabin” として公開された.ソフトウェアとしては etcd, CockroachDB, Consul などが使っている.
• https://github.com/logcabin/logcabin
4. 14.4 Raft: Properties
1. Safety:
• ビザンチン障害を除く,パケットロス,ネットワーク断,遅延,duplication, reordering に対応できる.
2. Available:
• (N/2)+1台までの障害に対応する可用性がある.
3. Timing:
• 実時間的なタイミングがプロトコルに含まれない.
• これを含んでいると,最悪の場合,可用性に問題がある.
4. Performance:
• 過半数のノードから応答が得られた時点で,リクエストが完了する => 遅いノードに性能が律速されない
6. 14.4 Raft
• プロトコルは Atomic Broadcast/Multi-Paxosと類似点がある
• 単一のリーダーを選出し,アトミックな決定を行い,メッセージの順序を確定する点が類似して
いる
• 参加ノードの役割は3つ(次ページ).
• 全てのノードに共通する要素として, Replicated State Machine を使う.
• 各ノードで,ステートマシンが実行する一連のコマンドのログを格納する
• 同じ順序で同じログを適用すれば,ステートマシンが同じ出力を返す
• Failure modelは Fail-stop + delayed/lost messages
7. 14.4 Raft: Replicated State Machine
1. クライアントはサーバに要求を送信する.
2. コンセンサスアルゴリズムがログを管理する.
3. ログを順序通りに実行すると,同じステートマ
シンが得られる.
※ ステートマシンがdeterministicである前提がある.
障害が発生した場合にも,同じログがすべてのノード
で得られるのであれば,単一のサーバとして透過的に
扱える,というのが Replicated State Machine.
8. 14.4 Raft: Novel Features
• Raftの(他の合意アルゴリズムと比較した際の)特徴は以下
1. Strong leader
• リーダの役割が強い.例えば,ログはリーダから他のノードにのみ流れる.
• ログの流れがシンプルで,理解しやすい.
2. Leader election
• リーダ選出の仕組みにrandomized timerを使用している.
• 他の合意アルゴリズムにも必ず登場する heartbeat の仕組みにほんの少しの修正を加えるだけでよ
3. Membership changes
• ノードの追加/削除などメンバシップの変更に joint consensus アプローチを用いている.
• 変更前/変更後で大部分のcon
fi
gurationを共有するというもので,変更を行いながらクライアントの要求を受け付けられる.
9. 14.4 Raft: Nodes
• 参加ノードの役割は以下の3つ
1. Follower
• ログエントリを永続化する受動的な参加ノード.Paxosにおけるアクセ
プタ/ラーナーと類似.
2. Candidate
• Follower が立候補するとなる役割.過半数の投票を得るとLeader にな
る.立候補のトリガはタイムアウト.
3. Leader
• クライアントの要求を処理する.任期(term)がある.基本的に再任
される.
• 各サーバの通信の際には必ず自身が観測する最大のtermを送る.
• 自分が最新ではないtermに属していると気づいたleader/candidateは
followerに戻る.
10. 14.4 Raft: RPC
• Raftは2つのRPCからなる.(# 実質3つでは?)
1. AppendEntries RPC
ログの送付を行う.leaderからfollowerに流れる.
ログが空の場合,leaderからのハートビートとして機能する.
i.e., ハートビートが送られてくる,ということは,「俺がleaderだぞ」という意味.
2. RequestVote RPC
Leader election の開始を告げる.candidateから送られてくる.
これを受け取った場合, termが最新ならば,誰かひとりに投票: `VoteGranted` をtrueにしてレスポンスする.
11. 14.4 Raft: Leader Election
• リーダは任期中,heartbeatを他のノードに送り続ける.
• Heartbeatがタイムアウトした際,フォロワーはtermをincrementして,自身がCandidateとなり,新たな任期を開始する.
• RequestVote RPC を発行し,全ノードに投票を募る.
• RequestVote RPCを受け取った場合,RPCについている任期が自分と同じ & 自分と同じログを全て持っている
CandidateからのRPCであれば, voteGranted = true にしてレスポンスする.そうでない場合は,棄却する.
• 誰かが選挙で勝つか,新たな投票が始まるまで続行.
• 過半数の投票を得たノードは,他のノードにハートビートを送り,投票の終了を知らせる.
• 同時に複数のCandidateが起こりうるし,複数のtermが存在しうる.無限に投票を繰り返す可能性がある.
• これを解決するのが,randomized timeout.
12. 14.4 Raft: Randomized Timeout
• RaftはCandidateが同時に起こって投票が無限に継続するのを防ぐため,150-300ms の選挙タイ
ムアウトを各サーバにランダムに割り振る.
• タイムアウト中は,candidateになれない.
• 投票が割れても,最速でタイムアウトを抜けるサーバが次のCandidateになり,他のサーバが
タイムアウト中に RequestVote RPCを発行できるので,優先権がついた形になり,無限に投
票を繰り返す可能性が下がる.
• もともとはrankingにしようとしていたが,availabilityの問題からretry形式にした.
Raft uses randomized election timeouts to ensure that split votes are rare and that they are resolved quickly. To
prevent split votes in the
fi
rst place, election timeouts are chosen randomly from a
fi
xed interval (e.g., 150–300ms).
13. • タイムアウトの時間設定によって,リーダ不在の時間が変化す
る,という実験.
• 上図: small amount randomization
• 下図: high amount randomization
タイムアウトの時間が同じ(150ms-150ms) の場合,80%程度のケー
スで100000ms (1分半以上) リーダ選出にかかることになる.
リーダ不在の時間だけを見ると12-24ms が一番良さそうだ
が・・・?
> However, lowering the timeouts beyond this point violates Raft’s
timing requirement: leaders have di
ffi
culty broadcasting heartbeats
before other servers start new elections. This can cause
unnecessary leader changes and lower overall system availability.
We recommend using a conservative election timeout such as 150–
300ms; such timeouts are unlikely to cause unnecessary leader
changes and will still provide good availability.
リーダが細かく切り替わっていくだけで,リクエストを処理できて
はいない,ということ?
14. Raft: AppendEntries RPC
• Leaderが決定している間は,クライアントからの要求を処理できる.
1. どのノードも,クライアントからの要求をLeaderに転送する
2. Leaderのローカルログにエントリを追記する
3. Leaderから全フォロワーにAppendEntries RPCを送信
4. 過半数のレスポンスが得られたらCommitted マークをLeaderのログに付ける
5. クライアントにCommittedを応答する.
• この後でも,全てのフォロワーからレスポンスが得られるまで,無制限に再送信する.
6. Committed マークが付いたことをFollowerに知らせる (AppendEntries RPCを再送).
15. 14.4 Raft: Log Matching Property
• 前者: ログエントリのインデックスと任期が同じならば,必ず同じ操作
• 後者: そのようなentriesがあるならば,それ以前のログも全て同じ.
Raft はこの Log Matching Propertyを提供している.これによって,一貫性を維持するための処理が簡単かつ理解しやすくなる.
# 例えば,一定期間sleep/faultしていたとしても,”index 3のitemはterm 4 のもの” という AppendEntries RPCを受け取っただけで,自分の持っ
ているエントリに不足がないか判断できる
A. index 3, term 4 のログを持っている => 一定時間死んでいたけど,ログはすべて正しいものを持っている
B. Index 1 までしか持ってない! => 無限再送される AppendEntries RPCを待てば,いつか う.
C. Index 3は term 4ではない => サーバ構成が変更されたことが検出できる.
• If two entries in different logs have the same index and term, then they store the same command.
• If two entries in different logs have the same index and term, then the logs are identical in all preceding entries.
17. 14.4 Raft: Committing Entries From Previous Terms
• AppendEntries RPCで過半数にログを複製したが,committedと通知する前に
Leaderがcrashした場合,新しいLeaderはこれをcommittedだと判断できる.
• 過半数にログを複製してあると,そのログを持っているノードしか次の選挙に勝て
ない.そして,選挙に勝ったleaderのローカルログはcommittedだとみなされる.
a. S1 が 2台に term 2を複製,そしてcrash
b. S5 が term 3 のleaderに,そしてcrash
c. S1 が復帰して新たなterm 2 を過半数に送付できた場
合,過半数が取れているので,term 3 を持っている
ノード (S5) は選挙に勝てない.必ず (e) になる
d. 逆に, term 3 が先に過半数に送付できた場合,選挙に
勝つので, term 2 は棄却される
18. 14.4 Raft: Cluster Membership Changes
• サーバ構成をオンラインで変更すると,選挙やログ複製の処理も一貫性を失う.
• サーバ構成をアトミックに切り替えることは不可能なため.
• 例えば,2つのリーダが同じtermに同居する,ということもありえてしまう.
• Raftはオンラインでサーバ構成を変更できるよう, joint consensus アプローチを作った.
19. 14.4 Raft: Joint Consensus
• Raftでは,構成を変更するという処理を,ログエントリとして扱う.
• は旧構成. は新構成.
• は,旧構成の過半数と新構成の過半数,両方を使う
• 構成変更のために,まず をコミットする.
• その次に をコミットする.
• に自分が存在しないノードは, のAppendEntries RPC
を見たら,即シャットダウンできる
• エントリがcommitされているか否かに依らず,持っている最新のエン
トリを使う.
• がcommitされていなくとも, を使う.
• を使っているleaderがいる => 既に はコミット済み
• => 単独でコミットできるログは存在しない => 安全
Cold Cnew
Cold,new
Cold,new
Cnew
Cnew Cnew
Cnew Cnew
Cnew Cold,new
Cold
20. 14.4 Raft: Joint Consensus
• いくつかの問題/最適化/細かいアプローチがある.
• 新規に追加されたノードは,これまでのログを全て反映しきるまで投票に参加できないので,足を引っ張る
ことになる.そのため,”non-voting members” になってログだけを受け取ることができる.
• に自分が含まれていないリーダは, がコミットされるまでは動き続ける.
• に自分が含まれていないノードは, AppendEntries RPC (heartbeat) を受け取れないため,タイムアウ
トが発生したとみなして他のサーバに RequestVote を行ってしまう.
• これに対処するため,各ノードは,現在のリーダから指定されたタイムアウト時間がすぎるまでは,
RequestVote RPCを棄却する.
• # この「タイムアウト時間の指定」がどこで行われるのかわからない. AppendEntries RPC?
Cnew Cnew
Cnew
21. 14.4 Raft: Misc
• ログが単調増加するため,スナップショットを使う.
• リーダの持つログは常に最新なので,リーダに作成させるのが簡単.
• Raft のゴールは Linearizable & Exactly-Once. しかしcrashした場合など,何回か同じクライアントの命令がステート
マシンに対して実行されうる.
• クライアントの命令にserial numberを割り振って,ステートマシンに記録しておけばOK.
• Read-only の命令はログを追加しないのでフォロワーが即実行できる? -> できない
• リーダ以外,最新のデータを持っている保証はない
• そして,リーダですらも知らないうちに新しい任期のリーダが誕生している可能性がある
• これに対処するために,Read-only 命令であっても書込みと同様に扱う. no-op 命令を含むログとしてコミット.
23. 14.5 ビザンチン合意
• これまでの合意アルゴリズムはすべて非ビザンチン障害が前提.
• 非ビザンチン障害を前提にすると,参加ノードの数やコミットまでのRTTを減らせる.
• ビザンチン障害を前提にすると,色々と難しい.
• 悪意ある振る舞い,バグ,設定ミス,ハードウェア異常,データの破損など
• あるメッセージが正しいかどうかについて検証するため,クォラム内の各ノードが相互
通信する必要があり, のメッセージが必要になる.
• この章では, Practical Byzantine Fault Tolerance (PBFT) について議論する.
N2
24. 14.5 PBFT
• PBFTの前提:
• Independent node failures: 障害は個別に発生する.システム全体が乗っ取られること
はない
• Weak synchrony: 障害が発生することはあるが,無限にではなく,いつかは復旧される
• Encrypted messages: ノード間の通信はすべて暗号化される.これによってメッセージ
の偽造を防げる…が,障害のあるノードは結局秘密 を漏洩してしまう可能性があるの
で,暗号化されているからといってメッセージが無制限に信頼できるわけではない.
25. 14.5.1 PBFTアルゴリズム
• PBFTがsafetyとlivenessを満たすために許容する障害レプリカの数は,
• nは参加ノード数.したがって,f の障害ノード数を許容するには 必要.
• クラスタ構成の中で,PBFTは views という概念を使う.各viewにおいて,以下が存在する
• View: ID v をもつ.primaryで障害が発生すると変更される.
• Primary: v % n のノードがこう呼ばれる.クライアントの要求を処理する.
• Backup: primaryからブロードキャストされる要求を実行し,クライアントにレスポンス.
• f+1 のレプリカから同じ結果が応答されたら,クライアントはコミットとみなせる.
(n − 1)/3
n = 3f + 1
26. 14.5.1 PBFTアルゴリズム
• 以下がPBFTのプロトコルの流れ.
• Primaryがクライアントのリクエストを受け取る.
• Pre-Prepare phase:
• primaryから{v, n, payload, digest(payload)} をブロードキャスト.nは単調増加するシーケンス番号. digestはデジタル署名を行う.
• backupは,自身のviewが v と一致している digestの計算が一致する際,メッセージを受け入れる.
• Prepare phase:
• Backupは,Prepare メッセージ {v, n, digest(payload), i} をブロードキャスト. i はレプリカのユニーク番号.
• 同じ Prepare メッセージを 2f 回,異なるbackupから受け取った場合にのみ Prepare phaseを抜ける.
• Commit phase:
• Backupは,このメッセージについてのCommit メッセージを 2f + 1 のノードから収集したらコミットをクライアントに返す.
• クライアントは f+1 のノードからCommitを返却してもらったら,コミットと判断できる
27. 14.5.1 PBFTアルゴリズム: 正常系
Figure 1: Normal Case Operation
• PBFTでは,フェーズの間に必ず,各ノードが 2f + 1 のメッセージをそれぞれ収集する.そしてdigestをチェックするた
め,不正なメッセージは防止できる.
• 上図は primary = 0, f=1. P3 で障害が発生したため,応答を返さなくなっている.しかし,prepare -> commit で 各ノー
ドが 2f のprepare を収集しており,commitも 2f +1を収集しているため,正常に続行できる.
• Primaryに障害が発生した際は “view changes” というプロトコルが走り,primaryが交代する.
28. 14.5.2 リカバリとチェックポイント
• 各レプリカは,メッセージを永続化する.
• f+1 のノードで命令が実行されるまで保持しておく必要がある.
• メッセージを転送すれば,NW分断の後でもリカバリが可能・・・だが,そのメッセージが正しいものであることを保証し
なければならない.
• 各メッセージを反映して処理を進めながら,digestを再検証していけばよい.が,コストが高すぎる.
• そこで,定期的に stable checkpoint をとる.
• 最新のシーケンス番号 n と,現在の状態に対するdigest をブロードキャストする.
• 2f+1 のレプリカが正しいと応答してきた場合,チェックポイントが取れている証左になる. n 以下のidのメッセージをすべ
て破棄できる.
• # チェックポイントは全レプリカで共通の断片ではなく,各ノードが各自に勝手に行う.
29. 14.5.1 PBFTアルゴリズム: 異常系
• Primaryが動作していない,など,backupが異常の疑いを検出した際,view
changes というプロトコルが走る.
• それ以降のメッセージへの応答を停止し,自分がprimaryになろうとする.
• viewの変更 { v+1, n, C, P, i} をbroadcastする.n は 自身が持つ最後の
チェックポイントのメッセージ番号.Cはそのチェックポイントに応答し
た2f+1 のノードのメッセージ集合.Pはまだチェックポイントに含まれて
いないリクエストの集合.
•
30. 14.5.2 PBFT summary
• PBFTは,敵意が含まれる可能性のあるネットワークで利用するもの.
• ビザンチン障害耐性を持つプロトコルは,メッセージ数が増大するという欠点がある.PBFTも,
(primaryを立てているのにも関わらず) ブロードキャストを多用してしまっている.
• 参加ノードの台数 N や 故障許容ノードの数 f というパラメータを全レプリカで共有しなければなら
ない.これは前述したweak synchrony があるから許されている.パブリックブロックチェーン等の
世界ではその点で評価されていない(と思う).
• > 大半の場合は,ノード間の通信を認証して暗号化すれば十分ですが,システムのパーツ間
に信頼性がない場合には,PBFTに類似したアルゴリズムを導入しなければなりません.
31. 14.6 まとめ
• Multi-paxos: proposerが継続する.複数の値についてreplicationできる.
• Fast paxos: fast ラウンドが存在し,メッセージの数が削減されている.
• EPaxos:メッセージ間の依存関係を解決し,イベントの順序が確立できる.
• Flexible Paxos: クォラムの要件を緩和する.
• Raft: 強いリーダシップがあり,Paxosの各要素がdecompositionされ,理解しやすい.
• PBFT: 敵意が含まれる(HW故障なども含む) 環境で安全に合意できる.
32. References
[1] Diego Ongaro, John K. Ousterhout: In Search of an Understandable
Consensus Algorithm. USENIX Annual Technical Conference 2014: 305-319
[2] https://raft.github.io/slides/linkedin2014.pptx
[3] Miguel Castro, Barbara Liskov (1999) Practical Byzantine Fault Tolerance