sequence自增原理是什么?
为什么get命令看到的cversion和实际存储的cversion不一样?
sequence自增怎么保证无并发问题?单节点和多节点?
-
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); }
-
为什么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); }
-
sequence自增怎么保证无并发问题?单节点和多节点?
先来说多节点吧,(参考网上通常的说法)当一个客户端进行写数据请求时,会指定ZooKeeper集群中的一个Server节点,如果该节点为Follower,则该节点会把写请求转发给Leader,Leader通过内部的协议进行原子广播,直到一半以上的server节点都成功写入数据,这次写请求便算是成功,然后Leader便会通过通知相应的Follower节点写请求成功,该节点向client返回写入成功.
本质上说还是把多节点写操作转换成了单节点的写操作,这样就可以在单节点进行并发控制了,效率更高.而在单节点做并发控制的话就方便的多了,通过PrepRequestProcessor->SyncRequestProcessor->FinalRequestProcessor->ZooKeeperServer->ZKDatabase->DataTree链路处理.有兴趣可以自己翻翻代码哦.
网友评论