@@ -2,7 +2,10 @@ package schedulers
2
2
3
3
import (
4
4
"github.com/pingcap/kvproto/pkg/metapb"
5
+ "github.com/tikv/pd/pkg/schedule/placement"
6
+ "go.uber.org/zap"
5
7
"net/http"
8
+ "sort"
6
9
"time"
7
10
8
11
"github.com/gorilla/mux"
@@ -25,10 +28,10 @@ const balanceKeyRangeName = "balance-key-ranges"
25
28
26
29
type balanceKeyRangeSchedulerHandler struct {
27
30
rd * render.Render
28
- config * balanceKeyRangeSchedulerConfig
31
+ config * balanceRangeSchedulerConfig
29
32
}
30
33
31
- func newBalanceKeyRangeHandler (conf * balanceKeyRangeSchedulerConfig ) http.Handler {
34
+ func newBalanceKeyRangeHandler (conf * balanceRangeSchedulerConfig ) http.Handler {
32
35
handler := & balanceKeyRangeSchedulerHandler {
33
36
config : conf ,
34
37
rd : render .New (render.Options {IndentJSON : true }),
@@ -50,31 +53,31 @@ func (handler *balanceKeyRangeSchedulerHandler) listConfig(w http.ResponseWriter
50
53
}
51
54
}
52
55
53
- type balanceKeyRangeSchedulerConfig struct {
56
+ type balanceRangeSchedulerConfig struct {
54
57
syncutil.RWMutex
55
58
schedulerConfig
56
- balanceKeyRangeSchedulerParam
59
+ balanceRangeSchedulerParam
57
60
}
58
61
59
- type balanceKeyRangeSchedulerParam struct {
62
+ type balanceRangeSchedulerParam struct {
60
63
Role string `json:"role"`
61
64
Engine string `json:"engine"`
62
65
Timeout time.Duration `json:"timeout"`
63
66
Ranges []core.KeyRange `json:"ranges"`
64
67
}
65
68
66
- func (conf * balanceKeyRangeSchedulerConfig ) encodeConfig () ([]byte , error ) {
69
+ func (conf * balanceRangeSchedulerConfig ) encodeConfig () ([]byte , error ) {
67
70
conf .RLock ()
68
71
defer conf .RUnlock ()
69
72
return EncodeConfig (conf )
70
73
}
71
74
72
- func (conf * balanceKeyRangeSchedulerConfig ) clone () * balanceKeyRangeSchedulerParam {
75
+ func (conf * balanceRangeSchedulerConfig ) clone () * balanceRangeSchedulerParam {
73
76
conf .RLock ()
74
77
defer conf .RUnlock ()
75
78
ranges := make ([]core.KeyRange , len (conf .Ranges ))
76
79
copy (ranges , conf .Ranges )
77
- return & balanceKeyRangeSchedulerParam {
80
+ return & balanceRangeSchedulerParam {
78
81
Ranges : ranges ,
79
82
Role : conf .Role ,
80
83
Engine : conf .Engine ,
@@ -83,16 +86,16 @@ func (conf *balanceKeyRangeSchedulerConfig) clone() *balanceKeyRangeSchedulerPar
83
86
}
84
87
85
88
// EncodeConfig serializes the config.
86
- func (s * balanceKeyRangeScheduler ) EncodeConfig () ([]byte , error ) {
89
+ func (s * balanceRangeScheduler ) EncodeConfig () ([]byte , error ) {
87
90
return s .conf .encodeConfig ()
88
91
}
89
92
90
93
// ReloadConfig reloads the config.
91
- func (s * balanceKeyRangeScheduler ) ReloadConfig () error {
94
+ func (s * balanceRangeScheduler ) ReloadConfig () error {
92
95
s .conf .Lock ()
93
96
defer s .conf .Unlock ()
94
97
95
- newCfg := & balanceKeyRangeSchedulerConfig {}
98
+ newCfg := & balanceRangeSchedulerConfig {}
96
99
if err := s .conf .load (newCfg ); err != nil {
97
100
return err
98
101
}
@@ -103,9 +106,9 @@ func (s *balanceKeyRangeScheduler) ReloadConfig() error {
103
106
return nil
104
107
}
105
108
106
- type balanceKeyRangeScheduler struct {
109
+ type balanceRangeScheduler struct {
107
110
* BaseScheduler
108
- conf * balanceKeyRangeSchedulerConfig
111
+ conf * balanceRangeSchedulerConfig
109
112
handler http.Handler
110
113
start time.Time
111
114
role Role
@@ -114,31 +117,31 @@ type balanceKeyRangeScheduler struct {
114
117
}
115
118
116
119
// ServeHTTP implements the http.Handler interface.
117
- func (s * balanceKeyRangeScheduler ) ServeHTTP (w http.ResponseWriter , r * http.Request ) {
120
+ func (s * balanceRangeScheduler ) ServeHTTP (w http.ResponseWriter , r * http.Request ) {
118
121
s .handler .ServeHTTP (w , r )
119
122
}
120
123
121
124
// IsScheduleAllowed checks if the scheduler is allowed to schedule new operators.
122
- func (s * balanceKeyRangeScheduler ) IsScheduleAllowed (cluster sche.SchedulerCluster ) bool {
123
- allowed := s .OpController .OperatorCount (operator .OpKeyRange ) < cluster .GetSchedulerConfig ().GetRegionScheduleLimit ()
125
+ func (s * balanceRangeScheduler ) IsScheduleAllowed (cluster sche.SchedulerCluster ) bool {
126
+ allowed := s .OpController .OperatorCount (operator .OpRange ) < cluster .GetSchedulerConfig ().GetRegionScheduleLimit ()
124
127
if ! allowed {
125
- operator .IncOperatorLimitCounter (s .GetType (), operator .OpKeyRange )
128
+ operator .IncOperatorLimitCounter (s .GetType (), operator .OpRange )
126
129
}
127
130
if time .Now ().Sub (s .start ) > s .conf .Timeout {
128
131
allowed = false
129
- balanceExpiredCounter .Inc ()
132
+ balanceRangeExpiredCounter .Inc ()
130
133
}
131
134
return allowed
132
135
}
133
136
134
137
// BalanceKeyRangeCreateOption is used to create a scheduler with an option.
135
- type BalanceKeyRangeCreateOption func (s * balanceKeyRangeScheduler )
138
+ type BalanceKeyRangeCreateOption func (s * balanceRangeScheduler )
136
139
137
140
// newBalanceKeyRangeScheduler creates a scheduler that tends to keep given peer role on
138
141
// special store balanced.
139
- func newBalanceKeyRangeScheduler (opController * operator.Controller , conf * balanceKeyRangeSchedulerConfig , options ... BalanceKeyRangeCreateOption ) Scheduler {
140
- s := & balanceKeyRangeScheduler {
141
- BaseScheduler : NewBaseScheduler (opController , types .BalanceKeyRangeScheduler , conf ),
142
+ func newBalanceKeyRangeScheduler (opController * operator.Controller , conf * balanceRangeSchedulerConfig , options ... BalanceKeyRangeCreateOption ) Scheduler {
143
+ s := & balanceRangeScheduler {
144
+ BaseScheduler : NewBaseScheduler (opController , types .BalanceRangeScheduler , conf ),
142
145
conf : conf ,
143
146
handler : newBalanceKeyRangeHandler (conf ),
144
147
start : time .Now (),
@@ -160,55 +163,126 @@ func newBalanceKeyRangeScheduler(opController *operator.Controller, conf *balanc
160
163
}
161
164
162
165
// Schedule schedules the balance key range operator.
163
- func (s * balanceKeyRangeScheduler ) Schedule (cluster sche.SchedulerCluster , dryRun bool ) ([]* operator.Operator , []plan.Plan ) {
164
- balanceKeyRangeCounter .Inc ()
166
+ func (s * balanceRangeScheduler ) Schedule (cluster sche.SchedulerCluster , dryRun bool ) ([]* operator.Operator , []plan.Plan ) {
167
+ balanceRangeCounter .Inc ()
165
168
plan ,err := s .prepare (cluster )
169
+ downFilter := filter .NewRegionDownFilter ()
170
+ replicaFilter := filter .NewRegionReplicatedFilter (cluster )
171
+ snapshotFilter := filter .NewSnapshotSendFilter (plan .stores , constant .Medium )
172
+ baseRegionFilters := []filter.RegionFilter {downFilter , replicaFilter , snapshotFilter }
173
+
174
+ for sourceIndex ,sourceStore := range plan .stores {
175
+ plan .source = sourceStore
176
+ switch s .role {
177
+ case Leader :
178
+ plan .region = filter .SelectOneRegion (cluster .RandLeaderRegions (plan .sourceStoreID (), s .conf .Ranges ), nil ,baseRegionFilters ... )
179
+ case Learner :
180
+ plan .region = filter .SelectOneRegion (cluster .RandLearnerRegions (plan .sourceStoreID (), s .conf .Ranges ), nil ,baseRegionFilters ... )
181
+ case Follower :
182
+ plan .region = filter .SelectOneRegion (cluster .RandFollowerRegions (plan .sourceStoreID (), s .conf .Ranges ), nil ,baseRegionFilters ... )
183
+ }
184
+ if plan .region == nil {
185
+ balanceRangeNoRegionCounter .Inc ()
186
+ continue
187
+ }
188
+ log .Debug ("select region" , zap .String ("scheduler" , s .GetName ()), zap .Uint64 ("region-id" , plan .region .GetID ()))
189
+ // Skip hot regions.
190
+ if cluster .IsRegionHot (plan .region ) {
191
+ log .Debug ("region is hot" , zap .String ("scheduler" , s .GetName ()), zap .Uint64 ("region-id" , plan .region .GetID ()))
192
+ balanceRangeHotCounter .Inc ()
193
+ continue
194
+ }
195
+ // Check region leader
196
+ if plan .region .GetLeader () == nil {
197
+ log .Warn ("region have no leader" , zap .String ("scheduler" , s .GetName ()), zap .Uint64 ("region-id" , solver .Region .GetID ()))
198
+ balanceRangeNoLeaderCounter .Inc ()
199
+ continue
200
+ }
201
+ plan .fit = replicaFilter .(* filter.RegionReplicatedFilter ).GetFit ()
202
+ if op := s .transferPeer (plan , plan .stores [sourceIndex + 1 :]); op != nil {
203
+ op .Counters = append (op .Counters , balanceRegionNewOpCounter )
204
+ return []* operator.Operator {op }, nil
205
+ }
206
+ }
207
+
166
208
if err != nil {
167
209
log .Error ("failed to prepare balance key range scheduler" , errs .ZapError (err ))
168
210
return nil ,nil
169
211
170
212
}
171
213
}
172
214
173
- // BalanceKeyRangeSchedulerPlan is used to record the plan of balance key range scheduler.
174
- type BalanceKeyRangeSchedulerPlan struct {
175
- source []* core.StoreInfo
176
- // store_id -> score
177
- scores map [uint64 ]uint64
178
- // store_id -> peer
179
- regions map [uint64 ]* metapb.Peer
215
+ // transferPeer selects the best store to create a new peer to replace the old peer.
216
+ func (s * balanceRangeScheduler ) transferPeer (plan * balanceRangeSchedulerPlan , dstStores []* storeInfo ) * operator.Operator {
217
+ excludeTargets := plan .region .GetStoreIDs ()
218
+ if s .role != Leader {
219
+ excludeTargets = append (excludeTargets , plan .sourceStoreID ())
220
+ }
221
+ return nil
222
+ }
223
+
224
+ // balanceRangeSchedulerPlan is used to record the plan of balance key range scheduler.
225
+ type balanceRangeSchedulerPlan struct {
226
+ // stores is sorted by score desc
227
+ stores []* storeInfo
228
+ source * storeInfo
229
+ target * storeInfo
230
+ region * core.RegionInfo
231
+ fit * placement.RegionFit
232
+ }
233
+
234
+ type storeInfo struct {
235
+ store * core.StoreInfo
236
+ score uint64
180
237
}
181
238
182
- func (s * balanceKeyRangeScheduler ) prepare (cluster sche.SchedulerCluster )(* BalanceKeyRangeSchedulerPlan ,error ) {
239
+ func (s * balanceRangeScheduler ) prepare (cluster sche.SchedulerCluster )(* balanceRangeSchedulerPlan ,error ) {
183
240
krs := core .NewKeyRanges (s .conf .Ranges )
184
241
scanRegions , err := cluster .BatchScanRegions (krs )
185
242
if err != nil {
186
243
return nil ,err
187
244
}
188
- stores := cluster .GetStores ()
189
- sources := filter .SelectSourceStores (stores , s .filters , cluster .GetSchedulerConfig (), nil , nil )
190
- scores := make (map [uint64 ]uint64 , len (sources ))
191
- regions := make (map [uint64 ]* metapb.Peer ,len (scanRegions ))
245
+ sources := filter .SelectSourceStores (cluster .GetStores (), s .filters , cluster .GetSchedulerConfig (), nil , nil )
246
+ storeInfos := make (map [uint64 ]* storeInfo ,len (sources ))
247
+ for _ , source := range sources {
248
+ storeInfos [source .GetID ()] = & storeInfo {store : source }
249
+ }
192
250
for _ , region := range scanRegions {
193
251
for _ , peer := range s .role .getPeers (region ) {
194
- scores [peer .GetStoreId ()] += 1
195
- regions [peer .GetStoreId ()] = peer
252
+ storeInfos [peer .GetStoreId ()].score += 1
196
253
}
197
254
}
198
- return & BalanceKeyRangeSchedulerPlan {
199
- source : sources ,
200
- scores : scores ,
201
- regions : regions ,
255
+
256
+ stores := make ([]* storeInfo ,0 ,len (storeInfos ))
257
+ for _ , store := range storeInfos {
258
+ stores = append (stores , store )
259
+ }
260
+ sort .Slice (stores , func (i , j int ) bool {
261
+ return stores [i ].score > stores [j ].score
262
+ })
263
+ return & balanceRangeSchedulerPlan {
264
+ stores :stores ,
265
+ source : nil ,
266
+ target : nil ,
267
+ region : nil ,
202
268
},nil
203
269
}
204
270
271
+ func (p * balanceRangeSchedulerPlan ) sourceStoreID () uint64 {
272
+ return p .source .store .GetID ()
273
+ }
274
+
275
+ func (p * balanceRangeSchedulerPlan ) targetStoreID () uint64 {
276
+ return p .target .store .GetID ()
277
+ }
278
+
205
279
206
280
207
281
type Role int
208
282
209
283
const (
210
284
Leader Role = iota
211
- Voter
285
+ Follower
212
286
Learner
213
287
Unknown
214
288
RoleLen
@@ -218,7 +292,7 @@ func (r Role) String() string {
218
292
switch r {
219
293
case Leader :
220
294
return "leader"
221
- case Voter :
295
+ case Follower :
222
296
return "voter"
223
297
case Learner :
224
298
return "learner"
@@ -231,8 +305,8 @@ func NewRole(role string) Role {
231
305
switch role {
232
306
case "leader" :
233
307
return Leader
234
- case "voter " :
235
- return Voter
308
+ case "follower " :
309
+ return Follower
236
310
case "learner" :
237
311
return Learner
238
312
default :
@@ -244,8 +318,13 @@ func (r Role) getPeers(region *core.RegionInfo) []*metapb.Peer {{
244
318
switch r {
245
319
case Leader :
246
320
return []* metapb.Peer {region .GetLeader ()}
247
- case Voter :
248
- return region .GetVoters ()
321
+ case Follower :
322
+ followers := region .GetFollowers ()
323
+ ret := make ([]* metapb.Peer ,len (followers ))
324
+ for _ ,peer := range followers {
325
+ ret = append (ret ,peer )
326
+ }
327
+ return ret
249
328
case Learner :
250
329
return region .GetLearners ()
251
330
default :
0 commit comments