Skip to content

Commit

Permalink
cherry pick tikv#2794 to release-4.0
Browse files Browse the repository at this point in the history
Signed-off-by: ti-srebot <ti-srebot@pingcap.com>
  • Loading branch information
Yisaer authored and ti-srebot committed Aug 19, 2020
1 parent 7e31082 commit c3b0e7d
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 3 deletions.
106 changes: 103 additions & 3 deletions server/schedule/filter/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package filter
import (
"fmt"

"github.com/pingcap/kvproto/pkg/metapb"
"github.com/pingcap/log"
"github.com/tikv/pd/pkg/slice"
"github.com/tikv/pd/server/core"
Expand Down Expand Up @@ -540,7 +541,9 @@ func (f *ruleFitFilter) Source(opt opt.Options, store *core.StoreInfo) bool {
}

func (f *ruleFitFilter) Target(opt opt.Options, store *core.StoreInfo) bool {
region := f.region.Clone(core.WithReplacePeerStore(f.oldStore, store.GetID()))
region := createRegionForRuleFit(f.region.GetStartKey(), f.region.GetEndKey(),
f.region.GetPeers(), f.region.GetLeader(),
core.WithReplacePeerStore(f.oldStore, store.GetID()))
newFit := f.fitter.FitRegion(region)
return placement.CompareRegionFit(f.oldFit, newFit) <= 0
}
Expand Down Expand Up @@ -583,8 +586,10 @@ func (f *ruleLeaderFitFilter) Target(opt opt.Options, store *core.StoreInfo) boo
log.Warn("ruleLeaderFitFilter couldn't find peer on target Store", zap.Uint64("target-store", store.GetID()))
return false
}
region := f.region.Clone(core.WithLeader(targetPeer))
newFit := f.fitter.FitRegion(region)
copyRegion := createRegionForRuleFit(f.region.GetStartKey(), f.region.GetEndKey(),
f.region.GetPeers(), f.region.GetLeader(),
core.WithLeader(targetPeer))
newFit := f.fitter.FitRegion(copyRegion)
return placement.CompareRegionFit(f.oldFit, newFit) <= 0
}

Expand Down Expand Up @@ -712,3 +717,98 @@ const (

var allSpecialUses = []string{SpecialUseHotRegion, SpecialUseReserved}
var allSpeicalEngines = []string{EngineTiFlash}
<<<<<<< HEAD
=======

type isolationFilter struct {
scope string
locationLabels []string
constraintSet [][]string
}

// NewIsolationFilter creates a filter that filters out stores with isolationLevel
// For example, a region has 3 replicas in z1, z2 and z3 individually.
// With isolationLevel = zone, if the region on z1 is down, we need to filter out z2 and z3
// because these two zones already have one of the region's replicas on them.
// We need to choose a store on z1 or z4 to place the new replica to meet the isolationLevel explicitly and forcibly.
func NewIsolationFilter(scope, isolationLevel string, locationLabels []string, regionStores []*core.StoreInfo) Filter {
isolationFilter := &isolationFilter{
scope: scope,
locationLabels: locationLabels,
constraintSet: make([][]string, 0),
}
// Get which idx this isolationLevel at according to locationLabels
var isolationLevelIdx int
for level, label := range locationLabels {
if label == isolationLevel {
isolationLevelIdx = level
break
}
}
// Collect all constraints for given isolationLevel
for _, regionStore := range regionStores {
constraintList := make([]string, 0)
for i := 0; i <= isolationLevelIdx; i++ {
constraintList = append(constraintList, regionStore.GetLabelValue(locationLabels[i]))
}
isolationFilter.constraintSet = append(isolationFilter.constraintSet, constraintList)
}
return isolationFilter
}

func (f *isolationFilter) Scope() string {
return f.scope
}

func (f *isolationFilter) Type() string {
return "isolation-filter"
}

func (f *isolationFilter) Source(opt opt.Options, store *core.StoreInfo) bool {
return true
}

func (f *isolationFilter) Target(opt opt.Options, store *core.StoreInfo) bool {
// No isolation constraint to fit
if len(f.constraintSet) <= 0 {
return true
}
for _, constrainList := range f.constraintSet {
match := true
for idx, constraint := range constrainList {
// Check every constraint in constrainList
match = store.GetLabelValue(f.locationLabels[idx]) == constraint && match
}
if len(constrainList) > 0 && match {
return false
}
}
return true
}

// createRegionForRuleFit is used to create a clone region with RegionCreateOptions which is only used for
// FitRegion in filter
func createRegionForRuleFit(startKey, endKey []byte,
peers []*metapb.Peer, leader *metapb.Peer, opts ...core.RegionCreateOption) *core.RegionInfo {
copyLeader := &metapb.Peer{
Id: leader.Id,
StoreId: leader.StoreId,
Role: leader.Role,
}
copyPeers := make([]*metapb.Peer, 0, len(peers))
for _, p := range peers {
peer := &metapb.Peer{
Id: p.Id,
StoreId: p.StoreId,
Role: p.Role,
}
copyPeers = append(copyPeers, peer)
}
cloneRegion := core.NewRegionInfo(&metapb.Region{
StartKey: startKey,
EndKey: endKey,
Peers: copyPeers,
}, copyLeader, opts...)
return cloneRegion
}
>>>>>>> a0eba9b... filter: replace region.Clone in filter (#2794)
25 changes: 25 additions & 0 deletions server/schedule/filter/filters_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,28 @@ func (s *testFiltersSuite) TestRuleFitFilter(c *C) {
c.Assert(filter.Target(tc, tc.GetStore(4)), IsFalse)
c.Assert(filter.Source(tc, tc.GetStore(4)), IsTrue)
}

func BenchmarkCloneRegionTest(b *testing.B) {
epoch := &metapb.RegionEpoch{
ConfVer: 1,
Version: 1,
}
region := core.NewRegionInfo(
&metapb.Region{
Id: 4,
StartKey: []byte("x"),
EndKey: []byte(""),
Peers: []*metapb.Peer{
{Id: 108, StoreId: 4},
},
RegionEpoch: epoch,
},
&metapb.Peer{Id: 108, StoreId: 4},
core.SetApproximateSize(50),
core.SetApproximateKeys(20),
)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = createRegionForRuleFit(region.GetStartKey(), region.GetEndKey(), region.GetPeers(), region.GetLeader())
}
}

0 comments on commit c3b0e7d

Please sign in to comment.