@@ -19,6 +19,7 @@ import (
1919 "fmt"
2020 "math"
2121 "strconv"
22+ "strings"
2223 "sync"
2324 "time"
2425
@@ -44,8 +45,10 @@ import (
4445const regionScatterName = "region-scatter"
4546
4647var (
47- gcInterval = time .Minute
48- gcTTL = time .Minute * 3
48+ gcInterval = time .Minute
49+ gcTTL = time .Minute * 3
50+ operatorPriorityLevel = constant .High
51+
4952 // WithLabelValues is a heavy operation, define variable to avoid call it every time.
5053 scatterSkipEmptyRegionCounter = scatterCounter .WithLabelValues ("skip" , "empty-region" )
5154 scatterSkipNoRegionCounter = scatterCounter .WithLabelValues ("skip" , "no-region" )
@@ -56,12 +59,15 @@ var (
5659 scatterUnnecessaryCounter = scatterCounter .WithLabelValues ("unnecessary" , "" )
5760 scatterFailCounter = scatterCounter .WithLabelValues ("fail" , "" )
5861 scatterSuccessCounter = scatterCounter .WithLabelValues ("success" , "" )
62+ scatterOperatorRunningCounter = scatterCounter .WithLabelValues ("skip" , "running" )
63+ scatterOperatorExistedCounter = scatterCounter .WithLabelValues ("fail" , "other-existed" )
5964)
6065
6166const (
6267 maxSleepDuration = time .Minute
6368 initialSleepDuration = 100 * time .Millisecond
6469 maxRetryLimit = 30
70+ scatterOperatorDesc = "scatter-region"
6571)
6672
6773type selectedStores struct {
@@ -156,7 +162,7 @@ type engineContext struct {
156162
157163func newEngineContext (ctx context.Context , filterFuncs ... filterFunc ) engineContext {
158164 filterFuncs = append (filterFuncs , func () filter.Filter {
159- return & filter.StoreStateFilter {ActionScope : regionScatterName , MoveRegion : true , ScatterRegion : true , OperatorLevel : constant . High }
165+ return & filter.StoreStateFilter {ActionScope : regionScatterName , MoveRegion : true , ScatterRegion : true , OperatorLevel : operatorPriorityLevel }
160166 })
161167 return engineContext {
162168 filterFuncs : filterFuncs ,
@@ -287,6 +293,28 @@ func (r *RegionScatterer) Scatter(region *core.RegionInfo, group string, skipSto
287293 return nil , errors .Errorf ("region %d is not fully replicated" , region .GetID ())
288294 }
289295
296+ // Check if there is any existing operator for the region.
297+ // if the exist operator level is higher than scatter operator level, give up to create new scatter operator new.
298+ // otherwise, create new scatter operator to replace the existing one.
299+ if op := r .opController .GetOperator (region .GetID ()); op != nil && op .GetPriorityLevel () >= operatorPriorityLevel {
300+ val , exist := op .GetAdditionalInfo ("group" )
301+ // If the existing operator is created by the same group scatterer, just skip creating a new one.
302+ if strings .Contains (op .Desc (), scatterOperatorDesc ) && exist && val == group {
303+ scatterOperatorRunningCounter .Inc ()
304+ log .Debug ("scatter operator is already running" ,
305+ zap .Uint64 ("region-id" , region .GetID ()))
306+ return nil , nil
307+ }
308+ scatterOperatorExistedCounter .Inc ()
309+ log .Debug ("the operator exist, but it does not meet requirement" ,
310+ zap .Uint64 ("region-id" , region .GetID ()),
311+ zap .String ("additional-info-group" , val ),
312+ zap .String ("operator-des" , op .Desc ()),
313+ zap .Bool ("group-exist" , exist ),
314+ )
315+ return nil , errors .Errorf ("the operator of region %d already exist" , region .GetID ())
316+ }
317+
290318 if region .GetLeader () == nil {
291319 scatterSkipNoLeaderCounter .Inc ()
292320 log .Warn ("region no leader during scatter" , zap .Uint64 ("region-id" , region .GetID ()))
@@ -405,7 +433,7 @@ func (r *RegionScatterer) scatterRegion(region *core.RegionInfo, group string, s
405433 r .Put (targetPeers , targetLeader , group )
406434 return nil , nil
407435 }
408- op , err := operator .CreateScatterRegionOperator ("scatter-region" , r .cluster , region , targetPeers , targetLeader , skipStoreLimit )
436+ op , err := operator .CreateScatterRegionOperator (scatterOperatorDesc , r .cluster , region , targetPeers , targetLeader , skipStoreLimit )
409437 if err != nil {
410438 scatterFailCounter .Inc ()
411439 for _ , peer := range region .GetPeers () {
@@ -420,7 +448,7 @@ func (r *RegionScatterer) scatterRegion(region *core.RegionInfo, group string, s
420448 r .Put (targetPeers , targetLeader , group )
421449 op .SetAdditionalInfo ("group" , group )
422450 op .SetAdditionalInfo ("leader-picked-count" , strconv .FormatUint (leaderStorePickedCount , 10 ))
423- op .SetPriorityLevel (constant . High )
451+ op .SetPriorityLevel (operatorPriorityLevel )
424452 }
425453 return op , nil
426454}
0 commit comments