Skip to content

Commit 34ffcfd

Browse files
committed
Delay the next campaign if the node lost the vote
Delay the next campaign if the node lost the vote. It's highly likely it will also lose next campaign, so it makes more sense to prioritize campaigns by other nodes within the current term. Signed-off-by: Benjamin Wang <[email protected]>
1 parent d475d7e commit 34ffcfd

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

raft.go

+7
Original file line numberDiff line numberDiff line change
@@ -1674,6 +1674,13 @@ func stepCandidate(r *raft, m pb.Message) error {
16741674
// pb.MsgPreVoteResp contains future term of pre-candidate
16751675
// m.Term > r.Term; reuse r.Term
16761676
r.becomeFollower(r.Term, None)
1677+
// Delay the next campaign if the node lost the vote. It's
1678+
// highly likely it will also lose next campaign, so it makes
1679+
// more sense to prioritize campaigns by other nodes within
1680+
// the current term.
1681+
if myVoteRespType == pb.MsgVoteResp {
1682+
r.randomizedElectionTimeout += r.electionTimeout
1683+
}
16771684
}
16781685
case pb.MsgTimeoutNow:
16791686
r.logger.Debugf("%x [term %d state %v] ignored MsgTimeoutNow from %x", r.id, r.Term, r.state, m.From)

raft_test.go

+30
Original file line numberDiff line numberDiff line change
@@ -1241,6 +1241,36 @@ func TestPastElectionTimeout(t *testing.T) {
12411241
}
12421242
}
12431243

1244+
func TestRandomizedElectionTimeoutOnLostVote(t *testing.T) {
1245+
storage := newTestMemoryStorage(withPeers(1, 2, 3))
1246+
storage.Append(index(1).terms(1, 2, 3, 4, 5))
1247+
r := newTestRaft(1, 10, 1, storage)
1248+
1249+
term, index := r.raftLog.lastEntryID().term, r.raftLog.lastEntryID().index
1250+
r.Term = term
1251+
1252+
r.becomeCandidate()
1253+
msgVote := pb.Message{
1254+
From: 1,
1255+
To: 2,
1256+
Type: pb.MsgVote,
1257+
Term: term + 1,
1258+
LogTerm: index,
1259+
Index: 42,
1260+
}
1261+
r.stepOrSend([]pb.Message{msgVote})
1262+
1263+
// The MsgVote is rejected by r2
1264+
err := r.Step(pb.Message{From: 2, To: 1, Term: term + 1, Type: pb.MsgVoteResp, Reject: true})
1265+
require.NoError(t, err)
1266+
require.Less(t, r.randomizedElectionTimeout, r.electionTimeout*2)
1267+
1268+
// The MsgVote is rejected by r3
1269+
err = r.Step(pb.Message{From: 3, To: 1, Term: term + 1, Type: pb.MsgVoteResp, Reject: true})
1270+
require.NoError(t, err)
1271+
require.GreaterOrEqual(t, r.randomizedElectionTimeout, r.electionTimeout*2)
1272+
}
1273+
12441274
// TestStepIgnoreOldTermMsg to ensure that the Step function ignores the message
12451275
// from old term and does not pass it to the actual stepX function.
12461276
func TestStepIgnoreOldTermMsg(t *testing.T) {

0 commit comments

Comments
 (0)