Zookeeper 3.6.X支持持久化watcher节点

公司内部使用zk的watcher功能做一个分布式监听器,用来做一个数据变更通知,但是出现了数据不同步的问题,查看了zk相关源码,发现zk的watcher在触发一次后,就会从监视队列中移除,也就是说,watcher是一次性的。
之前为了解决数据变更通知不丢消息的问题,考虑自己来实现一个简单的watcher机制,然后就考虑去扒一下zk的源码,稍微改一改,弄个简易版的watcher满足我们的需求即可,于是去github上clone了最新的代码,找到watcher触发相关的部分。Emmmm?!?! 我们一起来看一哈。
PS:在看Curator相关代码的时候,发现了关联的zk的任务–zk增加了持久化递归监视

https://issues.apache.org/jira/browse/ZOOKEEPER-1416

首先我切到3.6版本的分支,因为我在服务器上部署的是3.6.2版本的zk,所以branch_3.6应该是对应的我部署的server版本的代码。接收请求的流程就不详细说了,网上很多解析(关键是具体我也没看,直接百度然后找到重点代码来看的/狗头),请求最终都会走到这个类里面org.apache.zookeeper.server.FinalRequestProcessor,然后执行这个方法org.apache.zookeeper.server.FinalRequestProcessor#processRequest

public void processRequest(Request request) {
        LOG.debug("Processing request:: {}", request);

        // request.addRQRec(">final");
        long traceMask = ZooTrace.CLIENT_REQUEST_TRACE_MASK;
        if (request.type == OpCode.ping) {
            traceMask = ZooTrace.SERVER_PING_TRACE_MASK;
        }
        if (LOG.isTraceEnabled()) {
            ZooTrace.logRequest(LOG, traceMask, 'E', request, "");
        }

        ProcessTxnResult rc = zks.processTxn(request);
		// 以下省略成吨的代码
}

我们重点看一下zks.processTxn(request); 这个方法。点进去

public ProcessTxnResult processTxn(Request request) {
        TxnHeader hdr = request.getHdr();
        processTxnForSessionEvents(request, hdr, request.getTxn());

        final boolean writeRequest = (hdr != null);
        final boolean quorumRequest = request.isQuorum();

        // return fast w/o synchronization when we get a read
        if (!writeRequest && !quorumRequest) {
            return new ProcessTxnResult();
        }
        synchronized (outstandingChanges) {
            ProcessTxnResult rc = processTxnInDB(hdr, request.getTxn(), request.getTxnDigest());

            // request.hdr is set for write requests, which are the only ones
            // that add to outstandingChanges.
            if (writeRequest) {
                long zxid = hdr.getZxid();
                while (!outstandingChanges.isEmpty()
                        && outstandingChanges.peek().zxid <= zxid) {
                    ChangeRecord cr = outstandingChanges.remove();
                    ServerMetrics.getMetrics().OUTSTANDING_CHANGES_REMOVED.add(1);
                    if (cr.zxid < zxid) {
                        LOG.warn(
                            "Zxid outstanding 0x{} is less than current 0x{}",
                            Long.toHexString(cr.zxid),
                            Long.toHexString(zxid));
                    }
                    if (outstandingChangesForPath.get(cr.path) == cr) {
                        outstandingChangesForPath.remove(cr.path);
                    }
                }
            }

            // do not add non quorum packets to the queue.
            if (quorumRequest) {
                getZKDatabase().addCommittedProposal(request);
            }
            return rc;
        }
    }

其中同步块中,ProcessTxnResult rc = processTxnInDB(hdr, request.getTxn(), request.getTxnDigest()); 返回的类叫XXXResult,而方法名是processXXXInDB,而且入参是吧请求reqeust的一些东西丢了进去,应该是处理请求并得到结果,点进去可以看到都是参数传递,直接调用了下一层的方法,直到org.apache.zookeeper.server.DataTree#processTxn(TxnHeader, org.apache.jute.Record, boolean)

 public ProcessTxnResult processTxn(TxnHeader header, Record txn, boolean isSubTxn) {
        ProcessTxnResult rc = new ProcessTxnResult();

        try {
            rc.clientId = header.getClientId();
            rc.cxid = header.getCxid();
            rc.zxid = header.getZxid();
            rc.type = header.getType();
            rc.err = 0;
            rc.multiResult = null;
            switch (header.getType()) {
            case OpCode.create:
                CreateTxn createTxn = (CreateTxn) txn;
                rc.path = createTxn.getPath();
                createNode(
                    createTxn.getPath(),
                    createTxn.getData(),
                    createTxn.getAcl(),
                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值