Search in sources :

Example 11 with Replica

use of org.apache.cassandra.locator.Replica in project cassandra by apache.

the class RangeStreamer method convertPreferredEndpointsToWorkMap.

/**
 * The preferred endpoint list is the wrong format because it is keyed by Replica (this node) rather than the source
 * endpoint we will fetch from which streaming wants.
 */
public static Multimap<InetAddressAndPort, FetchReplica> convertPreferredEndpointsToWorkMap(EndpointsByReplica preferredEndpoints) {
    Multimap<InetAddressAndPort, FetchReplica> workMap = HashMultimap.create();
    for (Map.Entry<Replica, EndpointsForRange> e : preferredEndpoints.entrySet()) {
        for (Replica source : e.getValue()) {
            assert (e.getKey()).isSelf();
            assert !source.isSelf();
            workMap.put(source.endpoint(), new FetchReplica(e.getKey(), source));
        }
    }
    logger.debug("Work map {}", workMap);
    return workMap;
}
Also used : InetAddressAndPort(org.apache.cassandra.locator.InetAddressAndPort) EndpointsForRange(org.apache.cassandra.locator.EndpointsForRange) Map(java.util.Map) HashMap(java.util.HashMap) Replica.fullReplica(org.apache.cassandra.locator.Replica.fullReplica) Replica(org.apache.cassandra.locator.Replica) EndpointsByReplica(org.apache.cassandra.locator.EndpointsByReplica)

Example 12 with Replica

use of org.apache.cassandra.locator.Replica in project cassandra by apache.

the class RangeStreamer method calculateRangesToFetchWithPreferredEndpoints.

/**
 * Get a map of all ranges and the source that will be cleaned up once this bootstrapped node is added for the given ranges.
 * For each range, the list should only contain a single source. This allows us to consistently migrate data without violating
 * consistency.
 */
public static EndpointsByReplica calculateRangesToFetchWithPreferredEndpoints(BiFunction<InetAddressAndPort, EndpointsForRange, EndpointsForRange> snitchGetSortedListByProximity, AbstractReplicationStrategy strat, ReplicaCollection<?> fetchRanges, boolean useStrictConsistency, TokenMetadata tmdBefore, TokenMetadata tmdAfter, String keyspace, Collection<SourceFilter> sourceFilters) {
    EndpointsByRange rangeAddresses = strat.getRangeAddresses(tmdBefore);
    InetAddressAndPort localAddress = FBUtilities.getBroadcastAddressAndPort();
    logger.debug("Keyspace: {}", keyspace);
    logger.debug("To fetch RN: {}", fetchRanges);
    logger.debug("Fetch ranges: {}", rangeAddresses);
    Predicate<Replica> testSourceFilters = and(sourceFilters);
    Function<EndpointsForRange, EndpointsForRange> sorted = endpoints -> snitchGetSortedListByProximity.apply(localAddress, endpoints);
    // This list of replicas is just candidates. With strict consistency it's going to be a narrow list.
    EndpointsByReplica.Builder rangesToFetchWithPreferredEndpoints = new EndpointsByReplica.Builder();
    for (Replica toFetch : fetchRanges) {
        // Replica that is sufficient to provide the data we need
        // With strict consistency and transient replication we may end up with multiple types
        // so this isn't used with strict consistency
        Predicate<Replica> isSufficient = r -> toFetch.isTransient() || r.isFull();
        logger.debug("To fetch {}", toFetch);
        for (Range<Token> range : rangeAddresses.keySet()) {
            if (!range.contains(toFetch.range()))
                continue;
            final EndpointsForRange oldEndpoints = sorted.apply(rangeAddresses.get(range));
            // Ultimately we populate this with whatever is going to be fetched from to satisfy toFetch
            // It could be multiple endpoints and we must fetch from all of them if they are there
            // With transient replication and strict consistency this is to get the full data from a full replica and
            // transient data from the transient replica losing data
            EndpointsForRange sources;
            // Due to CASSANDRA-5953 we can have a higher RF than we have endpoints.
            // So we need to be careful to only be strict when endpoints == RF
            boolean isStrictConsistencyApplicable = useStrictConsistency && (oldEndpoints.size() == strat.getReplicationFactor().allReplicas);
            if (isStrictConsistencyApplicable) {
                EndpointsForRange strictEndpoints;
                // Start with two sets of who replicates the range before and who replicates it after
                EndpointsForRange newEndpoints = strat.calculateNaturalReplicas(toFetch.range().right, tmdAfter);
                logger.debug("Old endpoints {}", oldEndpoints);
                logger.debug("New endpoints {}", newEndpoints);
                // Remove new endpoints from old endpoints based on address
                strictEndpoints = oldEndpoints.without(newEndpoints.endpoints());
                if (strictEndpoints.size() > 1)
                    throw new AssertionError("Expected <= 1 endpoint but found " + strictEndpoints);
                // required for strict consistency
                if (!all(strictEndpoints, testSourceFilters))
                    throw new IllegalStateException("Necessary replicas for strict consistency were removed by source filters: " + buildErrorMessage(sourceFilters, strictEndpoints));
                // So it's an error if we don't find what we need.
                if (strictEndpoints.isEmpty() && toFetch.isTransient())
                    throw new AssertionError("If there are no endpoints to fetch from then we must be transitioning from transient to full for range " + toFetch);
                if (!any(strictEndpoints, isSufficient)) {
                    // need an additional replica; include all our filters, to ensure we include a matching node
                    Optional<Replica> fullReplica = Iterables.<Replica>tryFind(oldEndpoints, and(isSufficient, testSourceFilters)).toJavaUtil();
                    if (fullReplica.isPresent())
                        strictEndpoints = Endpoints.concat(strictEndpoints, EndpointsForRange.of(fullReplica.get()));
                    else
                        throw new IllegalStateException("Couldn't find any matching sufficient replica out of " + buildErrorMessage(sourceFilters, oldEndpoints));
                }
                sources = strictEndpoints;
            } else {
                // Without strict consistency we have given up on correctness so no point in fetching from
                // a random full + transient replica since it's also likely to lose data
                // Also apply testSourceFilters that were given to us so we can safely select a single source
                sources = sorted.apply(oldEndpoints.filter(and(isSufficient, testSourceFilters)));
                // Limit it to just the first possible source, we don't need more than one and downstream
                // will fetch from every source we supply
                sources = sources.size() > 0 ? sources.subList(0, 1) : sources;
            }
            // storing range and preferred endpoint set
            rangesToFetchWithPreferredEndpoints.putAll(toFetch, sources, Conflict.NONE);
            logger.debug("Endpoints to fetch for {} are {}", toFetch, sources);
        }
        EndpointsForRange addressList = rangesToFetchWithPreferredEndpoints.getIfPresent(toFetch);
        if (addressList == null)
            throw new IllegalStateException("Failed to find endpoints to fetch " + toFetch);
        /*
              * When we move forwards (shrink our bucket) we are the one losing a range and no one else loses
              * from that action (we also don't gain). When we move backwards there are two people losing a range. One is a full replica
              * and the other is a transient replica. So we must need fetch from two places in that case for the full range we gain.
              * For a transient range we only need to fetch from one.
              */
        if (useStrictConsistency && addressList.size() > 1 && (addressList.filter(Replica::isFull).size() > 1 || addressList.filter(Replica::isTransient).size() > 1))
            throw new IllegalStateException(String.format("Multiple strict sources found for %s, sources: %s", toFetch, addressList));
        // We must have enough stuff to fetch from
        if (!any(addressList, isSufficient)) {
            if (strat.getReplicationFactor().allReplicas == 1) {
                if (useStrictConsistency) {
                    logger.warn("A node required to move the data consistently is down");
                    throw new IllegalStateException("Unable to find sufficient sources for streaming range " + toFetch + " in keyspace " + keyspace + " with RF=1. " + "Ensure this keyspace contains replicas in the source datacenter.");
                } else
                    logger.warn("Unable to find sufficient sources for streaming range {} in keyspace {} with RF=1. " + "Keyspace might be missing data.", toFetch, keyspace);
            } else {
                if (useStrictConsistency)
                    logger.warn("A node required to move the data consistently is down");
                throw new IllegalStateException("Unable to find sufficient sources for streaming range " + toFetch + " in keyspace " + keyspace);
            }
        }
    }
    return rangesToFetchWithPreferredEndpoints.build();
}
Also used : BiFunction(java.util.function.BiFunction) LoggerFactory(org.slf4j.LoggerFactory) Iterables.all(com.google.common.collect.Iterables.all) StringUtils(org.apache.commons.lang3.StringUtils) Gossiper(org.apache.cassandra.gms.Gossiper) NetworkTopologyStrategy(org.apache.cassandra.locator.NetworkTopologyStrategy) Predicates.and(com.google.common.base.Predicates.and) StreamResultFuture(org.apache.cassandra.streaming.StreamResultFuture) Replica.fullReplica(org.apache.cassandra.locator.Replica.fullReplica) HashMultimap(com.google.common.collect.HashMultimap) Replicas(org.apache.cassandra.locator.Replicas) Endpoints(org.apache.cassandra.locator.Endpoints) Predicates.not(com.google.common.base.Predicates.not) ReplicaCollection(org.apache.cassandra.locator.ReplicaCollection) Map(java.util.Map) EndpointsByRange(org.apache.cassandra.locator.EndpointsByRange) Keyspace(org.apache.cassandra.db.Keyspace) EndpointsForRange(org.apache.cassandra.locator.EndpointsForRange) FBUtilities(org.apache.cassandra.utils.FBUtilities) Collection(java.util.Collection) Set(java.util.Set) Collectors(java.util.stream.Collectors) RangesAtEndpoint(org.apache.cassandra.locator.RangesAtEndpoint) List(java.util.List) Predicate(com.google.common.base.Predicate) Conflict(org.apache.cassandra.locator.ReplicaCollection.Builder.Conflict) Optional(java.util.Optional) FailureDetector(org.apache.cassandra.gms.FailureDetector) Iterables.any(com.google.common.collect.Iterables.any) InetAddressAndPort(org.apache.cassandra.locator.InetAddressAndPort) Iterables(com.google.common.collect.Iterables) HashMap(java.util.HashMap) Multimap(com.google.common.collect.Multimap) Function(java.util.function.Function) SystemKeyspace(org.apache.cassandra.db.SystemKeyspace) ArrayList(java.util.ArrayList) IEndpointSnitch(org.apache.cassandra.locator.IEndpointSnitch) TokenMetadata(org.apache.cassandra.locator.TokenMetadata) ImmutableMultimap(com.google.common.collect.ImmutableMultimap) StreamOperation(org.apache.cassandra.streaming.StreamOperation) Logger(org.slf4j.Logger) Replica(org.apache.cassandra.locator.Replica) IFailureDetector(org.apache.cassandra.gms.IFailureDetector) PreviewKind(org.apache.cassandra.streaming.PreviewKind) AbstractReplicationStrategy(org.apache.cassandra.locator.AbstractReplicationStrategy) StreamPlan(org.apache.cassandra.streaming.StreamPlan) EndpointsByReplica(org.apache.cassandra.locator.EndpointsByReplica) Preconditions(com.google.common.base.Preconditions) VisibleForTesting(com.google.common.annotations.VisibleForTesting) LocalStrategy(org.apache.cassandra.locator.LocalStrategy) InetAddressAndPort(org.apache.cassandra.locator.InetAddressAndPort) EndpointsByRange(org.apache.cassandra.locator.EndpointsByRange) Replica.fullReplica(org.apache.cassandra.locator.Replica.fullReplica) Replica(org.apache.cassandra.locator.Replica) EndpointsByReplica(org.apache.cassandra.locator.EndpointsByReplica) EndpointsByReplica(org.apache.cassandra.locator.EndpointsByReplica) EndpointsForRange(org.apache.cassandra.locator.EndpointsForRange)

Example 13 with Replica

use of org.apache.cassandra.locator.Replica in project cassandra by apache.

the class RangeFetchMapCalculator method getRangeFetchMapForTrivialRanges.

@VisibleForTesting
Multimap<InetAddressAndPort, Range<Token>> getRangeFetchMapForTrivialRanges(Multimap<InetAddressAndPort, Range<Token>> optimisedMap) {
    Multimap<InetAddressAndPort, Range<Token>> fetchMap = HashMultimap.create();
    for (Range<Token> trivialRange : trivialRanges) {
        boolean added = false;
        boolean localDCCheck = true;
        while (!added) {
            // sort with the endpoint having the least number of streams first:
            EndpointsForRange replicas = rangesWithSources.get(trivialRange).sorted(Comparator.comparingInt(o -> optimisedMap.get(o.endpoint()).size()));
            Replicas.temporaryAssertFull(replicas);
            for (Replica replica : replicas) {
                if (passFilters(replica, localDCCheck)) {
                    added = true;
                    // see RangeFetchMapCalculator#addEndpoints  and RangeStreamer#getRangeFetchMap
                    if (replica.isSelf())
                        // but don't add localhost to avoid streaming locally
                        continue;
                    fetchMap.put(replica.endpoint(), trivialRange);
                    break;
                }
            }
            if (!added && !localDCCheck)
                throw new IllegalStateException("Unable to find sufficient sources for streaming range " + trivialRange + " in keyspace " + keyspace);
            if (!added)
                logger.info("Using other DC endpoints for streaming for range: {} and keyspace {}", trivialRange, keyspace);
            localDCCheck = false;
        }
    }
    return fetchMap;
}
Also used : InetAddressAndPort(org.apache.cassandra.locator.InetAddressAndPort) MaximumFlowAlgorithmResult(org.psjava.algo.graph.flownetwork.MaximumFlowAlgorithmResult) LoggerFactory(org.slf4j.LoggerFactory) CapacityEdge(org.psjava.ds.graph.CapacityEdge) Multimap(com.google.common.collect.Multimap) Function(org.psjava.ds.math.Function) HashMultimap(com.google.common.collect.HashMultimap) Replicas(org.apache.cassandra.locator.Replicas) Predicates(com.google.common.base.Predicates) BigInteger(java.math.BigInteger) MaximumFlowAlgorithm(org.psjava.algo.graph.flownetwork.MaximumFlowAlgorithm) EndpointsByRange(org.apache.cassandra.locator.EndpointsByRange) DatabaseDescriptor(org.apache.cassandra.config.DatabaseDescriptor) EndpointsForRange(org.apache.cassandra.locator.EndpointsForRange) Logger(org.slf4j.Logger) DFSPathFinder(org.psjava.algo.graph.pathfinder.DFSPathFinder) Collection(java.util.Collection) Set(java.util.Set) IntegerNumberSystem(org.psjava.ds.numbersystrem.IntegerNumberSystem) Collectors(java.util.stream.Collectors) Replica(org.apache.cassandra.locator.Replica) Predicate(com.google.common.base.Predicate) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Comparator(java.util.Comparator) MutableCapacityGraph(org.psjava.ds.graph.MutableCapacityGraph) FordFulkersonAlgorithm(org.psjava.algo.graph.flownetwork.FordFulkersonAlgorithm) InetAddressAndPort(org.apache.cassandra.locator.InetAddressAndPort) EndpointsForRange(org.apache.cassandra.locator.EndpointsForRange) EndpointsByRange(org.apache.cassandra.locator.EndpointsByRange) EndpointsForRange(org.apache.cassandra.locator.EndpointsForRange) Replica(org.apache.cassandra.locator.Replica) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 14 with Replica

use of org.apache.cassandra.locator.Replica in project cassandra by apache.

the class ReadCommandVerbHandler method validateTransientStatus.

private void validateTransientStatus(Message<ReadCommand> message) {
    ReadCommand command = message.payload;
    if (command.metadata().isVirtual())
        return;
    Token token;
    if (command instanceof SinglePartitionReadCommand)
        token = ((SinglePartitionReadCommand) command).partitionKey().getToken();
    else
        token = ((PartitionRangeReadCommand) command).dataRange().keyRange().right.getToken();
    Replica replica = Keyspace.open(command.metadata().keyspace).getReplicationStrategy().getLocalReplicaFor(token);
    if (replica == null) {
        logger.warn("Received a read request from {} for a range that is not owned by the current replica {}.", message.from(), command);
        return;
    }
    if (!command.acceptsTransient() && replica.isTransient()) {
        MessagingService.instance().metrics.recordDroppedMessage(message, message.elapsedSinceCreated(NANOSECONDS), NANOSECONDS);
        throw new InvalidRequestException(String.format("Attempted to serve %s data request from %s node in %s", command.acceptsTransient() ? "transient" : "full", replica.isTransient() ? "transient" : "full", this));
    }
}
Also used : Token(org.apache.cassandra.dht.Token) InvalidRequestException(org.apache.cassandra.exceptions.InvalidRequestException) Replica(org.apache.cassandra.locator.Replica)

Example 15 with Replica

use of org.apache.cassandra.locator.Replica in project cassandra by apache.

the class PendingRangesBench method setUp.

@Setup
public void setUp() throws UnknownHostException {
    pendingRangeMaps = new PendingRangeMaps();
    oldPendingRanges = HashMultimap.create();
    List<InetAddressAndPort> endpoints = Lists.newArrayList(InetAddressAndPort.getByName("127.0.0.1"), InetAddressAndPort.getByName("127.0.0.2"));
    for (int i = 0; i < maxToken; i++) {
        for (int j = 0; j < ThreadLocalRandom.current().nextInt(2); j++) {
            Range<Token> range = genRange(Integer.toString(i * 10 + 5), Integer.toString(i * 10 + 15));
            Replica replica = Replica.fullReplica(endpoints.get(j), range);
            pendingRangeMaps.addPendingRange(range, replica);
            oldPendingRanges.put(range, replica);
        }
    }
    // add the wrap around range
    for (int j = 0; j < ThreadLocalRandom.current().nextInt(2); j++) {
        Range<Token> range = genRange(Integer.toString(maxToken * 10 + 5), Integer.toString(5));
        Replica replica = Replica.fullReplica(endpoints.get(j), range);
        pendingRangeMaps.addPendingRange(range, replica);
        oldPendingRanges.put(range, replica);
    }
}
Also used : InetAddressAndPort(org.apache.cassandra.locator.InetAddressAndPort) Token(org.apache.cassandra.dht.Token) PendingRangeMaps(org.apache.cassandra.locator.PendingRangeMaps) Replica(org.apache.cassandra.locator.Replica)

Aggregations

Replica (org.apache.cassandra.locator.Replica)69 InetAddressAndPort (org.apache.cassandra.locator.InetAddressAndPort)24 Token (org.apache.cassandra.dht.Token)22 Test (org.junit.Test)20 HashMap (java.util.HashMap)18 Mutation (org.apache.cassandra.db.Mutation)15 EndpointsByReplica (org.apache.cassandra.locator.EndpointsByReplica)15 Range (org.apache.cassandra.dht.Range)14 RangesAtEndpoint (org.apache.cassandra.locator.RangesAtEndpoint)13 TokenMetadata (org.apache.cassandra.locator.TokenMetadata)12 Keyspace (org.apache.cassandra.db.Keyspace)11 AbstractReplicationStrategy (org.apache.cassandra.locator.AbstractReplicationStrategy)11 EndpointsForRange (org.apache.cassandra.locator.EndpointsForRange)11 Replica.fullReplica (org.apache.cassandra.locator.Replica.fullReplica)10 Collection (java.util.Collection)8 Map (java.util.Map)8 EndpointsForToken (org.apache.cassandra.locator.EndpointsForToken)8 ReplicaPlan (org.apache.cassandra.locator.ReplicaPlan)8 ArrayList (java.util.ArrayList)7 HashSet (java.util.HashSet)6