FinalRequestProcessor

FinalRequestProcessor是责任链中的最后一个请求处理器,负责把已经commit的写操作(事务)应用到内存数据库中去,对于读操作则从本机中读取数据并返回给client。创建客户端请求的响应。

FinalRequestProcessor是一个同步处理的processor,主要的处理逻辑就在方法processRequest中:

  • 如果request.hdr != null,则表明request是写操作,则调用zks.processTxn(hdr,
    txn)来把request关联的写操作执行到内存数据库中

  • 如果是写操作,则调用zks.getZKDatabase().addCommittedProposal(request);
    把request加入到ZKDatabase.committedLog队列中,这个队列主要是为了快速和follower同步而保留的,详见zookeeper leader和learner的数据同步。

  • 为各类操作准备响应数据,对于写操作则根据processTxn的结果来回复,如果是读操作,则读取内存中的状态 发送响应数据给client

   public void processRequest(Request request) {
           ProcessTxnResult rc = null;
        synchronized (zks.outstandingChanges) {
            while (!zks.outstandingChanges.isEmpty()
                    && zks.outstandingChanges.get(0).zxid <= request.zxid) {
                ChangeRecord cr = zks.outstandingChanges.remove(0);
                if (cr.zxid < request.zxid) {
                    LOG.warn("Zxid outstanding "
                            + cr.zxid
                            + " is less than current " + request.zxid);
                }
                if (zks.outstandingChangesForPath.get(cr.path) == cr) {
                    zks.outstandingChangesForPath.remove(cr.path);
                }
            }
            if (request.hdr != null) {
               TxnHeader hdr = request.hdr;
               Record txn = request.txn;

               rc = zks.processTxn(hdr, txn);//把事务请求应用到内存数据库
            }
            // do not add non quorum packets to the queue.
            if (Request.isQuorum(request.type)) {
            //如果是事务请求,则把request加入到ZKDatabase.committedLog队列中
                zks.getZKDatabase().addCommittedProposal(request);
            }
            ....
        }

接下来来看一下如何提交到内存数据库zks.processTxn(hdr, txn);

    public ProcessTxnResult processTxn(TxnHeader hdr, Record txn) {
    ....
    rc = getZKDatabase().processTxn(hdr, txn);
    ....
    }

    public ProcessTxnResult processTxn(TxnHeader hdr, Record txn) {
        return dataTree.processTxn(hdr, txn);
    } 

        public ProcessTxnResult processTxn(TxnHeader header, Record txn)
    {
        ProcessTxnResult rc = new ProcessTxnResult();
        ....
        if (rc.zxid > lastProcessedZxid) {
            lastProcessedZxid = rc.zxid;
        }
        ....
    }

我关心的重点是提交到数据库的时候会不会记日志来记录当前服务器已经提交的事务zxid呢?

由上面的源码分析来看并不会记日志,仅仅只是在内存中修改了lastProcessedZxid,代表最后一个提交的事务zxid,并没有持久化,这样的好处就是快,因为不用每次提交都写日志。
那么如果机器突然挂掉重启服务后怎么知道上一次提交到哪里呢?将在下一篇zookeeper服务器初始化的过程中分析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值