Skip to content
2 changes: 1 addition & 1 deletion pkg/mcs/scheduling/server/apis/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1466,7 +1466,7 @@ func splitRegions(c *gin.Context) {
}

// @Tags region
// @Summary Check if regions in the given key ranges are replicated. Returns 'REPLICATED', 'INPROGRESS', or 'PENDING'. 'PENDING' means that there is at least one region pending for scheduling. Similarly, 'INPROGRESS' means there is at least one region in scheduling.
// @Summary Check if regions in the given key ranges are replicated. Returns 'REPLICATED', 'INPROGRESS', or 'PENDING'. 'PENDING' means that PD cannot currently make scheduling progress because the Store topology has no eligible placement. 'INPROGRESS' means that placement is incomplete but PD can continue or retry scheduling, including incomplete Region metadata in the requested range.
// @Param startKey query string true "Regions start key, hex encoded"
// @Param endKey query string true "Regions end key, hex encoded"
// @Produce plain
Expand Down
6 changes: 6 additions & 0 deletions pkg/schedule/checker/checker_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,12 @@ func (c *Controller) checkPendingProcessedRegions() {
pendingProcessedRegionsGauge.Set(float64(len(ids)))
for _, id := range ids {
region := c.cluster.GetRegion(id)
if region == nil {
continue
}
// Remove the old entry before checking. A checker will add it back if
// temporary conditions still prevent scheduling.
c.RemovePendingProcessedRegion(id)
c.tryAddOperators(region)
}
}
Expand Down
52 changes: 38 additions & 14 deletions pkg/schedule/checker/replica_strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ import (
// ReplicaStrategy collects some utilities to manipulate region peers. It
// exists to allow replica_checker and rule_checker to reuse common logics.
type ReplicaStrategy struct {
checkerName string // replica-checker / rule-checker
cluster sche.CheckerCluster
locationLabels []string
isolationLevel string
region *core.RegionInfo
extraFilters []filter.Filter
fastFailover bool
checkerName string // replica-checker / rule-checker
cluster sche.CheckerCluster
locationLabels []string
isolationLevel string
region *core.RegionInfo
extraFilters []filter.Filter
fastFailover bool
storeCandidates []*core.StoreInfo
storeCandidatesPrepared bool
}

// SelectStoreToAdd returns the store to add a replica to a region.
Expand All @@ -62,25 +64,29 @@ func (s *ReplicaStrategy) SelectStoreToAdd(coLocationStores []*core.StoreInfo, e
if s.fastFailover {
level = constant.Urgent
}
filters := []filter.Filter{
filter.NewExcludedFilter(s.checkerName, nil, s.region.GetStoreIDs()),
filter.NewStorageThresholdFilter(s.checkerName),
filter.NewSpecialUseFilter(s.checkerName),
&filter.StoreStateFilter{ActionScope: s.checkerName, MoveRegion: true, AllowTemporaryStates: true, OperatorLevel: level},
stores := s.storeCandidates
filters := []filter.Filter{filter.NewExcludedFilter(s.checkerName, nil, s.region.GetStoreIDs())}
if !s.storeCandidatesPrepared {
stores = s.cluster.GetStores()
filters = append(filters,
filter.NewStorageThresholdFilter(s.checkerName),
filter.NewSpecialUseFilter(s.checkerName),
&filter.StoreStateFilter{ActionScope: s.checkerName, MoveRegion: true, AllowTemporaryStates: true, OperatorLevel: level},
)
}
if len(s.locationLabels) > 0 && s.isolationLevel != "" {
filters = append(filters, filter.NewIsolationFilter(s.checkerName, s.isolationLevel, s.locationLabels, coLocationStores))
}
if len(extraFilters) > 0 {
filters = append(filters, extraFilters...)
}
if len(s.extraFilters) > 0 {
if !s.storeCandidatesPrepared && len(s.extraFilters) > 0 {
filters = append(filters, s.extraFilters...)
}

isolationComparer := filter.IsolationComparer(s.locationLabels, coLocationStores)
strictStateFilter := &filter.StoreStateFilter{ActionScope: s.checkerName, MoveRegion: true, AllowFastFailover: s.fastFailover, OperatorLevel: level}
targetCandidate := filter.NewCandidates(s.cluster.GetStores()).
targetCandidate := filter.NewCandidates(stores).
FilterTarget(s.cluster.GetCheckerConfig(), nil, nil, filters...).
KeepTheTopStores(isolationComparer, false) // greater isolation score is better
if targetCandidate.Len() == 0 {
Expand All @@ -94,6 +100,24 @@ func (s *ReplicaStrategy) SelectStoreToAdd(coLocationStores []*core.StoreInfo, e
return target.GetID(), false
}

// prepareStoreCandidates applies the Region-independent target filters so the
// result can be reused by placement-state checks using the same Rule.
func (s *ReplicaStrategy) prepareStoreCandidates(stores []*core.StoreInfo) {
level := constant.High
if s.fastFailover {
level = constant.Urgent
}
filters := []filter.Filter{
filter.NewStorageThresholdFilter(s.checkerName),
filter.NewSpecialUseFilter(s.checkerName),
&filter.StoreStateFilter{ActionScope: s.checkerName, MoveRegion: true, AllowTemporaryStates: true, OperatorLevel: level},
}
filters = append(filters, s.extraFilters...)
s.storeCandidates = filter.NewCandidates(stores).
FilterTarget(s.cluster.GetCheckerConfig(), nil, nil, filters...).Stores
s.storeCandidatesPrepared = true
}

// SelectStoreToFix returns a store to replace down/offline old peer. The location
// placement after scheduling is allowed to be worse than original.
func (s *ReplicaStrategy) SelectStoreToFix(coLocationStores []*core.StoreInfo, old uint64) (uint64, bool) {
Expand Down
Loading
Loading