-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
只读节点是否可以指定一个节点读取数据 #989
Comments
目前的 learner 都是从主节点读取,还不支持从其他节点读取,这是一个好的 proposal,可能需要想下怎么设计。 |
一、背景解决类似 #issue_989 的问题,支持通过配置指定Learner节点从特定的Leader或者Follower节点获取日志,尽可能减少跨数据中心的网络流量,节约网络带宽。 如上图,共有4个节点组成一个Raft Group,其中Node1、Node2在数据中心A,Node3、Node4在数据中心B。当Node1为Leader,Node2、Node3为Follower,Node4为Learner节点,在SOFAJRaft的实现中,所有的数据流向都是从Leader->Follower/Learner,那么会存在两份跨数据中心的流量:
跨数据中心的带宽是较为昂贵的,希望能支持配置实现Learner节点可以从特定的节点(Leader/Follower)同步数据,减少跨数据中心的流量。例如实现上图中Node4从Node3复制数据。 二、目标2.1 Goals
2.2 TradeOff
三、当前数据复制实现分析上图中大致罗列了JRaft实现中Learner控制流和数据流相关的组件:
四、数据复制改造方案根据目标和当前数据复制实现的分析,要支持Learner从特定节点复制数据需要:
如上图为Learner支持从Follower复制数据后的示意图,由Node1
在JRaft的实现中,系统的控制指令和数据指令都由Leader进行操作,并通过日志复制到Follower和Learner节点,完成系统初始化状态保持一致并通过应用相同顺序的一系列的指令达到另一个一致状态的原则,所以在本改造方案中依旧保持该原则的实现,所有的操作需要通过Leader节点之后应用到各个子节点,保持状态的一致。 4.1 基础配置改造按上文分析,Follower节点需要增加Replication Group的基础配置,而Follower节点时可以升级为Leader节点的,Learner节点也可以升级为Follower节点,那么Replication Group应当成为系统的一个基础配置,所有节点都需要有Replication Group配置。
系统通过CliService#addPeer方法添加节点,用PeerId指代一个Raft Group中的参与者。采用拓展PeerId的方式,向PeerId添加replicationGroup属性,表示节点所属的复制组。
当前PeerId#toString的格式需要进行修改(且保证解析和读取方式向前兼容):
4.2 Learner相关控制流改造4.2.1 Add/Remove LearnersJRaft添加Learner节点的流程如上图,其中在NodeImpl#unsafeRegisterConfChange之前会将新增的Learner保存到Configuration中。之后通过一系列操作实现在ReplicatorGroup添加一个新的Replicator,实现从Leader节点复制数据。
当前的配置类Configuration包含peers和learners两个列表,在支持将Learner挂载到Follower后需要在配置中指定Learner对应的Follower节点,因此需要修改Configuration类,将Learner和Follower的对应关系记录到Configuration中:
同时为了实现负载均衡,需要在Leader节点拿到所有节点的Learner挂载信息,并将选择的目标节点作为Entry的一部分写入到Log中。如第三章节的分析,在JRaft的实现中通过ReplicatorGroup维护了一个节点的所有Replicator(当前是Leader节点的ReplicatorGroup维护了所有代表Follower和Learner节点的Replicator),那么需要在节点上增加RPC接口和实现,允许调用获取当前节点的Replicator信息。
增加如上协议以及对应的Processor,Leader向目标Replication Group下的节点发起请求获取挂载情况信息,并从中按策略选出目标节点,将目标节点即对应Learner信息作为一个Entry写入到日志中。Entry的data字段包含的内容为目标节点的PeerId#toString结果。
移除Learner操作和添加Learner类似:
4.2.2 Get/GetAlive LearnersGet Learners操作通过Leader去获取Learner节点。因为Learner信息依旧保存在Configuration中,Leader可以直接通过Configuration拿到Learner列表并返回,所以本方案的变更对Get Learners操作无影响。 4.2.3 Reset LearnersReset Learners只是将Configuration的Learner配置进行修改,然后通过ConfigurationCtx#start方法去应用生效,流程和Add/Remove Learners操作是一致的,不需要做额外的修改。 4.2.4 Learner to FollowerLearner to Follower实现上是先Remove Learner节点,然后将Learner节点作为一个新的Follower节点进行添加操作,所以实现上不需要做任何修改。 4.3 Follower支持数据复制的改造ReplicatorGroup和Replicator已经实现了节点间的数据复制能力,在Follower上仅需根据配置决定是否启动Replicator来向Learner节点传输数据。
4.4 FO相关改造4.4.1 Follower故障时的改造当Follower故障时,挂在到该Follower的Learner节点需要自动化的迁移至同一个replicationGroup下的其他Follower节点。若此时目标replicationGroup下无可用的Follower节点则降级为挂载到Leader节点。 4.4.2 Follower提升为Leader节点时的改造添加ReplicationGroup配置的目的是解决跨数据中心的流量问题,因此ReplicationGroup用于标识处于同一个数据中心的节点,和节点的身份状态无关。所以当Follower节点升级为Leader节点时并不需要做任何改造工作,此时Learner从Leader节点复制数据,并依旧遵循ReplicationGroup的规则,并不会出现跨数据中心的数据复制。 |
👍 看起来很酷,感觉可以试试 |
背景是这样的:
我在甲地部署了A、B两个节点,在乙地部署了C,D两个节点。
我让A、B、C作为一个raft集群,D是这个集群的只读节点,并且将C的优先级设置为0,这样就可以保证在服务可用的情况下这个集群主节点一定在甲地。
同时我让C、D、A作为另一个raft集群,B是这个集群的只读节点,并且将A的优先级设置为0,这样就可以保证在服务可用的情况下这个集群主节点一定在乙地。
现在遇到一个小问题,数据同步的方向是主节点向从节点同步(包括只读节点),跨地区网络流量翻倍,有没有办法配置让只读节点从本地的从节点读数据,(第一个集群D从C读数据,第二个集群B从A读数据)。这样降低跨地区的网络开销。
The text was updated successfully, but these errors were encountered: