From c643967a41d8573bd070c44560bf70d8982035a6 Mon Sep 17 00:00:00 2001 From: Xiang Li Date: Tue, 10 Mar 2015 18:33:58 -0700 Subject: [PATCH] raft: reply with the commit index when receives a smaller append message Follower should not reject the append message with a smaller index than its commit index. Or it will trigger the leader's resending logic, which might have a high cost. --- raft/raft.go | 5 +++++ raft/raft_paper_test.go | 20 +++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/raft/raft.go b/raft/raft.go index 1b363a426..f673751cc 100644 --- a/raft/raft.go +++ b/raft/raft.go @@ -663,6 +663,11 @@ func stepFollower(r *raft, m pb.Message) { } func (r *raft) handleAppendEntries(m pb.Message) { + if m.Index < r.Commit { + r.send(pb.Message{To: m.From, Type: pb.MsgAppResp, Index: r.Commit}) + return + } + if mlastIndex, ok := r.raftLog.maybeAppend(m.Index, m.LogTerm, m.Commit, m.Entries...); ok { r.send(pb.Message{To: m.From, Type: pb.MsgAppResp, Index: mlastIndex}) } else { diff --git a/raft/raft_paper_test.go b/raft/raft_paper_test.go index 1a29b57ff..3d9e496cf 100644 --- a/raft/raft_paper_test.go +++ b/raft/raft_paper_test.go @@ -603,27 +603,33 @@ func TestFollowerCheckMsgApp(t *testing.T) { tests := []struct { term uint64 index uint64 + windex uint64 wreject bool wrejectHint uint64 }{ - {ents[0].Term, ents[0].Index, false, 0}, - {ents[0].Term, ents[0].Index + 1, true, 2}, - {ents[0].Term + 1, ents[0].Index, true, 2}, - {ents[1].Term, ents[1].Index, false, 0}, - {3, 3, true, 2}, + // match with committed entries + {0, 0, 1, false, 0}, + {ents[0].Term, ents[0].Index, 1, false, 0}, + // match with uncommitted entries + {ents[1].Term, ents[1].Index, 2, false, 0}, + + // unmatch with existing entry + {ents[0].Term, ents[1].Index, ents[1].Index, true, 2}, + // unexisting entry + {ents[1].Term + 1, ents[1].Index + 1, ents[1].Index + 1, true, 2}, } for i, tt := range tests { storage := NewMemoryStorage() storage.Append(ents) r := newRaft(1, []uint64{1, 2, 3}, 10, 1, storage, 0) - r.loadState(pb.HardState{Commit: 2}) + r.loadState(pb.HardState{Commit: 1}) r.becomeFollower(2, 2) r.Step(pb.Message{From: 2, To: 1, Type: pb.MsgApp, Term: 2, LogTerm: tt.term, Index: tt.index}) msgs := r.readMessages() wmsgs := []pb.Message{ - {From: 1, To: 2, Type: pb.MsgAppResp, Term: 2, Index: tt.index, Reject: tt.wreject, RejectHint: tt.wrejectHint}, + {From: 1, To: 2, Type: pb.MsgAppResp, Term: 2, Index: tt.windex, Reject: tt.wreject, RejectHint: tt.wrejectHint}, } if !reflect.DeepEqual(msgs, wmsgs) { t.Errorf("#%d: msgs = %+v, want %+v", i, msgs, wmsgs)