Skip to content

Commit

Permalink
Simplify balance-region scheduler (#130)
Browse files Browse the repository at this point in the history
* simplify store check

Signed-off-by: Yang Keao <keao.yang@yahoo.com>

* remove complicate get threshold

Signed-off-by: Yang Keao <keao.yang@yahoo.com>

* remove LeaderScore and RegionScore

Signed-off-by: Yang Keao <keao.yang@yahoo.com>
  • Loading branch information
YangKeao committed Mar 20, 2020
1 parent 44e29ee commit f660f80
Show file tree
Hide file tree
Showing 7 changed files with 13 additions and 323 deletions.
23 changes: 0 additions & 23 deletions scheduler/server/core/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ package core

import (
"fmt"
"math"
"time"

"github.com/gogo/protobuf/proto"
Expand Down Expand Up @@ -221,16 +220,6 @@ func (s *StoreInfo) GetLastHeartbeatTS() time.Time {

const minWeight = 1e-6

// LeaderScore returns the store's leader score.
func (s *StoreInfo) LeaderScore(delta int64) float64 {
return float64(int64(s.GetLeaderCount())+delta) / math.Max(s.GetLeaderWeight(), minWeight)
}

// RegionScore returns the store's region score.
func (s *StoreInfo) RegionScore() float64 {
return float64(s.GetRegionSize()) / math.Max(s.GetRegionWeight(), minWeight)
}

// StorageSize returns store's used storage size reported from tikv.
func (s *StoreInfo) StorageSize() uint64 {
return s.GetUsedSize()
Expand Down Expand Up @@ -273,18 +262,6 @@ func (s *StoreInfo) ResourceSize(kind ResourceKind) int64 {
}
}

// ResourceScore returns score of leader/region in the store.
func (s *StoreInfo) ResourceScore(scheduleKind ScheduleKind, delta int64) float64 {
switch scheduleKind.Resource {
case LeaderKind:
return s.LeaderScore(delta)
case RegionKind:
return s.RegionScore()
default:
return 0
}
}

// ResourceWeight returns weight of leader/region in the score
func (s *StoreInfo) ResourceWeight(kind ResourceKind) float64 {
switch kind {
Expand Down
59 changes: 4 additions & 55 deletions scheduler/server/schedule/selector/selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,57 +21,6 @@ import (
"github.com/pingcap-incubator/tinykv/scheduler/server/schedule/opt"
)

// BalanceSelector selects source/target from store candidates based on their
// resource scores.
type BalanceSelector struct {
kind core.ScheduleKind
filters []filter.Filter
}

// NewBalanceSelector creates a BalanceSelector instance.
func NewBalanceSelector(kind core.ScheduleKind, filters []filter.Filter) *BalanceSelector {
return &BalanceSelector{
kind: kind,
filters: filters,
}
}

// SelectSource selects the store that can pass all filters and has the maximal
// resource score.
func (s *BalanceSelector) SelectSource(opt opt.Options, stores []*core.StoreInfo, filters ...filter.Filter) *core.StoreInfo {
filters = append(filters, s.filters...)
var result *core.StoreInfo
for _, store := range stores {
if filter.Source(opt, store, filters) {
continue
}
if result == nil ||
result.ResourceScore(s.kind, 0) <
store.ResourceScore(s.kind, 0) {
result = store
}
}
return result
}

// SelectTarget selects the store that can pass all filters and has the minimal
// resource score.
func (s *BalanceSelector) SelectTarget(opt opt.Options, stores []*core.StoreInfo, filters ...filter.Filter) *core.StoreInfo {
filters = append(filters, s.filters...)
var result *core.StoreInfo
for _, store := range stores {
if filter.Target(opt, store, filters) {
continue
}
if result == nil ||
result.ResourceScore(s.kind, 0) >
store.ResourceScore(s.kind, 0) {
result = store
}
}
return result
}

// ReplicaSelector selects source/target store candidates based on their
// distinct scores based on a region's peer stores.
type ReplicaSelector struct {
Expand Down Expand Up @@ -130,12 +79,12 @@ func (s *ReplicaSelector) SelectTarget(opt opt.Options, stores []*core.StoreInfo
// Returns -1 if store B is better than store A.
func compareStoreScore(storeA *core.StoreInfo, storeB *core.StoreInfo) int {
// The store with lower region score is better.
if storeA.RegionScore() <
storeB.RegionScore() {
if storeA.GetRegionSize() <
storeB.GetRegionSize() {
return 1
}
if storeA.RegionScore() >
storeB.RegionScore() {
if storeA.GetRegionSize() >
storeB.GetRegionSize() {
return -1
}
return 0
Expand Down
35 changes: 0 additions & 35 deletions scheduler/server/schedule/selector/selector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"github.com/pingcap-incubator/tinykv/scheduler/pkg/mock/mockcluster"
"github.com/pingcap-incubator/tinykv/scheduler/pkg/mock/mockoption"
"github.com/pingcap-incubator/tinykv/scheduler/server/core"
"github.com/pingcap-incubator/tinykv/scheduler/server/schedule/filter"
. "github.com/pingcap/check"
)

Expand Down Expand Up @@ -47,37 +46,3 @@ func (s *testSelectorSuite) TestCompareStoreScore(c *C) {

c.Assert(compareStoreScore(store1, store3), Equals, 1)
}

func (s *testSelectorSuite) TestScheduleConfig(c *C) {
filters := make([]filter.Filter, 0)
testScheduleConfig := func(selector *BalanceSelector, stores []*core.StoreInfo, expectSourceID, expectTargetID uint64) {
c.Assert(selector.SelectSource(s.tc, stores).GetID(), Equals, expectSourceID)
c.Assert(selector.SelectTarget(s.tc, stores).GetID(), Equals, expectTargetID)
}

kinds := []core.ScheduleKind{{
Resource: core.RegionKind,
}}

for _, kind := range kinds {
selector := NewBalanceSelector(kind, filters)
stores := []*core.StoreInfo{
core.NewStoreInfoWithSizeCount(1, 2, 3, 10, 5),
core.NewStoreInfoWithSizeCount(2, 2, 3, 4, 5),
core.NewStoreInfoWithSizeCount(3, 2, 3, 4, 5),
core.NewStoreInfoWithSizeCount(4, 2, 3, 2, 5),
}
testScheduleConfig(selector, stores, 1, 4)
}

selector := NewBalanceSelector(core.ScheduleKind{
Resource: core.LeaderKind,
}, filters)
stores := []*core.StoreInfo{
core.NewStoreInfoWithSizeCount(1, 2, 20, 10, 25),
core.NewStoreInfoWithSizeCount(2, 2, 66, 10, 5),
core.NewStoreInfoWithSizeCount(3, 2, 6, 10, 5),
core.NewStoreInfoWithSizeCount(4, 2, 20, 10, 1),
}
testScheduleConfig(selector, stores, 2, 3)
}
9 changes: 4 additions & 5 deletions scheduler/server/schedulers/balance_leader.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ func (l *balanceLeaderScheduler) Schedule(cluster opt.Cluster) *operator.Operato
sources := filter.SelectSourceStores(stores, l.filters, cluster)
targets := filter.SelectTargetStores(stores, l.filters, cluster)
sort.Slice(sources, func(i, j int) bool {
return sources[i].LeaderScore(0) > sources[j].LeaderScore(0)
return sources[i].GetLeaderCount() > sources[j].GetLeaderCount()
})
sort.Slice(targets, func(i, j int) bool {
return targets[i].LeaderScore(0) < targets[j].LeaderScore(0)
return targets[i].GetLeaderCount() < targets[j].GetLeaderCount()
})

for i := 0; i < len(sources) || i < len(targets); i++ {
Expand Down Expand Up @@ -133,7 +133,7 @@ func (l *balanceLeaderScheduler) transferLeaderOut(cluster opt.Cluster, source *
targets := cluster.GetFollowerStores(region)
targets = filter.SelectTargetStores(targets, l.filters, cluster)
sort.Slice(targets, func(i, j int) bool {
return targets[i].LeaderScore(0) < targets[j].LeaderScore(0)
return targets[i].GetLeaderCount() < targets[j].GetLeaderCount()
})
for _, target := range targets {
if op := l.createOperator(cluster, region, source, target); op != nil {
Expand Down Expand Up @@ -174,8 +174,7 @@ func (l *balanceLeaderScheduler) transferLeaderIn(cluster opt.Cluster, target *c
func (l *balanceLeaderScheduler) createOperator(cluster opt.Cluster, region *core.RegionInfo, source, target *core.StoreInfo) *operator.Operator {
targetID := target.GetID()

kind := core.NewScheduleKind(core.LeaderKind)
if !shouldBalance(cluster, source, target, region, kind, l.GetName()) {
if source.GetLeaderCount()-target.GetLeaderCount() < 2*int(1.0*leaderTolerantSizeRatio) {
return nil
}

Expand Down
36 changes: 5 additions & 31 deletions scheduler/server/schedulers/balance_region.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,14 @@ func (s *balanceRegionScheduler) Schedule(cluster opt.Cluster) *operator.Operato
var stores []*core.StoreInfo

for _, store := range allStores {
if store.DownTime() > cluster.GetMaxStoreDownTime() || store.IsTombstone() || store.IsBusy() || !store.IsAvailable() {
if !store.IsUp() || store.DownTime() > cluster.GetMaxStoreDownTime() {
continue
}
stores = append(stores, store)
}

sort.Slice(stores, func(i, j int) bool {
return stores[i].RegionScore() > stores[j].RegionScore()
return stores[i].GetRegionSize() > stores[j].GetRegionSize()
})
for _, source := range stores {
sourceID := source.GetID()
Expand Down Expand Up @@ -159,7 +159,7 @@ func (s *balanceRegionScheduler) transferPeer(cluster opt.Cluster, region *core.
targetID := target.GetID()
log.Debug("", zap.Uint64("region-id", regionID), zap.Uint64("source-store", sourceID), zap.Uint64("target-store", targetID))

if int64(source.RegionScore()-target.RegionScore()) < getThreshold(cluster, region) {
if int64(source.GetRegionSize()-target.GetRegionSize()) < 2*region.GetApproximateSize() {
return nil
}

Expand All @@ -184,11 +184,11 @@ func selectBestReplacementStore(cluster opt.Cluster, region *core.RegionInfo) ui
continue
}

if !store.IsUp() || store.IsBusy() || store.DownTime() > cluster.GetMaxStoreDownTime() {
if !store.IsUp() || store.DownTime() > cluster.GetMaxStoreDownTime() {
continue
}

if best == nil || store.RegionScore() < best.RegionScore() {
if best == nil || store.GetRegionSize() < best.GetRegionSize() {
best = store
}
}
Expand All @@ -197,29 +197,3 @@ func selectBestReplacementStore(cluster opt.Cluster, region *core.RegionInfo) ui
}
return best.GetID()
}

func getThreshold(cluster opt.Cluster, region *core.RegionInfo) int64 {
regionSize := region.GetApproximateSize()
if regionSize < cluster.GetAverageRegionSize() {
regionSize = cluster.GetAverageRegionSize()
}
regionSize = int64(float64(regionSize)*getThresholdRatio(cluster)) * 2
return regionSize
}

func getThresholdRatio(cluster opt.Cluster) float64 {
var maxRegionCount float64
stores := cluster.GetStores()
for _, store := range stores {
regionCount := float64(cluster.GetStoreRegionCount(store.GetID()))
if maxRegionCount < regionCount {
maxRegionCount = regionCount
}
}
thresholdRatio := maxRegionCount * adjustRatio
if thresholdRatio < minTolerantSizeRatio {
thresholdRatio = minTolerantSizeRatio
}

return thresholdRatio
}

0 comments on commit f660f80

Please sign in to comment.