raft: lower split vote rate
parent
bf6d905a5a
commit
5d431b4782
30
raft/raft.go
30
raft/raft.go
|
@ -176,9 +176,14 @@ type raft struct {
|
||||||
|
|
||||||
heartbeatTimeout int
|
heartbeatTimeout int
|
||||||
electionTimeout int
|
electionTimeout int
|
||||||
rand *rand.Rand
|
// randomizedElectionTimeout is a random number between
|
||||||
tick func()
|
// [electiontimeout, 2 * electiontimeout - 1]. It gets reset
|
||||||
step stepFunc
|
// when raft changes its state to follower or candidate.
|
||||||
|
randomizedElectionTimeout int
|
||||||
|
|
||||||
|
rand *rand.Rand
|
||||||
|
tick func()
|
||||||
|
step stepFunc
|
||||||
|
|
||||||
logger Logger
|
logger Logger
|
||||||
}
|
}
|
||||||
|
@ -392,6 +397,7 @@ func (r *raft) reset(term uint64) {
|
||||||
|
|
||||||
r.electionElapsed = 0
|
r.electionElapsed = 0
|
||||||
r.heartbeatElapsed = 0
|
r.heartbeatElapsed = 0
|
||||||
|
r.resetRandomizedElectionTimeout()
|
||||||
|
|
||||||
r.votes = make(map[uint64]bool)
|
r.votes = make(map[uint64]bool)
|
||||||
for id := range r.prs {
|
for id := range r.prs {
|
||||||
|
@ -422,7 +428,7 @@ func (r *raft) tickElection() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r.electionElapsed++
|
r.electionElapsed++
|
||||||
if r.isElectionTimeout() {
|
if r.pastElectionTimeout() {
|
||||||
r.electionElapsed = 0
|
r.electionElapsed = 0
|
||||||
r.Step(pb.Message{From: r.id, Type: pb.MsgHup})
|
r.Step(pb.Message{From: r.id, Type: pb.MsgHup})
|
||||||
}
|
}
|
||||||
|
@ -863,15 +869,15 @@ func (r *raft) loadState(state pb.HardState) {
|
||||||
r.Vote = state.Vote
|
r.Vote = state.Vote
|
||||||
}
|
}
|
||||||
|
|
||||||
// isElectionTimeout returns true if r.electionElapsed is greater than the
|
// pastElectionTimeout returns true if r.electionElapsed is greater than the
|
||||||
// randomized election timeout in (electiontimeout, 2 * electiontimeout - 1).
|
// randomized election timeout in [electiontimeout, 2 * electiontimeout - 1].
|
||||||
// Otherwise, it returns false.
|
// Otherwise, it returns false.
|
||||||
func (r *raft) isElectionTimeout() bool {
|
func (r *raft) pastElectionTimeout() bool {
|
||||||
d := r.electionElapsed - r.electionTimeout
|
return r.electionElapsed >= r.randomizedElectionTimeout
|
||||||
if d < 0 {
|
}
|
||||||
return false
|
|
||||||
}
|
func (r *raft) resetRandomizedElectionTimeout() {
|
||||||
return d > r.rand.Int()%r.electionTimeout
|
r.randomizedElectionTimeout = r.electionTimeout + r.rand.Int()%r.electionTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkQuorumActive returns true if the quorum is active from
|
// checkQuorumActive returns true if the quorum is active from
|
||||||
|
|
|
@ -381,8 +381,8 @@ func testNonleadersElectionTimeoutNonconflict(t *testing.T, state StateType) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if g := float64(conflicts) / 1000; g > 0.4 {
|
if g := float64(conflicts) / 1000; g > 0.3 {
|
||||||
t.Errorf("probability of conflicts = %v, want <= 0.4", g)
|
t.Errorf("probability of conflicts = %v, want <= 0.3", g)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -754,9 +754,10 @@ func TestIsElectionTimeout(t *testing.T) {
|
||||||
round bool
|
round bool
|
||||||
}{
|
}{
|
||||||
{5, 0, false},
|
{5, 0, false},
|
||||||
{13, 0.3, true},
|
{10, 0.1, true},
|
||||||
{15, 0.5, true},
|
{13, 0.4, true},
|
||||||
{18, 0.8, true},
|
{15, 0.6, true},
|
||||||
|
{18, 0.9, true},
|
||||||
{20, 1, false},
|
{20, 1, false},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -765,7 +766,8 @@ func TestIsElectionTimeout(t *testing.T) {
|
||||||
sm.electionElapsed = tt.elapse
|
sm.electionElapsed = tt.elapse
|
||||||
c := 0
|
c := 0
|
||||||
for j := 0; j < 10000; j++ {
|
for j := 0; j < 10000; j++ {
|
||||||
if sm.isElectionTimeout() {
|
sm.resetRandomizedElectionTimeout()
|
||||||
|
if sm.pastElectionTimeout() {
|
||||||
c++
|
c++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue