Search in sources :

Example 1 with PeerId

use of io.dingodb.raft.entity.PeerId in project dingo by dingodb.

the class NodeImpl method addLearners.

@Override
public void addLearners(final List<PeerId> learners, final Closure done) {
    checkPeers(learners);
    this.writeLock.lock();
    try {
        final Configuration newConf = new Configuration(this.conf.getConf());
        for (final PeerId peer : learners) {
            newConf.addLearner(peer);
        }
        unsafeRegisterConfChange(this.conf.getConf(), newConf, done);
    } finally {
        this.writeLock.unlock();
    }
}
Also used : Configuration(io.dingodb.raft.conf.Configuration) PeerId(io.dingodb.raft.entity.PeerId)

Example 2 with PeerId

use of io.dingodb.raft.entity.PeerId in project dingo by dingodb.

the class NodeImpl method checkDeadNodes.

private boolean checkDeadNodes(final Configuration conf, final long monotonicNowMs, final boolean stepDownOnCheckFail) {
    // Check learner replicators at first.
    for (final PeerId peer : conf.getLearners()) {
        checkReplicator(peer);
    }
    // Ensure quorum nodes alive.
    final List<PeerId> peers = conf.listPeers();
    final Configuration deadNodes = new Configuration();
    if (checkDeadNodes0(peers, monotonicNowMs, true, deadNodes)) {
        return true;
    }
    if (stepDownOnCheckFail) {
        LOG.warn("Node {} steps down when alive nodes don't satisfy quorum, term={}, deadNodes={}, conf={}.", getNodeId(), this.currTerm, deadNodes, conf);
        final Status status = new Status();
        status.setError(RaftError.ERAFTTIMEDOUT, "Majority of the group dies: %d/%d", deadNodes.size(), peers.size());
        stepDown(this.currTerm, false, status);
    }
    return false;
}
Also used : Status(io.dingodb.raft.Status) Configuration(io.dingodb.raft.conf.Configuration) PeerId(io.dingodb.raft.entity.PeerId)

Example 3 with PeerId

use of io.dingodb.raft.entity.PeerId in project dingo by dingodb.

the class NodeImpl method handleRequestVoteRequest.

@Override
public Message handleRequestVoteRequest(final RpcRequests.RequestVoteRequest request) {
    boolean doUnlock = true;
    this.writeLock.lock();
    try {
        if (!this.state.isActive()) {
            LOG.warn("Node {} is not in active state, currTerm={}.", getNodeId(), this.currTerm);
            return // 
            RpcFactoryHelper.responseFactory().newResponse(RpcRequests.RequestVoteResponse.getDefaultInstance(), RaftError.EINVAL, "Node %s is not in active state, state %s.", getNodeId(), this.state.name());
        }
        final PeerId candidateId = new PeerId();
        if (!candidateId.parse(request.getServerId())) {
            LOG.warn("Node {} received RequestVoteRequest from {} serverId bad format.", getNodeId(), request.getServerId());
            return // 
            RpcFactoryHelper.responseFactory().newResponse(RpcRequests.RequestVoteResponse.getDefaultInstance(), RaftError.EINVAL, "Parse candidateId failed: %s.", request.getServerId());
        }
        // noinspection ConstantConditions
        do {
            // check term
            if (request.getTerm() >= this.currTerm) {
                LOG.info("Node {} received RequestVoteRequest from {}, term={}, currTerm={}.", getNodeId(), request.getServerId(), request.getTerm(), this.currTerm);
                // increase current term, change state to follower
                if (request.getTerm() > this.currTerm) {
                    stepDown(request.getTerm(), false, new Status(RaftError.EHIGHERTERMRESPONSE, "Raft node receives higher term RequestVoteRequest."));
                }
            } else {
                // ignore older term
                LOG.info("Node {} ignore RequestVoteRequest from {}, term={}, currTerm={}.", getNodeId(), request.getServerId(), request.getTerm(), this.currTerm);
                break;
            }
            doUnlock = false;
            this.writeLock.unlock();
            final LogId lastLogId = this.logManager.getLastLogId(true);
            doUnlock = true;
            this.writeLock.lock();
            // vote need ABA check after unlock&writeLock
            if (request.getTerm() != this.currTerm) {
                LOG.warn("Node {} raise term {} when get lastLogId.", getNodeId(), this.currTerm);
                break;
            }
            final boolean logIsOk = new LogId(request.getLastLogIndex(), request.getLastLogTerm()).compareTo(lastLogId) >= 0;
            if (logIsOk && (this.votedId == null || this.votedId.isEmpty())) {
                stepDown(request.getTerm(), false, new Status(RaftError.EVOTEFORCANDIDATE, "Raft node votes for some candidate, step down to restart election_timer."));
                this.votedId = candidateId.copy();
                this.metaStorage.setVotedFor(candidateId);
            }
        } while (false);
        return // 
        RpcRequests.RequestVoteResponse.newBuilder().setTerm(// 
        this.currTerm).setGranted(// 
        request.getTerm() == this.currTerm && candidateId.equals(this.votedId)).build();
    } finally {
        if (doUnlock) {
            this.writeLock.unlock();
        }
    }
}
Also used : Status(io.dingodb.raft.Status) LogId(io.dingodb.raft.entity.LogId) PeerId(io.dingodb.raft.entity.PeerId)

Example 4 with PeerId

use of io.dingodb.raft.entity.PeerId in project dingo by dingodb.

the class Configuration method parse.

public boolean parse(final String conf) {
    if (StringUtils.isBlank(conf)) {
        return false;
    }
    reset();
    final String[] peerStrs = StringUtils.split(conf, ',');
    for (String peerStr : peerStrs) {
        final PeerId peer = new PeerId();
        int index;
        boolean isLearner = false;
        if ((index = peerStr.indexOf(LEARNER_POSTFIX)) > 0) {
            // It's a learner
            peerStr = peerStr.substring(0, index);
            isLearner = true;
        }
        if (peer.parse(peerStr)) {
            if (isLearner) {
                addLearner(peer);
            } else {
                addPeer(peer);
            }
        } else {
            LOG.error("Fail to parse peer {} in {}, ignore it.", peerStr, conf);
        }
    }
    return true;
}
Also used : PeerId(io.dingodb.raft.entity.PeerId)

Example 5 with PeerId

use of io.dingodb.raft.entity.PeerId in project dingo by dingodb.

the class CliServiceImpl method rebalance.

@Override
public Status rebalance(final Set<String> balanceGroupIds, final Configuration conf, final Map<String, PeerId> rebalancedLeaderIds) {
    Requires.requireNonNull(balanceGroupIds, "Null balance group ids");
    Requires.requireTrue(!balanceGroupIds.isEmpty(), "Empty balance group ids");
    Requires.requireNonNull(conf, "Null configuration");
    Requires.requireTrue(!conf.isEmpty(), "No peers of configuration");
    LOG.info("Rebalance start with raft groups={}.", balanceGroupIds);
    final long start = Utils.monotonicMs();
    int transfers = 0;
    Status failedStatus = null;
    final Queue<String> groupDeque = new ArrayDeque<>(balanceGroupIds);
    final LeaderCounter leaderCounter = new LeaderCounter(balanceGroupIds.size(), conf.size());
    for (; ; ) {
        final String groupId = groupDeque.poll();
        if (groupId == null) {
            // well done
            break;
        }
        final PeerId leaderId = new PeerId();
        final Status leaderStatus = getLeader(groupId, conf, leaderId);
        if (!leaderStatus.isOk()) {
            failedStatus = leaderStatus;
            break;
        }
        if (rebalancedLeaderIds != null) {
            rebalancedLeaderIds.put(groupId, leaderId);
        }
        if (leaderCounter.incrementAndGet(leaderId) <= leaderCounter.getExpectedAverage()) {
            // The num of leaders is less than the expected average, we are going to deal with others
            continue;
        }
        // Find the target peer and try to transfer the leader to this peer
        final PeerId targetPeer = findTargetPeer(leaderId, groupId, conf, leaderCounter);
        if (!targetPeer.isEmpty()) {
            final Status transferStatus = transferLeader(groupId, conf, targetPeer);
            transfers++;
            if (!transferStatus.isOk()) {
                // The failure of `transfer leader` usually means the node is busy,
                // so we return failure status and should try `rebalance` again later.
                failedStatus = transferStatus;
                break;
            }
            LOG.info("Group {} transfer leader to {}.", groupId, targetPeer);
            leaderCounter.decrementAndGet(leaderId);
            groupDeque.add(groupId);
            if (rebalancedLeaderIds != null) {
                rebalancedLeaderIds.put(groupId, targetPeer);
            }
        }
    }
    final Status status = failedStatus != null ? failedStatus : Status.OK();
    if (LOG.isInfoEnabled()) {
        LOG.info("Rebalanced raft groups={}, status={}, number of transfers={}, elapsed time={} ms, rebalanced result={}.", balanceGroupIds, status, transfers, Utils.monotonicMs() - start, rebalancedLeaderIds);
    }
    return status;
}
Also used : Status(io.dingodb.raft.Status) ArrayDeque(java.util.ArrayDeque) PeerId(io.dingodb.raft.entity.PeerId)

Aggregations

PeerId (io.dingodb.raft.entity.PeerId)72 Status (io.dingodb.raft.Status)27 Configuration (io.dingodb.raft.conf.Configuration)15 Message (com.google.protobuf.Message)12 ArrayList (java.util.ArrayList)12 JRaftException (io.dingodb.raft.error.JRaftException)10 LogId (io.dingodb.raft.entity.LogId)9 CliRequests (io.dingodb.raft.rpc.CliRequests)8 Node (io.dingodb.raft.Node)6 RpcRequests (io.dingodb.raft.rpc.RpcRequests)4 Endpoint (io.dingodb.raft.util.Endpoint)4 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)4 LogEntry (io.dingodb.raft.entity.LogEntry)3 NodeOptions (io.dingodb.raft.option.NodeOptions)3 ByteBuffer (java.nio.ByteBuffer)3 TimeoutException (java.util.concurrent.TimeoutException)3 RaftOutter (io.dingodb.raft.entity.RaftOutter)2 RaftException (io.dingodb.raft.error.RaftException)2 ThreadId (io.dingodb.raft.util.ThreadId)2 ExecutionException (java.util.concurrent.ExecutionException)2