-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
raft: clean-up log conflict search #126318
Conversation
6af12f3
to
efe2947
Compare
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.
Just a couple of questions, for my own understanding of Raft.
Reviewed 1 of 1 files at r1, 2 of 2 files at r2.
Reviewable status: complete! 1 of 0 LGTMs obtained (waiting on @arulajmani and @pav-kv)
pkg/raft/log.go
line 165 at r2 (raw file):
// Check the term match at min(s.lastIndex(), l.lastIndex()) entry, and fall // back to conflict search only if it mismatches. // TODO(pav-kv): also, there should be no mismatch if s.term == l.accTerm, so
What's l.accTerm
?
pkg/raft/log.go
line 170 at r2 (raw file):
// TODO(pav-kv): every matchTerm call in the linear scan below can fall back // to fetching an entry from storage. This is inefficient, we can improve it. // Logs that don't match at one index, don't match at all indices above. So we
Is this always true? Could two logs have disjoint matching parts? E.g. if the second entry with term 1 below is missing from the second log:
log1: (index: 1, term: 1), (index: 2, term: 1), (index: 3, term: 2), (index: 4, term: 3) ...
log2: (index: 1, term: 1), (index: 2, term: 2), (index: 3, term: 3), (index: 4, term: 3) ...
Or will the missing entry correspond to a missing index as well? So it will look like this:
log1: (index: 1, term: 1), (index: 2, term: 1), (index: 3, term: 2), (index: 4, term: 3) ...
log2: (index: 1, term: 1), (index: 3, term: 2), (index: 4, term: 3), (index: 5, term: 3) ...
It seems like it's the latter, based on the Log Matching property of raft you mention above.
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.
Reviewable status: complete! 1 of 0 LGTMs obtained (waiting on @arulajmani and @miraradeva)
pkg/raft/log.go
line 165 at r2 (raw file):
Previously, miraradeva (Mira Radeva) wrote…
What's
l.accTerm
?
It is the term of the leader whose append we accepted last:
Lines 348 to 363 in 5769b24
// accTerm is the term of the leader whose append was accepted into the log | |
// last. Note that a rejected append does not update accTerm, by definition. | |
// | |
// Invariant: the log is a prefix of the accTerm's leader log | |
// Invariant: raftLog.lastEntryID().term <= accTerm <= Term | |
// | |
// In steady state, accTerm == Term. When someone campaigns, Term briefly | |
// overtakes the accTerm. However, accTerm catches up as soon as we accept a | |
// log append from the new leader. | |
// | |
// NB: the log can be partially or fully compacted. When we say "log" above, | |
// we logically include all the entries that were the pre-image of a snapshot, | |
// as well as the entries that are still physically in the log. | |
// | |
// TODO(pav-kv): move accTerm to raftLog. | |
accTerm uint64 |
By raft invariants, we have a guarantee that our log is a prefix of the accTerm
leader's log. So, if the accTerm
leader sends us log appends, we may skip all the matchTerm
checks (they will all succeed).
pkg/raft/log.go
line 170 at r2 (raw file):
Previously, miraradeva (Mira Radeva) wrote…
Is this always true? Could two logs have disjoint matching parts? E.g. if the second entry with term 1 below is missing from the second log:
log1: (index: 1, term: 1), (index: 2, term: 1), (index: 3, term: 2), (index: 4, term: 3) ...
log2: (index: 1, term: 1), (index: 2, term: 2), (index: 3, term: 3), (index: 4, term: 3) ...Or will the missing entry correspond to a missing index as well? So it will look like this:
log1: (index: 1, term: 1), (index: 2, term: 1), (index: 3, term: 2), (index: 4, term: 3) ...
log2: (index: 1, term: 1), (index: 3, term: 2), (index: 4, term: 3), (index: 5, term: 3) ...It seems like it's the latter, based on the Log Matching property of raft you mention above.
Yes, it is the latter. Both of the following are true:
- if two logs have the same entry at index, then all the entries at lower indices match too
- if two logs mismatch at some index, they also mismatch at all higher indices
This is true because all the entries in raft form a tree. See "Background" section in etcd-io/raft#144 for more details.
Epic: none Release note: none
Use the new entryID and logSlice types. Move the preceding entry check into the conflict search method rather than do it outside. Add a bunch of TODOs for optimization: most log append requests can skip the term check scanning or do it more efficiently. Epic: none Release note: none
The append function call right after this does the same check, we don't need to do this in two places. TestLogMaybeAppend exercises these panics, and confirms the behaviour is the same after the first panic is removed. Epic: none Release note: none
efe2947
to
8a7cfe0
Compare
bors r=miraradeva |
Use the new
entryID
andlogSlice
types. Move the preceding entry check into the conflict search method rather than do it outside. Add a bunch of TODOs for optimization: most log append requests can skip the term check scanning or do it more efficiently.Epic: CRDB-37516
Release note: none