以前文章
我们知道当我们选择出leader之后 ,leader 会同步数据给 follower 和 observer。
在同步数据时采用两种方式,一种是采用增量,一种是采用全部同步
- 如果 follower 滞后 leader 不多, leader 只需发送缺失的事务点即可。
- 如果 follower 滞后 leader 很久, leader 需要发送完整的快照。
数据同步是怎么完成的?
standalone 处理过程
PrepRequestProcessor
接受客户端的请求并执行这个请求,生成一个事务。
SyncRequestProcessor
负责将事务持久化到磁盘中。即将事务数据按顺序追加到事务日志中,并生成快照数据。
FinalRequestProcessor
事务操作将接受对数据树的修改。
leader 处理过程
PrepRequestProcessor
接受客户端的请求并执行这个请求,生成一个事务。
ProposalRequestProcessor
- 将请求转发给
CommitProcessor
- 准备一个
proposal
并发送给follower
- 将请求转发给
SyncRequestProcessor
public ProposalRequestProcessor(LeaderZooKeeperServer zks, RequestProcessor nextProcessor) { this.zks = zks; this.nextProcessor = nextProcessor; AckRequestProcessor ackProcessor = new AckRequestProcessor(zks.getLeader()); syncProcessor = new SyncRequestProcessor(zks, ackProcessor); } public void processRequest(Request request) throws RequestProcessorException { if(request instanceof LearnerSyncRequest){ zks.getLeader().processSync((LearnerSyncRequest)request); } else { // CommitProcessor nextProcessor.processRequest(request); if (request.hdr != null) { try { zks.getLeader().propose(request); } catch (XidRolloverException e) { throw new RequestProcessorException(e.getMessage(), e); } // SyncRequestProcessor syncProcessor.processRequest(request); } } }
SyncRequestProcessor
持久化事务到磁盘上并生成快照数据,并触发 AckRequestProcessor
处理器,
AckRequestProcessor
- 转发一个 ack 的响应给 leader (leader 自己也需要ack确认)
- 判断 ack 超过一半则进行提交操作并给 follower 发送 commit 命令
- 给observer发送inform信令,执行事务操作
zk.commitProcessor.commit(p.request);
唤醒CommitProcessor
线程
CommitProcessor
用来等待有提交操作时,唤醒 ToBeAppliedRequestProcessor
ToBeAppliedRequestProcessor
唤醒 FinalRequestProcessor
FinalRequestProcessor
事务操作将接受对数据树的修改。
1、接收客户端的request请求
2、将会修改同步数据的request请求 转化为proposal,并保存。
3、向所有的follower发送proposal。
4、接收follower的ack。
5、统计收到的ack,如果某一个proposal的ack超过了半数,那么向所有follower发送commit 信令,并向所有observer发送inform信令,执行这个proposal的动作。
6、leader自己执行已经被commit的proposal所对应的操作,并回复结果。
follower 处理过程
FollowerRequestProcessor
- 接受客户端请求
- 转发请求到
CommitProcessor
- 将事务请求转发给 leader
CommitProcessor
- 读请求会直接调用
FinalRequestProcessor
- 写请求会转发给
FinalRequestProcessor
之前等待事务提交
SyncRequestProcessor
- 当 leader 准备一个
proposal
并发送给follower
时 - follower 通过队列能收到一个
proposal
,持久化到磁盘,并生成快照 - 调用
SendAckRequestProcessor
SendAckRequestProcessor
向 leader 发送 ack 确认
当收到leader 的提交事务请求后, CommitProcessor
便会提交事务。
1、 发现leader。
2、 建立与leader的连接。
3、 向leader注册。(leader activation)
4、 与leader进行同步。
5、 无限循环
—读取从leader处接收到的信令。
—处理从leader处接收到的信令。
A、 如果是PROPOSAL信令(写请求),将此信令投递到FollowerZooKeeperServer的synProcessor。主要作用是回复leader一个ack。
B、 如果是COMMIT信令,将此信令投递到FollowerZooKeeperServer的commitProcessor。最终执行FollowerZooKeeperServer的commit函数。
C、 如果是SYNC信令,将此信令投递到FollowerZooKeeperServer的commitProcessor。commitProcessor直接将此信令转发给FinalRequestProcessor,将sync信令带的内容写入持久层。
Observer zookeeper server 处理过程
1、 发现leader。
2、 连接到leader上,建立TCP连接。
3、 与leader进行同步,同步leader上已经被commit的proposal。
4、 无限循环,读取接收到得信令,处理信令。
1、如果是syn信令,调用ObserverZooKeeperServer的syn函数,投递到commitProcessor中。
2、如果是info信令,同样调用ObserverZooKeeperServer的commit函数,投递到commitProcessor中。
OserverZookeeperServer的责任链基本上与follower的相同如下,只是commitProcessor调用的commit函数里的处理不同 .
follower会得到两个消息,而observer只会得到一个。follower通过广播得到proposal的内容,接下来获得一个简单commit消息,此消息只包含了zxid。相反,observer得到一个包含了已被commit的proposal的INFORM消息。