sofastack / sofa-jraft

A production-grade java implementation of RAFT consensus algorithm.
https://www.sofastack.tech/projects/sofa-jraft/
Apache License 2.0
3.59k stars 1.15k forks source link

主从复制部分的锁竞争 #876

Closed Cczzzz closed 2 years ago

Cczzzz commented 2 years ago

jraft 的主从模式是异步的,但是我阅读代码发现实际上 发送log 和收到从节点响应的处理逻辑中会抢用同一个锁。导致处理响应时不能继续发送新的请求给从节点,即使已经有了可以发送的新log。 我尝试添加log 以观察锁的影响: 在 Replicator#continueSending 1000 行

static boolean continueSending(final ThreadId id, final int errCode) {
    if (id == null) {
        //It was destroyed already
        return true;
    }
    long nanoTime = System.nanoTime();
    final Replicator r = (Replicator) id.lock();
    long num = r.getOpts().getLogManager().getLastLogIndex() - (r.nextIndex - 1);
    if (r == null) {
        return false;
    }
    double cost = (System.nanoTime() - nanoTime) / 1000D;
    if (num > 0 && cost > 10) {
        LOG.warn("lock cost time {} us , ready log is {}", cost, num);
    }

image 在3w tps 写入的情况下 可以看到对写入到耗时大概影响到 20-30 微妙,最坏可能会到达 0.1 ms

fengjiachun commented 2 years ago

这里的锁是必要的,但是瓶颈不应该在这里。

看起来,耗时主要是 r.getOpts().getLogManager().getLastLogIndex() 吧? 另外 continueSending 通常是因为发送 log 不连续也就是吞吐较低才会被触发的,在你 3w tps 写入的情况下,这里不应该被频繁调用也不会是热点代码,理论上不影响写入耗时。

可以再看看是否有别的原因。

fengjiachun commented 2 years ago

先关闭了,有新的发现可以再打开