stateIs0 / lu-raft-kv

this is raft java project. raft-kv-storage
https://thinkinjava.cn/2019/01/12/2019/2019-01-12-lu-raft-kv/
Apache License 2.0
806 stars 216 forks source link

系统可能存在两个问题:关于关闭节点后节点仍然会参与共识过程的 bug report #22

Open xyy9949 opened 1 year ago

xyy9949 commented 1 year ago

您好,我们在对系统进行测试时发现系统可能存在两个问题:

  1. 在关闭某个节点后该节点仍然会参与共识,接受 leader 发出的 proposal 并 commit。
  2. 在关闭某个节点后,如果用client查询该节点的数据,有时可以成功,有时不会成功。

首先,我们小幅修改了 RaftClient 类下的 get 方法代码,使得 client 使用 get 方法获取对应 key 的 value 值时,可以选择对应的节点的value。并且在 RaftClientWithCommandLine 类中将 get 方法替换为了 getCertainPeerKey 方法。

    /**
     * @param key
     * @return
     */
    // 修改 get 为 getCertainPeerKey,增加输入的参数 addr, 使client能获得对应节点的value
    // addr 为:"localhost:8777", "localhost:8778", "localhost:8779"其中之一
    public LogEntry getCertainPeerKey(String key, String addr) {
        ClientKVReq obj = ClientKVReq.builder().key(key).type(ClientKVReq.GET).build();

        ClientKVAck response;
        Request r = Request.builder().obj(obj).url(addr).cmd(Request.CLIENT_REQ).build();
        try {
            response = CLIENT.send(r);
        } catch (Exception e) {
            r.setUrl(list.get((int) ((count.incrementAndGet()) % list.size())));
            response = CLIENT.send(r);
        }
        return (LogEntry)response.getResult();
    }

复现过程如下:

  1. 启动三个节点,节点端口号分别为:8777,8778和8779,等待新leader产生
  2. 启动RaftClientWithCommandLine
  3. 输入 put A 0
  4. 关闭 leader 节点(这里我关闭的是8777),等待新leader产生
  5. 输入 put A 1
  6. 多次尝试输入 get A

此时会得到两种结果: 一种是:

截屏2023-04-27 22 18 11

另一种是:

截屏2023-04-27 22 18 36

在前一种结果时,我们可以看到 8777 节点仍然 commit 了<A, 1> 这表明它参与了第5步的proposal的共识过程,但是在这一步被执行时它已经被关闭并且之后并未被重新启动,这里存在矛盾,此为问题1。 这两种结果的出现情况无法被控制,此为问题2。

希望得到您的回复,谢谢!

kebukeYi commented 1 year ago

既然关闭服务了,怎么可能还能正常返回结果啊