2020/**
2121 * Similar to the {@link ClusterRebalanceAllocationDecider} this
2222 * {@link AllocationDecider} controls the number of currently in-progress
23- * re-balance (relocation) operations and restricts node allocations if the
24- * configured threshold is reached. The default number of concurrent rebalance
25- * operations is set to {@code 2}
23+ * re-balance (shard relocation) operations and restricts node allocations
24+ * if the configured threshold is reached. Frozen and non-frozen shards are
25+ * considered separately. The default number of concurrent rebalance operations
26+ * is set to {@code 2} for non-frozen shards. For frozen shards, the default is
27+ * the same setting as non-frozen shards, until set explicitly.
2628 * <p>
2729 * Re-balance operations can be controlled in real-time via the cluster update API using
28- * {@code cluster.routing.allocation.cluster_concurrent_rebalance}. Iff this
29- * setting is set to {@code -1} the number of concurrent re-balance operations
30- * are unlimited.
30+ * {@code cluster.routing.allocation.cluster_concurrent_rebalance} and
31+ * {@code cluster.routing.allocation.cluster_concurrent_frozen_rebalance}.
32+ * Iff either setting is set to {@code -1} the number of concurrent re-balance operations
33+ * within the setting's category (frozen or non-frozen) are unlimited.
3134 */
3235public class ConcurrentRebalanceAllocationDecider extends AllocationDecider {
3336
@@ -44,21 +47,91 @@ public class ConcurrentRebalanceAllocationDecider extends AllocationDecider {
4447 );
4548 private volatile int clusterConcurrentRebalance ;
4649
50+ /**
51+ * Same as cluster_concurrent_rebalance, but applies separately to frozen tier shards
52+ *
53+ * Defaults to the same value as normal concurrent rebalance, if unspecified
54+ */
55+ public static final Setting <Integer > CLUSTER_ROUTING_ALLOCATION_CLUSTER_CONCURRENT_FROZEN_REBALANCE_SETTING = Setting .intSetting (
56+ "cluster.routing.allocation.cluster_concurrent_frozen_rebalance" ,
57+ CLUSTER_ROUTING_ALLOCATION_CLUSTER_CONCURRENT_REBALANCE_SETTING ,
58+ -1 ,
59+ Property .Dynamic ,
60+ Property .NodeScope
61+ );
62+ private volatile int clusterConcurrentFrozenRebalance ;
63+
4764 public ConcurrentRebalanceAllocationDecider (ClusterSettings clusterSettings ) {
4865 clusterSettings .initializeAndWatch (
4966 CLUSTER_ROUTING_ALLOCATION_CLUSTER_CONCURRENT_REBALANCE_SETTING ,
5067 this ::setClusterConcurrentRebalance
5168 );
52- logger .debug ("using [cluster_concurrent_rebalance] with [{}]" , clusterConcurrentRebalance );
69+ clusterSettings .initializeAndWatch (
70+ CLUSTER_ROUTING_ALLOCATION_CLUSTER_CONCURRENT_FROZEN_REBALANCE_SETTING ,
71+ this ::setClusterConcurrentFrozenRebalance
72+ );
73+ logger .debug (
74+ "using [cluster_concurrent_rebalance] with [concurrent_rebalance={}, concurrent_frozen_rebalance={}]" ,
75+ clusterConcurrentRebalance ,
76+ clusterConcurrentFrozenRebalance
77+ );
5378 }
5479
5580 private void setClusterConcurrentRebalance (int concurrentRebalance ) {
5681 clusterConcurrentRebalance = concurrentRebalance ;
5782 }
5883
84+ private void setClusterConcurrentFrozenRebalance (int concurrentFrozenRebalance ) {
85+ clusterConcurrentFrozenRebalance = concurrentFrozenRebalance ;
86+ }
87+
5988 @ Override
6089 public Decision canRebalance (ShardRouting shardRouting , RoutingAllocation allocation ) {
61- return canRebalance (allocation );
90+ int relocatingFrozenShards = allocation .routingNodes ().getRelocatingFrozenShardCount ();
91+ if (allocation .routingNodes ().isDedicatedFrozenNode (shardRouting .currentNodeId ())) {
92+ if (clusterConcurrentFrozenRebalance == -1 ) {
93+ return allocation .decision (Decision .YES , NAME , "unlimited concurrent frozen rebalances are allowed" );
94+ }
95+ if (relocatingFrozenShards >= clusterConcurrentFrozenRebalance ) {
96+ return allocation .decision (
97+ Decision .THROTTLE ,
98+ NAME ,
99+ "reached the limit of concurrently rebalancing frozen shards [%d], cluster setting [%s=%d]" ,
100+ relocatingFrozenShards ,
101+ CLUSTER_ROUTING_ALLOCATION_CLUSTER_CONCURRENT_FROZEN_REBALANCE_SETTING .getKey (),
102+ clusterConcurrentFrozenRebalance
103+ );
104+ }
105+ return allocation .decision (
106+ Decision .YES ,
107+ NAME ,
108+ "below threshold [%d] for concurrent frozen rebalances, current frozen rebalance shard count [%d]" ,
109+ clusterConcurrentFrozenRebalance ,
110+ relocatingFrozenShards
111+ );
112+ } else {
113+ int relocatingShards = allocation .routingNodes ().getRelocatingShardCount () - relocatingFrozenShards ;
114+ if (clusterConcurrentRebalance == -1 ) {
115+ return allocation .decision (Decision .YES , NAME , "unlimited concurrent rebalances are allowed" );
116+ }
117+ if (relocatingShards >= clusterConcurrentRebalance ) {
118+ return allocation .decision (
119+ Decision .THROTTLE ,
120+ NAME ,
121+ "reached the limit of concurrently rebalancing shards [%d], cluster setting [%s=%d]" ,
122+ relocatingShards ,
123+ CLUSTER_ROUTING_ALLOCATION_CLUSTER_CONCURRENT_REBALANCE_SETTING .getKey (),
124+ clusterConcurrentRebalance
125+ );
126+ }
127+ return allocation .decision (
128+ Decision .YES ,
129+ NAME ,
130+ "below threshold [%d] for concurrent rebalances, current rebalance shard count [%d]" ,
131+ clusterConcurrentRebalance ,
132+ relocatingShards
133+ );
134+ }
62135 }
63136
64137 /**
@@ -68,33 +141,52 @@ public Decision canRebalance(ShardRouting shardRouting, RoutingAllocation alloca
68141 */
69142 @ Override
70143 public Decision canRebalance (RoutingAllocation allocation ) {
144+ int relocatingFrozenShards = allocation .routingNodes ().getRelocatingFrozenShardCount ();
71145 int relocatingShards = allocation .routingNodes ().getRelocatingShardCount ();
72146 if (allocation .isSimulating () && relocatingShards >= 2 ) {
73147 // BalancedShardAllocator is prone to perform unnecessary moves when cluster_concurrent_rebalance is set to high values (>2).
74148 // (See https://github.com/elastic/elasticsearch/issues/87279)
75149 // Above allocator is used in DesiredBalanceComputer. Since we do not move actual shard data during calculation
76150 // it is possible to artificially set above setting to 2 to avoid unnecessary moves in desired balance.
151+ // Separately: keep overall limit in simulation to two including frozen shards
77152 return allocation .decision (Decision .THROTTLE , NAME , "allocation should move one shard at the time when simulating" );
78153 }
79- if (clusterConcurrentRebalance == -1 ) {
80- return allocation .decision (Decision .YES , NAME , "unlimited concurrent rebalances are allowed" );
81- }
82- if (relocatingShards >= clusterConcurrentRebalance ) {
154+
155+ // separate into frozen/non-frozen counts
156+ relocatingShards = relocatingShards - relocatingFrozenShards ;
157+
158+ // either frozen or non-frozen having some allowance before their limit means the allocator has room to rebalance
159+ if (clusterConcurrentRebalance == -1 || relocatingShards < clusterConcurrentRebalance ) {
83160 return allocation .decision (
84- Decision .THROTTLE ,
161+ Decision .YES ,
85162 NAME ,
86- "reached the limit of concurrently rebalancing shards [%d], cluster setting [%s=%d]" ,
87- relocatingShards ,
163+ "below threshold [%s=%d] for concurrent rebalances, current rebalance shard count [%d]" ,
88164 CLUSTER_ROUTING_ALLOCATION_CLUSTER_CONCURRENT_REBALANCE_SETTING .getKey (),
89- clusterConcurrentRebalance
165+ clusterConcurrentRebalance ,
166+ relocatingShards
167+ );
168+ }
169+ if (clusterConcurrentFrozenRebalance == -1 || relocatingFrozenShards < clusterConcurrentFrozenRebalance ) {
170+ return allocation .decision (
171+ Decision .YES ,
172+ NAME ,
173+ "below threshold [%s=%d] for concurrent frozen rebalances, current frozen rebalance shard count [%d]" ,
174+ CLUSTER_ROUTING_ALLOCATION_CLUSTER_CONCURRENT_FROZEN_REBALANCE_SETTING .getKey (),
175+ clusterConcurrentFrozenRebalance ,
176+ relocatingFrozenShards
90177 );
91178 }
92179 return allocation .decision (
93- Decision .YES ,
180+ Decision .THROTTLE ,
94181 NAME ,
95- "below threshold [%d] for concurrent rebalances, current rebalance shard count [%d]" ,
182+ "reached the limit of concurrently rebalancing shards [%d] for concurrent rebalances, cluster setting [%s=%d], "
183+ + "and [%d] for concurrent frozen rebalances, frozen cluster setting [%s=%d]" ,
184+ relocatingShards ,
185+ CLUSTER_ROUTING_ALLOCATION_CLUSTER_CONCURRENT_REBALANCE_SETTING .getKey (),
96186 clusterConcurrentRebalance ,
97- relocatingShards
187+ relocatingFrozenShards ,
188+ CLUSTER_ROUTING_ALLOCATION_CLUSTER_CONCURRENT_FROZEN_REBALANCE_SETTING .getKey (),
189+ clusterConcurrentFrozenRebalance
98190 );
99191 }
100192}
0 commit comments