Skip to content

Commit faa6415

Browse files
jiajunwangjiajunwang
authored andcommitted
Adjust the replica rebalance calculating ordering to avoid static order. (apache#535)
* Adjust the replica rebalance calculating ordering to avoid static order. The problem of a static order is that the same set of replicas will always be the ones that are moved or state transited during the rebalance. This randomize won't change the algorithm's performance. But it will help the Helix to eliminate very unstable partitions.
1 parent 39b84fb commit faa6415

1 file changed

Lines changed: 17 additions & 5 deletions

File tree

helix-core/src/main/java/org/apache/helix/controller/rebalancer/waged/constraints/ConstraintBasedAlgorithm.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.HashMap;
2525
import java.util.List;
2626
import java.util.Map;
27+
import java.util.Objects;
2728
import java.util.Optional;
2829
import java.util.Set;
2930
import java.util.function.Function;
@@ -134,7 +135,6 @@ private List<String> convertFailureReasons(List<HardConstraint> hardConstraints)
134135
.collect(Collectors.toList());
135136
}
136137

137-
// TODO investigate better ways to sort replicas. One option is sorting based on the creation time.
138138
private List<AssignableReplica> getOrderedAssignableReplica(ClusterModel clusterModel) {
139139
Map<String, Set<AssignableReplica>> replicasByResource = clusterModel.getAssignableReplicaMap();
140140
List<AssignableReplica> orderedAssignableReplicas =
@@ -162,11 +162,23 @@ private List<AssignableReplica> getOrderedAssignableReplica(ClusterModel cluster
162162
int statePriority1 = replica1.getStatePriority();
163163
int statePriority2 = replica2.getStatePriority();
164164
if (statePriority1 == statePriority2) {
165-
// If state prioritizes are the same, compare the names.
166-
if (resourceName1.equals(resourceName2)) {
167-
return replica1.getPartitionName().compareTo(replica2.getPartitionName());
165+
// If state priorities are the same, try to randomize the replicas order. Otherwise,
166+
// the same replicas might always be moved in each rebalancing. This is because their
167+
// placement calculating will always happen at the critical moment while the cluster is
168+
// almost close to the expected utilization.
169+
//
170+
// Note that to ensure the algorithm is deterministic with the same inputs, do not use
171+
// Random functions here. Use hashcode based on the cluster topology information to get
172+
// a controlled randomized order is good enough.
173+
Long replicaHash1 = (long) Objects
174+
.hash(replica1.toString(), clusterModel.getAssignableNodes().keySet());
175+
Long replicaHash2 = (long) Objects
176+
.hash(replica2.toString(), clusterModel.getAssignableNodes().keySet());
177+
if (!replicaHash1.equals(replicaHash2)) {
178+
return replicaHash1.compareTo(replicaHash2);
168179
} else {
169-
return resourceName1.compareTo(resourceName2);
180+
// In case of hash collision, return order according to the name.
181+
return replica1.toString().compareTo(replica2.toString());
170182
}
171183
} else {
172184
// Note we shall prioritize the replica with a higher state priority,

0 commit comments

Comments
 (0)