-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
suffixの明示的な削除コードを追加(issue18対策) #42
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
まだ見ている最中です
src/test_dsl/dsl.rs
Outdated
StepAll(iter) => { | ||
for _ in 0..iter { | ||
for (_n, io) in service.iter_mut() { | ||
io.poll().expect("never fails in test senarios"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit (typo):
io.poll().expect("never fails in test senarios"); | |
io.poll().expect("never fails in test scenarios"); |
src/test_dsl/impl_io.rs
Outdated
assert!(rawlog.head.index <= from); | ||
rawlog | ||
.truncate(from) | ||
.expect("should not make an error in test senarios"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit (typo):
.expect("should not make an error in test senarios"); | |
.expect("should not make an error in test scenarios"); |
PRの概要
Termがlog中で昇順に並ばないことがあるissue #18 を解決するためのコード群です。
ノード中のlogが古すぎる・staleしていて、ある位置
x
のエントリがcommitすることがないことが判明した段階で、suffix中のx以降のエントリ
[x..)
を全て削除するように変更します。このPR以前では、ストレージ側にあるsuffixの削除は行っていないのですが、メモリ上のキャッシュに相当するHistoryでは削除を行っていました。
これに一致するようにsuffixも削除するコードである、とも言えます。
別の説明としては、Raftのオリジナル論文において、
AppendEntriesRPCではstaleが判明した段階でエントリを削除するよう以下の指示があり、
論文と同じ振る舞いをするように修正する、とも言えます。
コードの新規追加による修正箇所
新規追加による修正は大きく分けて以下の4つです。
FollowerDelete
を追加しました。FollowerDelete
内に移動しました。Issue18の解決に対応する修正内容・箇所について
Issue18はつまるところ「ストレージに永続化されているlogと、そのメモリ上のキャッシュに相当するhistoryに「ズレ」が生じている状態で計算を続けると、クラスタが不整合のある状態になる」と言えます。
このズレを解消する処理として今回新たにDeleteを導入します。
Deleteの導入の有効性について
これまでDelete処理を行っていないために「logとhistoryにズレが発生し」そのまま計算を続けると問題が発生することを明らかにするテストケース シナリオ1 と シナリオ2 が既に存在していました。
このPRでのDeleteの導入によりlogとhistoryのズレが修正でき、上のテストケースが期待通りに動くことが確認できました。このことをもって、Deleteは有効であると言えます。
ここ と ここ の周辺になります。
ここ と ここ です。
既存のコードに関して注意するべき点
Delete処理の導入だけでは、logとhistoryのズレを完全には解消できません。
なぜなら、Delete処理の途中で状態遷移を行うと、結局ズレが解消していないまま計算が続行されるからです。
(削除処理中に状態遷移をしてズレたまま計算すると、実際に問題が起こることについては、次のセクションで説明しています。)
これを防ぐために、Delete処理が完了するまでは状態遷移をしないように、既存のコードも合わせて修正します。
修正箇所は以下の通りです:
FollowerIdle
に遷移します。この箇所です。Common構造体
の中に、logの削除処理を実行中でhistoryにズレが生じていることを表すためのフラグメンバを追加しています。これをより正確な実装である、Followerならばタイムアウトさせるメソッドを呼び出す、という実装に変更しています。
削除中のズレた状態で遷移すると発生する問題について
削除処理中に遷移すると実際に問題が生じることを述べたテストコードの内容を説明しているセクションです。
修正ではなくテストコードの説明を行っているセクションなので、skip可能です。
このテストコードでは次のような考え方をしています:
実際に、テストコードでは、Delete処理中にlogとhistoryが食い違った状況を作っています。
その後でDelete処理中のズレたままの状態でタイムアウトを引き起こします。
この時、本PRでも採用しているように、削除中のタイムアウトによるCandidateへの遷移を防いでいる場合には問題は起こりません。
一方で、(PRのコードを修正して)削除中のタイムアウトによるCandidateへの即座の遷移を許す場合、ズレたCandidateがLeaderになるようなコードになっています。テストコードでは、リーダー選出直後のNoopログエントリの書き込みを、History情報を用いてlogに追加しようとして、ストレージ視点でログの非連結状態を生み、エラーとなります。