Zookeeper

ZooKeeper顺序节点之Sequence原理

2020-11-15  本文已影响0人  超人也害羞

sequence自增原理是什么?

为什么get命令看到的cversion和实际存储的cversion不一样?

sequence自增怎么保证无并发问题?单节点和多节点?

  1. sequence自增原理是什么?

    // 代码取自(服务端代码)org.apache.zookeeper.server.PrepRequestProcessor#pRequest2TxnCreate
    ChangeRecord parentRecord = getRecordForPath(parentPath);
    checkACL(zks, parentRecord.acl, ZooDefs.Perms.CREATE, request.authInfo);
    int parentCVersion = parentRecord.stat.getCversion();
    if (createMode.isSequential()) {
        // 如果是顺序节点的话,从父节点中取出cversion的值作为sequence.
        path = path + String.format(Locale.ENGLISH, "%010d", parentCVersion);
    }
    
  2. 为什么get命令看到的cversion和实际存储的cversion不一样?

    知道了sequence取值逻辑后,用get命令查看父节点的cversion字段,却发现总是和新生成节点的sequence不一致?最后定位到get命令的代码.

    // 代码取自(服务端代码)org.apache.zookeeper.server.DataNode#copyStat
    synchronized public void copyStat(Stat to) {
            to.setAversion(stat.getAversion());
            to.setCtime(stat.getCtime());
            to.setCzxid(stat.getCzxid());
            to.setMtime(stat.getMtime());
            to.setMzxid(stat.getMzxid());
            to.setPzxid(stat.getPzxid());
            to.setVersion(stat.getVersion());
            to.setEphemeralOwner(getClientEphemeralOwner(stat));
            to.setDataLength(data == null ? 0 : data.length);
            int numChildren = 0;
            if (this.children != null) {
                numChildren = children.size();
            }
         // 重点!
            // when we do the Cversion we need to translate from the count of the creates
            // to the count of the changes (v3 semantics)
            // for every create there is a delete except for the children still present
         // 当我们进行Cversion时,我们需要从create的数量中进行翻译更改计数(v3语义)对于每个创建都有一个删除,除了仍然存在的孩子(Google 翻译)
            to.setCversion(stat.getCversion()*2 - numChildren);
            to.setNumChildren(numChildren);
    }
    
  3. sequence自增怎么保证无并发问题?单节点和多节点?

    先来说多节点吧,(参考网上通常的说法)当一个客户端进行写数据请求时,会指定ZooKeeper集群中的一个Server节点,如果该节点为Follower,则该节点会把写请求转发给Leader,Leader通过内部的协议进行原子广播,直到一半以上的server节点都成功写入数据,这次写请求便算是成功,然后Leader便会通过通知相应的Follower节点写请求成功,该节点向client返回写入成功.
    本质上说还是把多节点写操作转换成了单节点的写操作,这样就可以在单节点进行并发控制了,效率更高.而在单节点做并发控制的话就方便的多了,通过PrepRequestProcessor->SyncRequestProcessor->FinalRequestProcessor->ZooKeeperServer->ZKDatabase->DataTree链路处理.有兴趣可以自己翻翻代码哦.

上一篇下一篇

猜你喜欢

热点阅读