schedule: add region merge checker#839
Conversation
5825464 to
16a9ca7
Compare
aedf20e to
b0331ef
Compare
server/coordinator.go
Outdated
| } | ||
|
|
||
| if op1, op2 := c.mergeChecker.Check(region); op1 != nil && op2 != nil { | ||
| if c.addOperator(op1) == true { |
server/coordinator.go
Outdated
|
|
||
| if op1, op2 := c.mergeChecker.Check(region); op1 != nil && op2 != nil { | ||
| if c.addOperator(op1) == true { | ||
| if c.addOperator(op2) == false { |
server/coordinator.go
Outdated
| if op1, op2 := c.mergeChecker.Check(region); op1 != nil && op2 != nil { | ||
| if c.addOperator(op1) == true { | ||
| if c.addOperator(op2) == false { | ||
| c.removeOperator(op1) |
There was a problem hiding this comment.
The operator may have been sent to tikv already. I think it will better to check operators before add.
server/coordinator.go
Outdated
| } | ||
| c.hbStreams.sendMsg(region, cmd) | ||
| case schedule.MergeRegion: | ||
| if s.IsFake == true { |
server/schedule/merge_checker.go
Outdated
| var target *core.RegionInfo | ||
| prev, next := m.cluster.GetAdjacentRegions(region) | ||
| // check key to avoid key range hole | ||
| if prev != nil && bytes.Compare(prev.Region.EndKey, region.Region.StartKey) != 0 { |
There was a problem hiding this comment.
Maybe check it inside getAdjacentRegions?
server/schedule/merge_checker.go
Outdated
| } | ||
|
|
||
| func (m *MergeChecker) matchPeers(source *core.RegionInfo, target *core.RegionInfo) ([]OperatorStep, error) { | ||
| storeIDs := make(map[uint64]bool) |
There was a problem hiding this comment.
We usually use struct{} instead of bool when using map as set.
server/schedule/operator.go
Outdated
| // IsFinish checks if cuurent step is finished | ||
| func (mr MergeRegion) IsFinish(region *core.RegionInfo) bool { | ||
| // In view of pd doesn't know merge is success or not | ||
| // this step will not finish, so just let operator timeout and then be removed |
There was a problem hiding this comment.
How about save its key range then check if key range expands?
server/schedule/operator.go
Outdated
|
|
||
| // Influence calculates the store difference that current step make | ||
| func (mr MergeRegion) Influence(opInfluence OpInfluence, region *core.RegionInfo) { | ||
| // merge influence nothing |
There was a problem hiding this comment.
Seems it decreases region count, although we don't use it for balancing now.
server/schedule/operator.go
Outdated
| FromRegion uint64 | ||
| ToRegion uint64 | ||
| Direction pdpb.MergeDirection | ||
| IsFake bool |
There was a problem hiding this comment.
there are two regions involved in merge process, so to keep them from other scheduler, both of them should add operator. But actually, tikv just need one region to get the merge request, thus use a IsFake mark to indicate that this region doesn't need to send merge request to tikv
There was a problem hiding this comment.
I don't think IsFake is reasonable name here, maybe IsPassive. Also need some comments here.
| MaxPendingPeerCount uint64 `toml:"max-pending-peer-count,omitempty" json:"max-pending-peer-count"` | ||
| // If the size of region is smaller than this value, | ||
| // it will try to merge with adjacent regions. | ||
| MaxMergeRegionSize uint64 `toml:"max-merge-region-size,omitempty" json:"max-merge-region-size"` |
There was a problem hiding this comment.
I think we need another configuration to restrict maximum region size after merge, or the new region may need to split again soon after.
ade7b64 to
97fe966
Compare
97fe966 to
a57ec0f
Compare
a57ec0f to
e89b7ff
Compare
server/core/region_tree.go
Outdated
| next = i.(*regionItem) | ||
| return false | ||
| }) | ||
| item = ®ionItem{region: &metapb.Region{StartKey: region.StartKey}} |
There was a problem hiding this comment.
why assign the item again?
| return false | ||
| }) | ||
| item = ®ionItem{region: &metapb.Region{StartKey: region.StartKey}} | ||
| t.tree.AscendGreaterOrEqual(item, func(i btree.Item) bool { |
There was a problem hiding this comment.
The AscendGreaterOrEqual will iterate in [item, last], so I am confused that why you set prev here?
There was a problem hiding this comment.
the item store in region_tree is in reversed order, namely startkey "a" is greater than "b". https://github.com/Connor1996/pd/blob/e81d31ff04bdb282b66521f09f1562088e8869e7/server/core/region_tree.go#L30
| } | ||
| c.hbStreams.sendMsg(region, cmd) | ||
| case schedule.MergeRegion: | ||
| if s.IsPassive { |
There was a problem hiding this comment.
you can see the explanation at where it defines
eb9e6f5 to
74f28db
Compare
|
do we disable this by default? |
pdctl/command/region_command.go
Outdated
| func NewRegionWithSiblingCommand() *cobra.Command { | ||
| r := &cobra.Command{ | ||
| Use: "sibling <region_id>", | ||
| Short: "show the sibling region of specific region", |
|
|
||
| if bytes.Compare(region.StartKey, target.EndKey) != 0 && bytes.Compare(region.EndKey, target.StartKey) != 0 { | ||
| return ErrRegionNotAdjacent | ||
| } |
There was a problem hiding this comment.
What if merge the first region (start key is nil) with the last region (end key is nil) ?
| if m.cluster.IsRegionHot(region.GetId()) { | ||
| checkerCounter.WithLabelValues("merge_checker", "hot_region").Inc() | ||
| return nil, nil | ||
| } |
There was a problem hiding this comment.
I think we can also skip the region if its replica count is different from default configuration.
|
PTAL @nolouch |
| prev, next := m.cluster.GetAdjacentRegions(region) | ||
|
|
||
| target = m.checkTarget(region, prev, target) | ||
| target = m.checkTarget(region, next, target) |
There was a problem hiding this comment.
I think we also need to consider the state of target peers.
server/handler.go
Outdated
| if bytes.Compare(region.StartKey, target.EndKey) != 0 && bytes.Compare(region.EndKey, target.StartKey) != 0 { | ||
| // for the case first region (start key is nil) with the last region (end key is nil) but not adjacent | ||
| if (bytes.Compare(region.StartKey, target.EndKey) != 0 || region.StartKey == nil) && | ||
| (bytes.Compare(region.EndKey, target.StartKey) != 0 || region.EndKey == nil) { |
There was a problem hiding this comment.
Do not use == nil to check empty []byte. Use len(b) == 0 instead.
|
LGTM. |
14a1cc2 to
3ed34eb
Compare
in some case, region size is so small even empty, it would be better to merge it with adjacent region if allowed. So introduce region merge checker to detect whether it needs to merge every time receive heartbeat from region. If yes, pd schedule region's peers to make sure that two regions to be merged in same stores, and then launch a merge request to tikv.