Use existing datastructures from RoutingNodes to elect unassigned primaries
Currently we trying to find a replica for a primary that is allocated by running through all shards in the cluster while RoutingNodes already has a datastructure keyed by shard ID for this. We should lookup this directly rather than using linear probing. This improves shard allocation performance by 5x.
This commit is contained in:
parent
62104a10ef
commit
314499cee0
|
@ -23,6 +23,7 @@ import com.carrotsearch.hppc.ObjectIntOpenHashMap;
|
|||
import com.carrotsearch.hppc.cursors.ObjectCursor;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
|
@ -97,7 +98,7 @@ public class RoutingNodes implements Iterable<RoutingNode> {
|
|||
}
|
||||
MutableShardRouting sr = new MutableShardRouting(shard);
|
||||
entries.add(sr);
|
||||
activeShardsAdd(sr);
|
||||
assignedShardsAdd(sr);
|
||||
if (shard.relocating()) {
|
||||
entries = nodesToShards.get(shard.relocatingNodeId());
|
||||
relocatingShards++;
|
||||
|
@ -110,7 +111,7 @@ public class RoutingNodes implements Iterable<RoutingNode> {
|
|||
sr = new MutableShardRouting(shard.index(), shard.id(), shard.relocatingNodeId(),
|
||||
shard.currentNodeId(), shard.primary(), ShardRoutingState.INITIALIZING, shard.version());
|
||||
entries.add(sr);
|
||||
activeShardsAdd(sr);
|
||||
assignedShardsAdd(sr);
|
||||
} else if (!shard.active()) { // shards that are initializing without being relocated
|
||||
if (shard.primary()) {
|
||||
inactivePrimaryCount++;
|
||||
|
@ -119,7 +120,7 @@ public class RoutingNodes implements Iterable<RoutingNode> {
|
|||
}
|
||||
} else {
|
||||
MutableShardRouting sr = new MutableShardRouting(shard);
|
||||
activeShardsAdd(sr);
|
||||
assignedShardsAdd(sr);
|
||||
unassignedShards.add(sr);
|
||||
}
|
||||
}
|
||||
|
@ -251,22 +252,40 @@ public class RoutingNodes implements Iterable<RoutingNode> {
|
|||
*/
|
||||
public MutableShardRouting activePrimary(ShardRouting shard) {
|
||||
assert !shard.primary();
|
||||
for (MutableShardRouting shardRouting : activeShards(shard.shardId())) {
|
||||
if (shardRouting.primary()) {
|
||||
if (shardRouting.active()) {
|
||||
for (MutableShardRouting shardRouting : assignedShards(shard.shardId())) {
|
||||
if (shardRouting.primary() && shardRouting.active()) {
|
||||
return shardRouting;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns one active replica shard for the given ShardRouting shard ID or <code>null</code> if
|
||||
* no active replica is found.
|
||||
*/
|
||||
public MutableShardRouting activeReplica(ShardRouting shard) {
|
||||
for (MutableShardRouting shardRouting : assignedShards(shard.shardId())) {
|
||||
if (!shardRouting.primary() && shardRouting.active()) {
|
||||
return shardRouting;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all shards that are not in the state UNASSIGNED with the same shard
|
||||
* ID as the given shard.
|
||||
*/
|
||||
public Iterable<MutableShardRouting> assignedShards(ShardRouting shard) {
|
||||
return Iterables.unmodifiableIterable(assignedShards(shard.shardId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> iff all replicas are active for the given shard routing. Otherwise <code>false</code>
|
||||
*/
|
||||
public boolean allReplicasActive(ShardRouting shardRouting) {
|
||||
final Set<MutableShardRouting> shards = activeShards(shardRouting.shardId());
|
||||
final Set<MutableShardRouting> shards = assignedShards(shardRouting.shardId());
|
||||
if (shards.isEmpty() || shards.size() < this.routingTable.index(shardRouting.index()).shard(shardRouting.id()).size()) {
|
||||
return false; // if we are empty nothing is active if we have less than total at least one is unassigned
|
||||
}
|
||||
|
@ -352,7 +371,7 @@ public class RoutingNodes implements Iterable<RoutingNode> {
|
|||
if (shard.state() == ShardRoutingState.RELOCATING) {
|
||||
relocatingShards++;
|
||||
}
|
||||
activeShardsAdd(shard);
|
||||
assignedShardsAdd(shard);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -410,7 +429,7 @@ public class RoutingNodes implements Iterable<RoutingNode> {
|
|||
|
||||
private static final Set<MutableShardRouting> EMPTY = Collections.emptySet();
|
||||
|
||||
private Set<MutableShardRouting> activeShards(ShardId shardId) {
|
||||
private Set<MutableShardRouting> assignedShards(ShardId shardId) {
|
||||
final Set<MutableShardRouting> replicaSet = assignedShards.get(shardId);
|
||||
return replicaSet == null ? EMPTY : Collections.unmodifiableSet(replicaSet);
|
||||
}
|
||||
|
@ -430,10 +449,10 @@ public class RoutingNodes implements Iterable<RoutingNode> {
|
|||
} else if (shard.relocating()) {
|
||||
cancelRelocation(shard);
|
||||
}
|
||||
activeShardsRemove(shard);
|
||||
assignedShardsRemove(shard);
|
||||
}
|
||||
|
||||
private void activeShardsAdd(MutableShardRouting shard) {
|
||||
private void assignedShardsAdd(MutableShardRouting shard) {
|
||||
if (shard.unassigned()) {
|
||||
// no unassigned
|
||||
return;
|
||||
|
@ -446,7 +465,7 @@ public class RoutingNodes implements Iterable<RoutingNode> {
|
|||
replicaSet.add(shard);
|
||||
}
|
||||
|
||||
private void activeShardsRemove(MutableShardRouting shard) {
|
||||
private void assignedShardsRemove(MutableShardRouting shard) {
|
||||
Set<MutableShardRouting> replicaSet = assignedShards.get(shard.shardId());
|
||||
if (replicaSet != null) {
|
||||
if (replicaSet.contains(shard)) {
|
||||
|
@ -488,6 +507,7 @@ public class RoutingNodes implements Iterable<RoutingNode> {
|
|||
public final static class UnassignedShards implements Iterable<MutableShardRouting> {
|
||||
|
||||
private final List<MutableShardRouting> unassigned;
|
||||
|
||||
private int primaries = 0;
|
||||
private long transactionId = 0;
|
||||
private final UnassignedShards source;
|
||||
|
@ -581,10 +601,6 @@ public class RoutingNodes implements Iterable<RoutingNode> {
|
|||
return new UnassignedShards(this);
|
||||
}
|
||||
|
||||
public void copyAll(Collection<MutableShardRouting> others) {
|
||||
others.addAll(unassigned);
|
||||
}
|
||||
|
||||
public MutableShardRouting[] drain() {
|
||||
MutableShardRouting[] mutableShardRoutings = unassigned.toArray(new MutableShardRouting[unassigned.size()]);
|
||||
unassigned.clear();
|
||||
|
@ -649,7 +665,7 @@ public class RoutingNodes implements Iterable<RoutingNode> {
|
|||
}
|
||||
}
|
||||
}
|
||||
Set<MutableShardRouting> mutableShardRoutings = routingNodes.activeShards(new ShardId(index, i));
|
||||
Set<MutableShardRouting> mutableShardRoutings = routingNodes.assignedShards(new ShardId(index, i));
|
||||
for (MutableShardRouting r : mutableShardRoutings) {
|
||||
assert shards.contains(r);
|
||||
shards.remove(r);
|
||||
|
|
|
@ -246,58 +246,44 @@ public class AllocationService extends AbstractComponent {
|
|||
private boolean electPrimariesAndUnassignDanglingReplicas(RoutingAllocation allocation) {
|
||||
boolean changed = false;
|
||||
RoutingNodes routingNodes = allocation.routingNodes();
|
||||
if (!routingNodes.hasUnassignedPrimaries()) {
|
||||
// move out if we don't have unassigned primaries
|
||||
return changed;
|
||||
}
|
||||
for (MutableShardRouting shardEntry : routingNodes.unassigned()) {
|
||||
if (shardEntry.primary() && !shardEntry.assignedToNode()) {
|
||||
boolean elected = false;
|
||||
// primary and not assigned, go over and find a replica that is assigned and active (since it might be relocating)
|
||||
for (RoutingNode routingNode : routingNodes) {
|
||||
|
||||
for (MutableShardRouting shardEntry2 : routingNode) {
|
||||
if (shardEntry.shardId().equals(shardEntry2.shardId()) && shardEntry2.active()) {
|
||||
assert shardEntry2.assignedToNode();
|
||||
assert !shardEntry2.primary();
|
||||
|
||||
if (shardEntry.primary()) {
|
||||
MutableShardRouting candidate = allocation.routingNodes().activeReplica(shardEntry);
|
||||
if (candidate != null) {
|
||||
routingNodes.swapPrimaryFlag(shardEntry, candidate);
|
||||
if (candidate.relocatingNodeId() != null) {
|
||||
changed = true;
|
||||
routingNodes.swapPrimaryFlag(shardEntry, shardEntry2);
|
||||
|
||||
if (shardEntry2.relocatingNodeId() != null) {
|
||||
// its also relocating, make sure to move the other routing to primary
|
||||
RoutingNode node = routingNodes.node(shardEntry2.relocatingNodeId());
|
||||
RoutingNode node = routingNodes.node(candidate.relocatingNodeId());
|
||||
if (node != null) {
|
||||
for (MutableShardRouting shardRouting : node) {
|
||||
if (shardRouting.shardId().equals(shardEntry2.shardId()) && !shardRouting.primary()) {
|
||||
if (shardRouting.shardId().equals(candidate.shardId()) && !shardRouting.primary()) {
|
||||
routingNodes.swapPrimaryFlag(shardRouting);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
elected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (elected) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// go over and remove dangling replicas that are initializing, but we couldn't elect primary ones...
|
||||
List<ShardRouting> shardsToFail = null;
|
||||
if (routingNodes.hasUnassignedPrimaries()) {
|
||||
for (MutableShardRouting shardEntry : routingNodes.unassigned()) {
|
||||
if (shardEntry.primary() && !shardEntry.assignedToNode()) {
|
||||
for (RoutingNode routingNode : routingNodes) {
|
||||
for (MutableShardRouting shardEntry2 : routingNode) {
|
||||
if (shardEntry.shardId().equals(shardEntry2.shardId()) && !shardEntry2.active()) {
|
||||
if (shardEntry.primary()) {
|
||||
for(MutableShardRouting routing : routingNodes.assignedShards(shardEntry)) {
|
||||
if (!routing.primary()) {
|
||||
changed = true;
|
||||
if (shardsToFail == null) {
|
||||
shardsToFail = new ArrayList<ShardRouting>();
|
||||
}
|
||||
shardsToFail.add(shardEntry2);
|
||||
}
|
||||
shardsToFail.add(routing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -307,6 +293,7 @@ public class AllocationService extends AbstractComponent {
|
|||
applyFailedShard(allocation, shardToFail, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue