Coder Social home page Coder Social logo

Comments (5)

fengjiachun avatar fengjiachun commented on August 22, 2024

感谢关注 jraft
如果我没理解错您的意思的话,jraft 中的处理貌似不存在问题,以下是 jraft 的 leader transfer 过程:

  1. transferLeadershipTo 方法在 writeLock 保护中更新 state 为 STATE_TRANSFERRING
  2. lease read 要先在 readLock 中检查 state, 如果 state 为 STATE_TRANSFERRING 会禁止 read, 相关逻辑在 handleReadIndexRequest方法内(lease read 也在该方法内实现的)

from sofa-jraft.

oatiz avatar oatiz commented on August 22, 2024

感谢您的答复,这是我对transferLeadershipTo方法的注解
请看中文注释:

public Status transferLeadershipTo(PeerId peer) {
        Requires.requireNonNull(peer, "Null peer");
        writeLock.lock();
        try {
            if (state != State.STATE_LEADER) {
                LOG.warn("Node {} can't transfer leadership to peer {} as it is in state {}", this.getNodeId(), peer,
                    this.state);
                return new Status(state == State.STATE_TRANSFERRING ? RaftError.EBUSY : RaftError.EPERM,
                        "Not a leader");
            }
            if (confCtx.isBusy()) {
                // It's very messy to deal with the case when the |peer| received
                // TimeoutNowRequest and increase the term while somehow another leader
                // which was not replicated with the newest configuration has been
                // elected. If no add_peer with this very |peer| is to be invoked ever
                // after nor this peer is to be killed, this peer will spin in the voting
                // procedure and make the each new leader stepped down when the peer
                // reached vote timedout and it starts to vote (because it will increase
                // the term of the group)
                // To make things simple, refuse the operation and force users to
                // invoke transfer_leadership_to after configuration changing is
                // completed so that the peer's configuration is up-to-date when it
                // receives the TimeOutNowRequest.
                LOG.warn(
                    "Node {} refused to transfer leadership to peer {} when the leader is changing the configuration",
                    this.getNodeId(), peer);
                return new Status(RaftError.EBUSY, "Changing the configuration");
            }

            PeerId peerId = peer.copy();
            // if peer_id is ANY_PEER(0.0.0.0:0:0), the peer with the largest
            // last_log_id will be selected.
            if (peerId.equals(PeerId.ANY_PEER)) {
                LOG.info("Node {} starts to transfer leadership to any peer.", getNodeId());
                if ((peerId = replicatorGroup.findTheNextCandidate(this.conf)) == null) {
                    return new Status(-1, "Candidate not found for any peer");
                }
            }
            if (peerId.equals(this.serverId)) {
                LOG.info("Node {} transfered leadership to self.");
                return Status.OK();
            }
            if (!conf.contains(peerId)) {
                LOG.info("Node {} refused to transfer leadership to peer {} as it is not in {}", getNodeId(), peer,
                    this.conf.getConf());
                return new Status(RaftError.EINVAL, "Not in current configuration");
            }

            final long lastLogIndex = logManager.getLastLogIndex();
            /*
            * 调用transferLeadership在设置状态之前:
            * 此处进行了leader transfer,在rpc过程中,由于新leader接收到了请求,成功当选.
            * 由于网络分区的问题,老leader没有接收到resp,然后return new Status(RaftError.EINVAL,...).
            * 老leader的状态这时并没改变.
            */
            if (!this.replicatorGroup.transferLeadershipTo(peerId, lastLogIndex)) {
                LOG.warn("No such peer {}", peer);
                return new Status(RaftError.EINVAL, "No such peer %s", peer);
            }
            this.state = State.STATE_TRANSFERRING;
            final Status status = new Status(RaftError.ETRANSFERLEADERSHIP,
                "Raft leader is transferring leadership to %s", peerId);
            onLeaderStop(status);
            LOG.info("Node {} starts to transfer leadership to peer {}", getNodeId(), peer);
            final StopTransferArg stopArg = new StopTransferArg(this, currTerm, peerId);
            this.stopTransferArg = stopArg;
            this.transferTimer = this.timerManager.schedule(() -> onTransferTimeout(stopArg),
                this.options.getElectionTimeoutMs(), TimeUnit.MILLISECONDS);

        } finally {
            writeLock.unlock();
        }
        return Status.OK();
    }

from sofa-jraft.

killme2008 avatar killme2008 commented on August 22, 2024
  /*
            * 调用transferLeadership在设置状态之前:
            * 此处进行了leader transfer,在rpc过程中,由于新leader接收到了请求,成功当选.
            * 由于网络分区的问题,老leader没有接收到resp,然后return new Status(RaftError.EINVAL,...).
            * 老leader的状态这时并没改变.
            */
            if (!this.replicatorGroup.transferLeadershipTo(peerId, lastLogIndex)) {
                LOG.warn("No such peer {}", peer);
                return new Status(RaftError.EINVAL, "No such peer %s", peer);
            }

我来解释下这段代码,关键的理解差异是jraft里所有的网络请求都是异步回调的方式,因此这里的

this.replicatorGroup.transferLeadershipTo(peerId, lastLogIndex)

返回的只是说请求有没有发送(并且 timeout 请求在 replicator 复制的 log index 还没有达到 leader 最新 log index 的时候会延迟发送),并不等待应答,立即就进入下面代码了。

timeoutNow 请求的发送逻辑参见 Replicator 。 jraft 整个类库都是异步 callback 的形式,这也是他能达到较高性能的一个因素。

from sofa-jraft.

oatiz avatar oatiz commented on August 22, 2024

@killme2008 感谢偶像的耐心解答, 我再仔细研读下jraft

再次感谢 @fengjiachun 的答复.

from sofa-jraft.

killme2008 avatar killme2008 commented on August 22, 2024

@oatiz 客气,感谢这么仔细的研读,欢迎继续探讨。

from sofa-jraft.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.