Closed leakey0626 closed 1 year ago
感谢pr,我先看看细节😁
哈喽,请问review过程还需要我提供什么帮助吗(本机上测试ok)
哈喽,请问review过程还需要我提供什么帮助吗(本机上测试ok)
我正在看代码。改的地方比较多,比如这个 心跳间隔基数 为什么改成 300?
哈喽,请问review过程还需要我提供什么帮助吗(本机上测试ok)
还有一些重入锁,为什么把超时锁变成无超时的?我理解后者相较而言不容易排查问题。
嗯嗯,小改动确实比较多,辛苦您review了~ 我为了提高测试效率(raft整体运行效率),把心跳时间间隔、选举超时时间等参数调小了。我应该改回去或者说明一下的,后面给忘记了,不好意思。。
哈喽,请问review过程还需要我提供什么帮助吗(本机上测试ok)
还有一些重入锁,为什么把超时锁变成无超时的?我理解后者相较而言不容易排查问题。
您指的是不是DefaultLogModule
里面的lock
?原项目这部分的代码在tryLock
超时之后仍会继续执行,这样难以保证写日志过程的线程安全。我参考了另外一些开源项目的设计,如 sofa-jraft 、wenweihu86的raft-java,它们也是采用无超时锁,所以我认为不存在死锁条件时可以使用无超时锁。如果有说得不对的地方烦请指出~
使用超时锁 是一种好的开发习惯
受教了~
如果此处改为
if (!lock.tryLock(3000, MILLISECONDS)) return;
会不会更合适一些呢
抱歉,感觉代码还有很多不完善的地方,我再改进一下~
@leakey0626 刚刚我还在 review 呢,回过头就 close 了 😂
@leakey0626 刚刚我还在 review 呢,回过头就 close 了 😂
这两天回看代码的时候发现我优化的部分有不少问题,为了不耽误您的时间,我就想着先 close,改完之后再提交。 可能有点缺乏 git 使用经验,擅自关闭 pr 是不是不太友好。。
@leakey0626 刚刚我还在 review 呢,回过头就 close 了 😂
这两天回看代码的时候发现我优化的部分有不少问题,为了不耽误您的时间,我就想着先 close,改完之后再提交。 可能有点缺乏 git 使用经验,擅自关闭 pr 是不是不太友好。。
没关系,你再看看呗,我也研究你提的几个问题。期待你的新提pr。
@leakey0626 刚刚我还在 review 呢,回过头就 close 了 😂
这两天回看代码的时候发现我优化的部分有不少问题,为了不耽误您的时间,我就想着先 close,改完之后再提交。 可能有点缺乏 git 使用经验,擅自关闭 pr 是不是不太友好。。
没关系,你再看看呗,我也研究你提的几个问题。期待你的新提pr。
跟您的交流过程中学到了很多东西,非常感谢
非常感谢莫那·鲁道给我们提供了如此优秀的raft开源项目!
我是raft的初学者大东,在学习您的项目的过程中,我发现了该项目存在一定的优化空间,于是我对代码进行了一些增改,希望能达到锦上添花的效果。下面是我对优化点的说明:
日志提交
问题描述
在原项目中,跟随者接收到 append entry 请求后,会立即将日志内容应用到状态机,个人认为这种做法有风险。
假设日志还未分发到多数节点时,【领导者A】宕机,并且下一任【领导者B】恰好不含该日志,那么该日志将会在【领导者B】发出它的 append entry 请求时被清除。但原先持有该日志的节点已经将其应用到状态机了,并且无法撤销
apply
。所以,该机制会导致状态机数据与日志数据的不一致。这种不一致一方面会导致我们无法通过日志准确地恢复出状态机的数据,不利于备份和分析;另一方面,若后期对项目进行扩展,让跟随者承担一部分“读操作”的职责时,会产生严重的数据不一致问题。
优化
领导者提交日志的逻辑修改为:
跟随者提交日志的逻辑修改为:
补充:
getLastIndex
返回-1,getPreLog
返回{-1,-1}no-op 空日志
问题描述
优化
引入 no-op 空日志来解决补充①里提到的可用性问题:
command
为 null 的日志并提交客户端协议
优化
完善了客户端请求类
RaftClientRPC
:若 RPC 调用超时,会将请求发送至另一个节点,不断循环直至获取到服务端响应引入了幂等性机制:在客户端请求体中加入由 ip 和序号组成的 request id。当请求被 raft 集群响应后,request id 会存储至各节点的状态机中。这样可以保证即使领导者在执行命令之后、返回客户端响应之前宕机,客户端去寻找下一任领导者处理请求时,同一命令不会在状态机上执行两次
实现了基于命令行交互的客户端:解析用户输入并返回处理结果
线性一致性
问题描述
系统发生网络分区时,可能存在两个领导者。旧领导者仍在工作,但集群的另一部分已经选举出一个新的领导者,并提交了新的日志条目。如果此时客户端连接的恰好是旧领导者,那么它将返回旧的数据给客户端,这不满足线性一致性——读操作必须返回最近一次提交的写操作的结果。
优化
结合心跳机制实现线性一致性:
运行说明
-Dserver.port=8775
RaftNodeBootStrap
RaftClient
进行调试和验证参考:《深入理解分布式系统》,唐伟志