Skip to content

Commit

Permalink
Avoid assigning duplicate RAFT IDs to new nodes. (#5604)
Browse files Browse the repository at this point in the history
Currently, zero uses the MaxRaftId to assign RAFT IDs to new nodes. However, the
MaxRaftId value is not immediately updated and the lock is released in between
creating the proposal and sending the proposal to the RAFT node. This can lead
to situations where more than one new node is assigned the same ID.

To solve this, this change introduces a new field to generate the IDs that is
updated immediately, thus preventing multiple nodes from being assigned
the same ID.

Fixes #5436

cherry-picked from c093805
  • Loading branch information
martinmr authored Jun 9, 2020
1 parent c6a45f9 commit dfca80d
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 1 deletion.
1 change: 1 addition & 0 deletions dgraph/cmd/zero/raft.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ func (n *node) applyProposal(e raftpb.Entry) (string, error) {
return p.Key, errInvalidProposal
}
state.MaxRaftId = p.MaxRaftId
n.server.nextRaftId = x.Max(n.server.nextRaftId, p.MaxRaftId+1)
}
if p.SnapshotTs != nil {
for gid, ts := range p.SnapshotTs {
Expand Down
11 changes: 10 additions & 1 deletion dgraph/cmd/zero/zero.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ type Server struct {

NumReplicas int
state *pb.MembershipState
nextRaftId uint64

nextLeaseId uint64
nextTxnTs uint64
Expand Down Expand Up @@ -83,6 +84,7 @@ func (s *Server) Init() {
Groups: make(map[uint32]*pb.Group),
Zeros: make(map[uint64]*pb.Member),
}
s.nextRaftId = 1
s.nextLeaseId = 1
s.nextTxnTs = 1
s.nextGroup = 1
Expand Down Expand Up @@ -217,7 +219,10 @@ func (s *Server) hasLeader(gid uint32) bool {
func (s *Server) SetMembershipState(state *pb.MembershipState) {
s.Lock()
defer s.Unlock()

s.state = state
s.nextRaftId = x.Max(s.nextRaftId, s.state.MaxRaftId+1)

if state.Zeros == nil {
state.Zeros = make(map[uint64]*pb.Member)
}
Expand Down Expand Up @@ -491,7 +496,11 @@ func (s *Server) Connect(ctx context.Context,
}
}
if m.Id == 0 {
m.Id = s.state.MaxRaftId + 1
// In certain situations, the proposal can be sent and return with an error.
// However, Dgraph will keep retrying the proposal. To avoid assigning duplicating
// IDs, the couter is incremented every time a proposal is created.
m.Id = s.nextRaftId
s.nextRaftId += 1
proposal.MaxRaftId = m.Id
}

Expand Down

0 comments on commit dfca80d

Please sign in to comment.