ZK EphemeralOwner
ZK的EphemeralOwner如果有的话说明是临时节点
那么你有了解过EphemeralOwner值代表什么吗?
Stat
Czxid21757311074 节点创建时的事务id
Mzxid21757311074 最近一次修改的事务id
Pzxid21757311074 子节点删除或添加的znode的事务id,如果没有子节点,就是本身节点的czxid
Version0
Cversion0 对节点的子节点的创建、删除次数
Aversion0 aclVersion acl权限修改次数
NumChildren0 第一层子节点个数
EphemeralOwner 178880420134350789 临时节点所属实例的sessionId
Ctime2022-03-08 19:17:15 创建时间
Mtime2022-03-08 19:17:15 修改时间
DataLength1293 znode数据字段的长度
可以看到EphemeralOwner 是一个long值
public static long initializeNextSession(long id) {
long nextSid = 0;
nextSid = (Time.currentElapsedTime() << 24) >>> 8;
nextSid = nextSid | (id <<56);
return nextSid;
}
传入的id是sid,也就是节点的myid
后续的客户端sessionId都是在这个值上递增的,那费不费出现重复?
是这样的
其实就短短四行代码,通过位运算移动来操作的数据的
可以大概分析一下, Time.currentElapsedTime返回的就是一个long类型的毫秒数,一个long类型时64位
比如当前时间转成64位之后
当前时间为2020-08-09 11:20:20 转成毫秒数之后时 1596943220000,转成64位的long类型如下
0000 0000 0000 0000 0000 0001 0111 0011 1101 0001 0011 1011 1011 1101 0010 0000
向左移动24位
0111 0011 1101 0001 0011 1011 1011 1101 0010 0000 0000 0000 0000 0000 0000 0000
然后向右移动8位,此时为 nextSid
0000 0000 0111 0011 1101 0001 0011 1011 1011 1101 0010 0000 0000 0000 0000 0000
接下来是 id << 56
id是我们自己设置的myid,一般都是一个比较小的数字,1、2、3、4等等这样的,一个集群有5态机器,一般都是1、2、3、4、5
如果此时id = 5 转成二进制
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0101
向左移动56位,得到数据
0000 0101 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
然后和nextSid做或操作,或操作是 有1得1,没有1得0,即
0000 0000 0111 0011 1101 0001 0011 1011 1011 1101 0010 0000 0000 0000 0000 0000
0000 0101 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
得到
0000 0101 0111 0011 1101 0001 0011 1011 1011 1101 0010 0000 0000 0000 0000 0000
为何要这么做呢?
打个比方,如果sessionId只是根据当前服务器的时间来生成,那么如果zk集群中得多台机器同时去了相同得时间呢?所以如果不把myid加入运算就会出现sessionId不唯一性
那么上面得运算就可以得到一个唯一得数字,首先
(Time.currentElapsedTime() << 24) >>> 8
这一行数据就是把最高得8位转成0,而一般myid比较小,然后nextSid | (id <<56) 时得到得就是低位56位是当前时间戳,高8位就是myid,此时得到得数据肯定是一个唯一得值,把当前时间戳和myid都参与到位运算当中去
以上就是生成sessionId得策略,sessionId是在客户端和zk集群中得某一个zk建立连接时生成的