Skip to content

Commit 9fda354

Browse files
committed
rebalancer: introduce rebalancer_mode
Closes #432 @TarantoolBot document Title: vshard: rebalancer flag and mode So far it was impossible to specify which instance should run the rebalancer. It was always automatically assigned using some internal rules based on UUIDs. Now the users can choose: - Which specific instance should run the rebalancer. Can be a replica or a master - won't matter. - In which replicaset the instance to run the rebalancer should be selected automatically. - Which instances and whole replicasets should not run the rebalancer even when it is selected automatically. For that there are 2 new options: `rebalancer = <bool>` and `rebalancer_mode = <name>`. The `rebalancer` flag can be either omitted, or set to true, or false. It can be set for replicasets and for specific instances. There can be only one `rebalancer = true` in the whole config. But can be many `rebalancer = false`. * `rebalancer = true` assigned to an instance means that this instance is guaranteed to run the rebalancer service on it. The instance role doesn't matter - it can be a replica or a master. Will run the rebalancer anyway. * `rebalancer = true` assigned to a replicaset means that the service will run only on the master of this replicaset. Can be combined with `master = 'auto'` on the given replicaset. * `rebalancer = false` assigned to an instance means that it will not run the rebalancer. * `rebalancer = false` assigned to a replicaset means that all the instances of this replicaset will not run the rebalancer. * `rebalancer = nil` (same as omitted, default) means that the instance/replicaset will be eligible to run the rebalancer only if `rebalancer_mode = 'auto'` is set and there are no `rebalancer = true` anywhere. The option `rebalancer_mode` should be specified in the root of the config. It can have one of those values: * `'auto'` - default. Means that the rebalancer service location is chosen automatically among all master instances in the cluster. Excluding those which have `rebalancer = false` on them or on their replicaset. If there are any `rebalancer = true`, then this mode works the same as `'manual'`. * `'manual'`. The rebalancer will run only if there is at least one `rebalancer = true` in the config. And only on the given instance / replicaset (depending on at which level the flag was specified - for a specific instance or for a whole replicaset). * `'off'`. The rebalancer will not run anywhere, regardless of all the `rebalancer = true/false` specified in the config.
1 parent d624973 commit 9fda354

File tree

4 files changed

+120
-1
lines changed

4 files changed

+120
-1
lines changed

test/storage-luatest/rebalancer_test.lua

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,3 +233,62 @@ test_group.test_locate_with_flag = function(g)
233233
vtest.cluster_cfg(g, global_cfg)
234234
wait_rebalancer_on_instance(g, 'replica_1_a')
235235
end
236+
237+
test_group.test_rebalancer_mode = function(g)
238+
local new_cfg_template = table.deepcopy(cfg_template)
239+
--
240+
-- Auto-mode won't ignore rebalancer flags. It can only do any difference
241+
-- when the rebalancer is not specified explicitly.
242+
--
243+
new_cfg_template.rebalancer_mode = 'auto'
244+
new_cfg_template.sharding[1].rebalancer = nil
245+
new_cfg_template.sharding[2].rebalancer = true
246+
local new_global_cfg = vtest.config_new(new_cfg_template)
247+
vtest.cluster_cfg(g, new_global_cfg)
248+
wait_rebalancer_on_instance(g, 'replica_2_a')
249+
--
250+
-- The rebalancer false-flags are taken into account.
251+
--
252+
new_cfg_template.sharding[1].rebalancer = false
253+
new_cfg_template.sharding[2].rebalancer = false
254+
new_global_cfg = vtest.config_new(new_cfg_template)
255+
vtest.cluster_cfg(g, new_global_cfg)
256+
wait_rebalancer_on_instance(g, 'replica_3_a')
257+
--
258+
-- The flags don't matter then the rebalancer is off.
259+
--
260+
new_cfg_template.rebalancer_mode = 'off'
261+
new_global_cfg = vtest.config_new(new_cfg_template)
262+
vtest.cluster_cfg(g, new_global_cfg)
263+
wait_rebalancer_on_instance(g, nil)
264+
--
265+
-- Manual with a rebalancer assigned explicitly to an instance.
266+
--
267+
new_cfg_template.rebalancer_mode = 'manual'
268+
new_cfg_template.sharding[2].rebalancer = nil
269+
new_cfg_template.sharding[2].replicas.replica_2_b.rebalancer = true
270+
new_global_cfg = vtest.config_new(new_cfg_template)
271+
vtest.cluster_cfg(g, new_global_cfg)
272+
wait_rebalancer_on_instance(g, 'replica_2_b')
273+
--
274+
-- Manual with a rebalancer assigned explicitly to a replicaset.
275+
--
276+
new_cfg_template.rebalancer_mode = 'manual'
277+
new_cfg_template.sharding[2].replicas.replica_2_b.rebalancer = nil
278+
new_cfg_template.sharding[3].rebalancer = true
279+
new_global_cfg = vtest.config_new(new_cfg_template)
280+
vtest.cluster_cfg(g, new_global_cfg)
281+
wait_rebalancer_on_instance(g, 'replica_3_a')
282+
--
283+
-- Manual with no explicitly assigned rebalancer means no rebalancer at all.
284+
--
285+
new_cfg_template.sharding[3].rebalancer = nil
286+
new_global_cfg = vtest.config_new(new_cfg_template)
287+
vtest.cluster_cfg(g, new_global_cfg)
288+
wait_rebalancer_on_instance(g, nil)
289+
--
290+
-- Cleanup.
291+
--
292+
vtest.cluster_cfg(g, global_cfg)
293+
wait_rebalancer_on_instance(g, 'replica_1_a')
294+
end

test/unit-luatest/config_test.lua

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,3 +211,42 @@ g.test_rebalancer_flag = function()
211211
replicaset_1.rebalancer = nil
212212
storage_1_a.rebalancer = nil
213213
end
214+
215+
g.test_rebalancer_mode = function()
216+
local storage_1_a = {
217+
uri = 'storage:storage@127.0.0.1:3301',
218+
name = 'storage_1_a',
219+
}
220+
local replicaset_1 = {
221+
replicas = {
222+
storage_1_a_uuid = storage_1_a,
223+
},
224+
}
225+
local config = {
226+
sharding = {
227+
storage_1_uuid = replicaset_1,
228+
},
229+
}
230+
t.assert(vcfg.check(config))
231+
232+
local function check_all_flag_combinations()
233+
t.assert(vcfg.check(config))
234+
storage_1_a.rebalancer = true
235+
t.assert(vcfg.check(config))
236+
storage_1_a.rebalancer = nil
237+
replicaset_1.rebalancer = true
238+
t.assert(vcfg.check(config))
239+
replicaset_1.rebalancer = false
240+
t.assert(vcfg.check(config))
241+
replicaset_1.rebalancer = nil
242+
storage_1_a.rebalancer = false
243+
t.assert(vcfg.check(config))
244+
storage_1_a.rebalancer = nil
245+
end
246+
config.rebalancer_mode = 'auto'
247+
check_all_flag_combinations()
248+
config.rebalancer_mode = 'manual'
249+
check_all_flag_combinations()
250+
config.rebalancer_mode = 'off'
251+
check_all_flag_combinations()
252+
end

vshard/cfg.lua

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,12 @@ local function check_discovery_mode(value)
208208
end
209209
end
210210

211+
local function check_rebalancer_mode(value)
212+
if value ~= 'auto' and value ~= 'manual' and value ~= 'off' then
213+
error("Expected 'auto', 'manual', or 'off' for rebalancer_mode")
214+
end
215+
end
216+
211217
local function check_sharding(sharding)
212218
local uuids = {}
213219
local uris = {}
@@ -319,6 +325,13 @@ local cfg_template = {
319325
default = consts.DEFAULT_REBALANCER_MAX_SENDING,
320326
max = consts.REBALANCER_MAX_SENDING_MAX
321327
},
328+
rebalancer_mode = {
329+
type = 'string',
330+
name = 'Rebalancer mode',
331+
is_optional = true,
332+
default = 'auto',
333+
check = check_rebalancer_mode,
334+
},
322335
collect_bucket_garbage_interval = {
323336
name = 'Garbage bucket collect interval', is_deprecated = true,
324337
reason = 'Has no effect anymore'

vshard/storage/init.lua

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3238,8 +3238,10 @@ end
32383238
-- Find UUID of the instance which should run the rebalancer service.
32393239
--
32403240
local function rebalancer_cfg_find_instance(cfg)
3241+
assert(cfg.rebalancer_mode ~= 'off')
32413242
local target_uuid
32423243
local is_assigned
3244+
local is_auto = cfg.rebalancer_mode == 'auto'
32433245
for _, rs in pairs(cfg.sharding) do
32443246
if rs.rebalancer == false then
32453247
goto next_rs
@@ -3253,7 +3255,7 @@ local function rebalancer_cfg_find_instance(cfg)
32533255
end
32543256
local ok = true
32553257
ok = ok and not no_rebalancer
3256-
ok = ok and (replica.master or replica.rebalancer)
3258+
ok = ok and ((is_auto and replica.master) or replica.rebalancer)
32573259
ok = ok and (not target_uuid or replica_uuid < target_uuid)
32583260
ok = ok and (not is_assigned or is_rebalancer)
32593261
if ok then
@@ -3266,8 +3268,10 @@ local function rebalancer_cfg_find_instance(cfg)
32663268
end
32673269

32683270
local function rebalancer_cfg_find_replicaset(cfg)
3271+
assert(cfg.rebalancer_mode ~= 'off')
32693272
local target_uuid
32703273
local is_assigned
3274+
local is_auto = cfg.rebalancer_mode == 'auto'
32713275
for rs_uuid, rs in pairs(cfg.sharding) do
32723276
local is_rebalancer = rs.rebalancer
32733277
local no_rebalancer = rs.rebalancer == false
@@ -3278,6 +3282,7 @@ local function rebalancer_cfg_find_replicaset(cfg)
32783282
local ok = true
32793283
ok = ok and not no_rebalancer
32803284
ok = ok and (rs.master == 'auto')
3285+
ok = ok and (is_auto or is_rebalancer)
32813286
ok = ok and (not target_uuid or rs_uuid < target_uuid)
32823287
ok = ok and (not is_assigned or is_rebalancer)
32833288
if ok then
@@ -3293,6 +3298,9 @@ local function rebalancer_is_needed()
32933298
return false
32943299
end
32953300
local cfg = M.current_cfg
3301+
if cfg.rebalancer_mode == 'off' then
3302+
return false
3303+
end
32963304
local this_replica_uuid = M.this_replica.uuid
32973305
local this_replicaset_uuid = M.this_replicaset.uuid
32983306

0 commit comments

Comments
 (0)