The Problem about peerMsgHandler.destroyPeer
Panlisong opened this issue · 2 comments
Panlisong commented
In kv/raftstore/peer_msg_handler.go:385
if isInitialized && meta.regionRanges.Delete(®ionItem{region: d.Region()}) == nil {
consider the situation bellow:
- cluster commit the add confChange, p0 is created by store s0, current storeMeta in s0 is: regions: map[s0 : <...>] regionRanges: <region_id: s0, region_epoch: <>>
- peer p0 was added into region but not receive snapshot(i.e. not initialized), so the storeMeta in s0 remains constant
- cluster commit the remove confChange while the peer p0 have not receive the remove confChange entry
- cluster remove p0 in router, so p0 will never receive message from leader
- next time cluster commit add p1 in s0, since p1>p0(peer_id), when in peerMsgHandler.checkMessage:265, it will call peerMsgHandler.destroyPeer to destroy p0
- at this time, since p0 is uninitialized, the if statement upon will be short circuit so the meta.regionRanges.Delete() will not execute, so the current storeMeta in s0 is: regions: map[] regionRanges: <region_id: x, region_epoch: <>>
- after the destroy finished, peerMsgHandler will call
kv/raftstore/peer_msg_handler.go:266
d.ctx.router.sendStore(message.NewMsg(message.MsgTypeStoreRaftMessage, msg))
- the store will try to create peer but will fail in this statement since s0 regionRanges contains: <region_id: s0, region_epoch: <>>
kv/raftstore/store_worker.go:209
for _, region := range meta.getOverlapRegions(&metapb.Region{
StartKey: msg.StartKey,
EndKey: msg.EndKey,
}) {
log.Debugf("msg %s is overlapped with exist region %s", msg, region)
if util.IsFirstVoteMessage(msg.Message) {
meta.pendingVotes = append(meta.pendingVotes, msg)
}
return false, nil
}
My solution:
reverse order to avoid short circuit
kv/raftstore/peer_msg_handler.go:385
- if isInitialized && meta.regionRanges.Delete(®ionItem{region: d.Region()}) == nil {
+ if meta.regionRanges.Delete(®ionItem{region: d.Region()}) == nil && isInitialized {
Connor1996 commented
the region info is inserted into regionRanges
only after it is initialized.
Panlisong commented
thx