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

对于PeerId中index的一些疑问 #921

Closed funky-eyes closed 1 year ago

funky-eyes commented 1 year ago

Your question

PeerId 表示一个 raft 协议的参与者(leader/follower/candidate etc.), 它由三元素组成: ip:port:index, IP 就是节点的 IP, port 就是端口, index 表示同一个端口的序列号,目前没有用到,总被认为是 0。预留此字段是为了支持同一个端口启动不同的 raft 节点,通过 index 区分。 上述内容是官网的解释,也就是我业务端口假设是8091,我在8091上要使用multi-raft,我可能会创建多个raft节点,例如 raft集群1: 192.168.31.182:9091::100,192.168.31.181:9092::10,192.168.31.183:9093::10 集群2:192.168.31.182:9095::100,192.168.31.181:9096::10,192.168.31.183:9097::10 实际182,181,183 三个节点上跑了2个raft集群,业务端口为8091,8092,8093,但是由于是multi-raft,业务有业务的端口,通过cliservice只能获取到集群raft选举和通信的端口,无法知晓raft节点的业务端口是多少,比如一个http的端口。 我是否可以将index改为业务具体端口,写成如下 raft集群1: 192.168.31.182:9091:8091:100,192.168.31.181:9092:8092:10,192.168.31.183:9093:8093:10 集群2:192.168.31.182:9095:8091:100,192.168.31.181:9096:8091:10,192.168.31.183:9097:8091:10 这样就有点像zk的配置server.1=192.168.31.181:2888:3888的样子,用户使用上还是比较符合其传统中间件的习惯的 这样我就可以达到多个节点都知道彼此的http端口是多少,但是由于index字段是预留的,我担心后续被jraft官方使用了,这样就会出现冲突,如果会被使用,是否可以在peerid这个对象里增加一个扩展字段,这个字段可以是string类型,业务自行使用? 如 192.168.31.182:9095::10:{“http-port”: "8088"} 之类的,具有业务含义的内容存在?

Your scenes

Describe your use scenes (why need this feature)

Your advice

Describe the advice or solution you'd like

Environment

funky-eyes commented 1 year ago

@fengjiachun @killme2008 PTAL

fengjiachun commented 1 year ago

可预见的时间内,jraft 应该不会在内部启用 index,不过除非你别无他法,否则也不建议业务层使用 index,cc @killme2008

funky-eyes commented 1 year ago

可预见的时间内,jraft 应该不会在内部启用 index,不过除非你别无他法,否则也不建议业务层使用 index,cc @killme2008

目前来看好像也没什么好的办法,家纯兄对我上面场景有什么建议吗? 假设我client只能通过cliservice读到peerid里的port也就是jraft的端口,业务端口貌似无法知晓,初期我尝试http port+1000,假设8088,那么jraft端口就是9088这样固定的间隔来使client知晓leader节点地址,而目前来看在multi-raft下,raft的端口可能有多个,就无法用固定的jraft端口-1000形式来得出http的端口了

fengjiachun commented 1 year ago

没有明白的是,multi-group 用 groupId 隔离就可以了,为什么还需要多个端口?

funky-eyes commented 1 year ago

没有明白的是,multi-group 用 groupId 隔离就可以了,为什么还需要多个端口?

难道是我使用的有问题?我是想搭成3台机器,3个进程,3个group的形式,RaftGroupService没有多个groupid的入参,每一个RaftGroupService里的rpcServer是不能共享的端口被占用,包括log的datapath也不行会文件被使用中等错误,起不来

fengjiachun commented 1 year ago

单进程就可以了,共享一个 RaftGroupService,每个 jraft request 都有 groupId 的,rpc processor 会根据 groupId 隔离,具体看这里

fengjiachun commented 1 year ago

RheaKV 就是 multi group 啊,一个 StoreEngine 包含多个 RegionEngine, 参考一下就行了

funky-eyes commented 1 year ago

单个进程不是很理解,raft起码得3个进程吧,我上面说的是3个进程,刚好是3个集群而不是1个集群,每个集群是一个独立的group. 我看了下RegionEngine的代码,是不是看region做隔离,RaftGroupService里的group还是同一个,然后StateMachine也是记录当前的region,通过同的region,提交到不通的状态机中?

funky-eyes commented 1 year ago

又看了一下明白了

 final RpcServer rpcServer = this.storeEngine.getRpcServer(); //共享的rpcserver
        this.raftGroupService = new RaftGroupService(opts.getRaftGroupId(), serverId, nodeOpts, rpcServer, true);
        this.node = this.raftGroupService.start(false); //因为已经开启start了
        RouteTable.getInstance().updateConfiguration(this.raftGroupService.getGroupId(), nodeOpts.getInitialConf()); // 更新集群配置

核心是这块,共享了raftGroupService,多个region=多个group,然后每个group一个fsm,每个region的增删改动作都使用对应的fsm提交Closure即可,是这样吗?

fengjiachun commented 1 year ago

funky-eyes commented 1 year ago

搞好了@fengjiachun 谢谢家纯兄指导,看了下RheaKV这块立马醍醐灌顶呀