Zab系列6 zk单机版工作原理

Zab系列博客

Raft Vs Zab
https://www.jianshu.com/p/24307e7ca9da
Zab系列1 核心概念
https://www.jianshu.com/p/76e5dba31ea4
Zab系列2 角色和存储
https://www.jianshu.com/p/d80f9250ffd1
Zab系列3 选举
https://www.jianshu.com/p/0d2390c242f6
Zab系列4 zookeeper特性
https://www.jianshu.com/p/08b62ca1fe4e
Zab系列5 选举恢复(源码分析)
https://www.jianshu.com/p/b6acd99921b7
Zab系列6 zk单机版工作原理
https://www.jianshu.com/p/ed45982b18b4

单机版的事务请求

http://www.cnblogs.com/davidwang456/p/5001244.html

  • 事务请求: 先append到zk的内存中,再持久化日志,持久化完成之后,响应客户端,操作成功或者失败
  • 读取请求: 直接读取,然后返回客户端

因为不涉及到投票等操作,相对来说简单很多,单机版的ZK的requestProcessor组装过程
ZookeeperServer.setupRequestProcessors()

    protected void setupRequestProcessors() {
        RequestProcessor finalProcessor = new FinalRequestProcessor(this);
        RequestProcessor syncProcessor = new SyncRequestProcessor(this,finalProcessor);
        ((SyncRequestProcessor)syncProcessor).start();
        firstProcessor = new PrepRequestProcessor(this, syncProcessor);
        ((PrepRequestProcessor)firstProcessor).start();
    }

PrepRequestProcessor -->SyncRequestProcessor-->FinalRequestProcessor
Zookeeper单机版的工作原理:

  1. Node监听到的Client发起的请求,调用PrepRequestProcessor.processRequest,把请求扔到它的submittedRequests里面
  2. PrepRequestProcessor有一个线程循环的从submittedRequest里面来消费请求(可能是事务请求,可能是非事务请求)
  3. 消费线程通过request.type,来选择不同的处理方式,如果是事务请求,则会自增zks的Zxid,且会封装消息头,header里面有这个操作的zxid、sessionId、request.cxid
  4. 而非事务请求则不需要自增Zxid,消息头为null,只需要校验Session即可
  5. 无论是哪种请求最后都会转发给SyncRequestProcessor,扔到它的queuedRequests里面
  6. SyncRequestProcessor的消费线程从queuedRequests捞任务。这里面要重点注意了:不管是不是事务请求,都会进入了queuedRequests,但是非事务请求不会被持久化,因为appendLog的时候会判断Request消息头是否为空)
  7. 调用FinalRequestProcessor,如果是事务请求,会应用内存树,完成客户响应

相关代码

  1. PrepRequestProcesso把接收到的请求扔到它的submittedRequests里面
LinkedBlockingQueue submittedRequests = new LinkedBlockingQueue();

    public void processRequest(Request request) {
        submittedRequests.add(request);
    }
  1. PrepRequestProcessor根据请求类型分开处理,不管是哪种请求都会转发到下个处理器SyncRequestProcessor
  switch (request.type) {
            case OpCode.create:                
                CreateRequest create2Request = new CreateRequest();
                pRequest2Txn(request.type, zks.getNextZxid(), request, create2Request, true);
             //All the rest don't need to create a Txn - just verify session
            case OpCode.getData:
            case OpCode.ping:
                zks.sessionTracker.checkSession(request.sessionId,request.getOwner());
    }
request.zxid = zks.getZxid();
nextProcessor.processRequest(request);
  1. SyncRequestProcessor把接收到的请求扔到它的queuedRequests里面
    public void processRequest(Request request) {
        queuedRequests.add(request);
    }
  1. SyncRequestProcessor有一个线程,从queuedRequests捞请求,会按照一定的策略(size和当前是否空闲)持久化事务请求,同时会把所有的请求交给下一个处理器
 while (true) {
     si = queuedRequests.poll();
     if (si != null) {
           if (zks.getZKDatabase().append(si)) {
                    check是否要快照
            }else{
         nextProcessor.processRequest(si);
        }
    flush(toFlush);
}

你可能感兴趣的:(Zab系列6 zk单机版工作原理)