Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

*: add region option for random pick region #1005

Merged
merged 4 commits into from
Mar 27, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions server/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,10 +279,10 @@ func (c *clusterInfo) getRegions() []*core.RegionInfo {
return c.Regions.GetRegions()
}

func (c *clusterInfo) randomRegion() *core.RegionInfo {
func (c *clusterInfo) randomRegion(opts ...core.RegionOption) *core.RegionInfo {
c.RLock()
defer c.RUnlock()
return c.Regions.RandRegion()
return c.Regions.RandRegion(opts...)
}

func (c *clusterInfo) getMetaRegions() []*metapb.Region {
Expand Down Expand Up @@ -324,17 +324,17 @@ func (c *clusterInfo) getStoreLeaderCount(storeID uint64) int {
}

// RandLeaderRegion returns a random region that has leader on the store.
func (c *clusterInfo) RandLeaderRegion(storeID uint64) *core.RegionInfo {
func (c *clusterInfo) RandLeaderRegion(storeID uint64, ops ...core.RegionOption) *core.RegionInfo {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/ops/opts

c.RLock()
defer c.RUnlock()
return c.BasicCluster.RandLeaderRegion(storeID)
return c.BasicCluster.RandLeaderRegion(storeID, ops...)
}

// RandFollowerRegion returns a random region that has a follower on the store.
func (c *clusterInfo) RandFollowerRegion(storeID uint64) *core.RegionInfo {
func (c *clusterInfo) RandFollowerRegion(storeID uint64, ops ...core.RegionOption) *core.RegionInfo {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

c.RLock()
defer c.RUnlock()
return c.BasicCluster.RandFollowerRegion(storeID)
return c.BasicCluster.RandFollowerRegion(storeID, ops...)
}

// GetRegionStores returns all stores that contains the region's peer.
Expand Down
10 changes: 5 additions & 5 deletions server/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,10 @@ func (s *testRegionsInfoSuite) Test(c *C) {
}

for i := uint64(0); i < n; i++ {
region := cache.RandLeaderRegion(i)
region := cache.RandLeaderRegion(i, core.HealthRegion())
c.Assert(region.Leader.GetStoreId(), Equals, i)

region = cache.RandFollowerRegion(i)
region = cache.RandFollowerRegion(i, core.HealthRegion())
c.Assert(region.Leader.GetStoreId(), Not(Equals), i)

c.Assert(region.GetStorePeer(i), NotNil)
Expand All @@ -166,14 +166,14 @@ func (s *testRegionsInfoSuite) Test(c *C) {
// All regions will be filtered out if they have pending peers.
for i := uint64(0); i < n; i++ {
for j := 0; j < cache.GetStoreLeaderCount(i); j++ {
region := cache.RandLeaderRegion(i)
region := cache.RandLeaderRegion(i, core.HealthRegion())
region.PendingPeers = region.Peers
cache.SetRegion(region)
}
c.Assert(cache.RandLeaderRegion(i), IsNil)
c.Assert(cache.RandLeaderRegion(i, core.HealthRegion()), IsNil)
}
for i := uint64(0); i < n; i++ {
c.Assert(cache.RandFollowerRegion(i), IsNil)
c.Assert(cache.RandFollowerRegion(i, core.HealthRegion()), IsNil)
}
}

Expand Down
35 changes: 26 additions & 9 deletions server/core/region.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ import (
"github.com/pingcap/kvproto/pkg/pdpb"
)

// RegionOption used to select region
type RegionOption func(region *RegionInfo) bool

// HealthRegion checks if the region is healthy
func HealthRegion() RegionOption {
return func(region *RegionInfo) bool {
return len(region.DownPeers) == 0 && len(region.PendingPeers) == 0
}
}

// RegionInfo records detail region info.
type RegionInfo struct {
*metapb.Region
Expand Down Expand Up @@ -478,18 +488,18 @@ func (r *RegionsInfo) GetStoreFollowerCount(storeID uint64) int {
}

// RandRegion get a region by random
func (r *RegionsInfo) RandRegion() *RegionInfo {
return randRegion(r.regions)
func (r *RegionsInfo) RandRegion(opts ...RegionOption) *RegionInfo {
return randRegion(r.regions, opts...)
}

// RandLeaderRegion get a store's leader region by random
func (r *RegionsInfo) RandLeaderRegion(storeID uint64) *RegionInfo {
return randRegion(r.leaders[storeID])
func (r *RegionsInfo) RandLeaderRegion(storeID uint64, opts ...RegionOption) *RegionInfo {
return randRegion(r.leaders[storeID], opts...)
}

// RandFollowerRegion get a store's follower region by random
func (r *RegionsInfo) RandFollowerRegion(storeID uint64) *RegionInfo {
return randRegion(r.followers[storeID])
func (r *RegionsInfo) RandFollowerRegion(storeID uint64, opts ...RegionOption) *RegionInfo {
return randRegion(r.followers[storeID], opts...)
}

// GetLeader return leader RegionInfo by storeID and regionID(now only used in test)
Expand Down Expand Up @@ -581,14 +591,21 @@ func (r *RegionsInfo) GetRegionStats(startKey, endKey []byte) *RegionStats {

const randomRegionMaxRetry = 10

func randRegion(regions *regionMap) *RegionInfo {
func randRegion(regions *regionMap, opts ...RegionOption) *RegionInfo {
for i := 0; i < randomRegionMaxRetry; i++ {
region := regions.RandomRegion()
if region == nil {
return nil
}
if len(region.DownPeers) == 0 && len(region.PendingPeers) == 0 {
return region.Clone()
isSelect := true
for _, opt := range opts {
if !opt(region) {
isSelect = false
break
}
}
if isSelect {
return region
}
}
return nil
Expand Down
8 changes: 4 additions & 4 deletions server/namespace_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ func (c *namespaceCluster) checkRegion(region *core.RegionInfo) bool {
const randRegionMaxRetry = 10

// RandFollowerRegion returns a random region that has a follower on the store.
func (c *namespaceCluster) RandFollowerRegion(storeID uint64) *core.RegionInfo {
func (c *namespaceCluster) RandFollowerRegion(storeID uint64, ops ...core.RegionOption) *core.RegionInfo {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto.

for i := 0; i < randRegionMaxRetry; i++ {
r := c.Cluster.RandFollowerRegion(storeID)
r := c.Cluster.RandFollowerRegion(storeID, ops...)
if r == nil {
return nil
}
Expand All @@ -74,9 +74,9 @@ func (c *namespaceCluster) RandFollowerRegion(storeID uint64) *core.RegionInfo {
}

// RandLeaderRegion returns a random region that has leader on the store.
func (c *namespaceCluster) RandLeaderRegion(storeID uint64) *core.RegionInfo {
func (c *namespaceCluster) RandLeaderRegion(storeID uint64, ops ...core.RegionOption) *core.RegionInfo {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

for i := 0; i < randRegionMaxRetry; i++ {
r := c.Cluster.RandLeaderRegion(storeID)
r := c.Cluster.RandLeaderRegion(storeID, ops...)
if r == nil {
return nil
}
Expand Down
8 changes: 4 additions & 4 deletions server/schedule/basic_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,13 @@ func (bc *BasicCluster) UnblockStore(storeID uint64) {
}

// RandFollowerRegion returns a random region that has a follower on the store.
func (bc *BasicCluster) RandFollowerRegion(storeID uint64) *core.RegionInfo {
return bc.Regions.RandFollowerRegion(storeID)
func (bc *BasicCluster) RandFollowerRegion(storeID uint64, ops ...core.RegionOption) *core.RegionInfo {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

return bc.Regions.RandFollowerRegion(storeID, ops...)
}

// RandLeaderRegion returns a random region that has leader on the store.
func (bc *BasicCluster) RandLeaderRegion(storeID uint64) *core.RegionInfo {
return bc.Regions.RandLeaderRegion(storeID)
func (bc *BasicCluster) RandLeaderRegion(storeID uint64, ops ...core.RegionOption) *core.RegionInfo {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

return bc.Regions.RandLeaderRegion(storeID, ops...)
}

// IsRegionHot checks if a region is in hot state.
Expand Down
4 changes: 2 additions & 2 deletions server/schedule/scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ import (

// Cluster provides an overview of a cluster's regions distribution.
type Cluster interface {
RandFollowerRegion(storeID uint64) *core.RegionInfo
RandLeaderRegion(storeID uint64) *core.RegionInfo
RandFollowerRegion(storeID uint64, ops ...core.RegionOption) *core.RegionInfo
RandLeaderRegion(storeID uint64, ops ...core.RegionOption) *core.RegionInfo

GetStores() []*core.StoreInfo
GetStore(id uint64) *core.StoreInfo
Expand Down
4 changes: 2 additions & 2 deletions server/schedulers/balance_leader.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func (l *balanceLeaderScheduler) Schedule(cluster schedule.Cluster, opInfluence
}

func (l *balanceLeaderScheduler) transferLeaderOut(source *core.StoreInfo, cluster schedule.Cluster, opInfluence schedule.OpInfluence) []*schedule.Operator {
region := cluster.RandLeaderRegion(source.GetId())
region := cluster.RandLeaderRegion(source.GetId(), core.HealthRegion())
if region == nil {
log.Debugf("[%s] store%d has no leader", l.GetName(), source.GetId())
schedulerCounter.WithLabelValues(l.GetName(), "no_leader_region").Inc()
Expand All @@ -132,7 +132,7 @@ func (l *balanceLeaderScheduler) transferLeaderOut(source *core.StoreInfo, clust
}

func (l *balanceLeaderScheduler) transferLeaderIn(target *core.StoreInfo, cluster schedule.Cluster, opInfluence schedule.OpInfluence) []*schedule.Operator {
region := cluster.RandFollowerRegion(target.GetId())
region := cluster.RandFollowerRegion(target.GetId(), core.HealthRegion())
if region == nil {
log.Debugf("[%s] store%d has no follower", l.GetName(), target.GetId())
schedulerCounter.WithLabelValues(l.GetName(), "no_follower_region").Inc()
Expand Down
4 changes: 2 additions & 2 deletions server/schedulers/balance_region.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ func (s *balanceRegionScheduler) Schedule(cluster schedule.Cluster, opInfluence
balanceRegionCounter.WithLabelValues("source_store", sourceLabel).Inc()

for i := 0; i < balanceRegionRetryLimit; i++ {
region := cluster.RandFollowerRegion(source.GetId())
region := cluster.RandFollowerRegion(source.GetId(), core.HealthRegion())
if region == nil {
region = cluster.RandLeaderRegion(source.GetId())
region = cluster.RandLeaderRegion(source.GetId(), core.HealthRegion())
}
if region == nil {
schedulerCounter.WithLabelValues(s.GetName(), "no_region").Inc()
Expand Down
2 changes: 1 addition & 1 deletion server/schedulers/evict_leader.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func (s *evictLeaderScheduler) IsScheduleAllowed(cluster schedule.Cluster) bool

func (s *evictLeaderScheduler) Schedule(cluster schedule.Cluster, opInfluence schedule.OpInfluence) []*schedule.Operator {
schedulerCounter.WithLabelValues(s.GetName(), "schedule").Inc()
region := cluster.RandLeaderRegion(s.storeID)
region := cluster.RandLeaderRegion(s.storeID, core.HealthRegion())
if region == nil {
schedulerCounter.WithLabelValues(s.GetName(), "no_leader").Inc()
return nil
Expand Down
2 changes: 1 addition & 1 deletion server/schedulers/grant_leader.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func (s *grantLeaderScheduler) IsScheduleAllowed(cluster schedule.Cluster) bool

func (s *grantLeaderScheduler) Schedule(cluster schedule.Cluster, opInfluence schedule.OpInfluence) []*schedule.Operator {
schedulerCounter.WithLabelValues(s.GetName(), "schedule").Inc()
region := cluster.RandFollowerRegion(s.storeID)
region := cluster.RandFollowerRegion(s.storeID, core.HealthRegion())
if region == nil {
schedulerCounter.WithLabelValues(s.GetName(), "no_follower").Inc()
return nil
Expand Down
2 changes: 1 addition & 1 deletion server/schedulers/label.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (s *labelScheduler) Schedule(cluster schedule.Cluster, opInfluence schedule
}
log.Debugf("label scheduler reject leader store list: %v", rejectLeaderStores)
for id := range rejectLeaderStores {
if region := cluster.RandLeaderRegion(id); region != nil {
if region := cluster.RandLeaderRegion(id, core.HealthRegion()); region != nil {
log.Debugf("label scheduler selects region %d to transfer leader", region.GetId())
target := s.selector.SelectTarget(cluster, cluster.GetFollowerStores(region))
if target == nil {
Expand Down
3 changes: 2 additions & 1 deletion server/schedulers/random_merge.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package schedulers
import (
"math/rand"

"github.com/pingcap/pd/server/core"
"github.com/pingcap/pd/server/schedule"
)

Expand Down Expand Up @@ -65,7 +66,7 @@ func (s *randomMergeScheduler) Schedule(cluster schedule.Cluster, opInfluence sc
schedulerCounter.WithLabelValues(s.GetName(), "no_store").Inc()
return nil
}
region := cluster.RandLeaderRegion(store.GetId())
region := cluster.RandLeaderRegion(store.GetId(), core.HealthRegion())
if region == nil {
schedulerCounter.WithLabelValues(s.GetName(), "no_region").Inc()
return nil
Expand Down
2 changes: 1 addition & 1 deletion server/schedulers/shuffle_leader.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func (s *shuffleLeaderScheduler) Schedule(cluster schedule.Cluster, opInfluence
schedulerCounter.WithLabelValues(s.GetName(), "no_target_store").Inc()
return nil
}
region := cluster.RandFollowerRegion(targetStore.GetId())
region := cluster.RandFollowerRegion(targetStore.GetId(), core.HealthRegion())
if region == nil {
schedulerCounter.WithLabelValues(s.GetName(), "no_follower").Inc()
return nil
Expand Down
4 changes: 2 additions & 2 deletions server/schedulers/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ func scheduleRemovePeer(cluster schedule.Cluster, schedulerName string, s schedu
return nil, nil
}

region := cluster.RandFollowerRegion(source.GetId())
region := cluster.RandFollowerRegion(source.GetId(), core.HealthRegion())
if region == nil {
region = cluster.RandLeaderRegion(source.GetId())
region = cluster.RandLeaderRegion(source.GetId(), core.HealthRegion())
}
if region == nil {
schedulerCounter.WithLabelValues(schedulerName, "no_region").Inc()
Expand Down