2.zookeeper原理解析-数据存储之Snapshot

=====================================斩秋|http://blog.youkuaiyun.com/quhongwei_zhanqiu=======================================

Snapshot是datatree在内存中某一时刻的影像,zookeeper有一定的机制会定时生成datatree的snapshot。FileSnap实现了SnapShot接口负责将数据写入文件中,下面我们来看看snap相关内容。

2.1 snapshot文件格式

   Snapshot是以二进制形式存在在文件的,我们用ue打开一个新的snapshot文件


Snapshot文件的中数据大体可以分为两部分header和body。


Header数据格式:

FileHeader{

   int    magic  //魔数   常量ZKSN  代表zookeeper snapshot文件

   int    version  //版本  常量 2

   long   dbid   //dbid  常量 -1

}

这里很奇怪 version和dbid都是常量,那还有什么意思,也许是保留字段为后续版本使用。

由头部字段可以计算出头部信息占用 4 + 4 + 8 =16bit的固定长度

5A 4B 53 4E 就是魔术ZKSN

00 00 00 02 就是dbid号2

FF FF FF FF FF FF FF FF就是十六进制的-1


Body数据格式:

Snapshot文件中头部信息之后,紧接着就是body部分的信息,body数据大小是动态不是固定。

1) Map<Long, Integer> sessionWithTimeoutbody信息前面部分存储的是内存中活着的session以及session的超时时间

oa.writeInt(sessSnap.size(),"count");

        for (Entry<Long, Integer> entry :sessSnap.entrySet()) {

           oa.writeLong(entry.getKey().longValue(), "id");

            oa.writeInt(entry.getValue().intValue(),"timeout");

        }

由上面序列到文件代码可以看出先写入一个int类型字段用来存储sessionWithTimeout的个数,然后在遍历集合以一个long一个int的形式写入

2) 紧接着就是对datatree序列化到文件了

我们看下datatree的序列化方法

public voidserialize(OutputArchive oa, String tag) throws IOException {

        scount = 0;

        serializeList(longKeyMap, oa);

        serializeNode(oa, newStringBuilder(""));

        if (root != null) {

            oa.writeString("/","path");

        }

    }

2.1)序列化longKeyMap是存储在datatree中的acl权限集合

           readInt("map") //acl的映射个数?

        while (map > 0) {

             readLong("long") //这个long值longKeyMap的key,作用?是这一组acl的key

         readInt("acls")

         while (acls) {

               readInt("perms")

           readString("scheme")  

           readString("id")

           }

     }

 

2.2)存储datatree中数据节点

        readString("path")//第一个datanode ""

    while(!path.equals("/")) {   //  "/"代表路径结束       

           readRecord(node, "node")包括:

           readBuffer("data")

           readLong("acl")

           deserialize(archive,"statpersisted") 状态存储包括:

                          readLong("czxid")  //createNode时事务号

                            readLong("mzxid")  //createNode时与Czxid同,setData时的事务号

                            readLong("ctime")  // 创建节点时间

                            readLong("mtime")  //createNode时与ctime相同,setData时间

                            readInt("version")  //createNode版本为0,setData的数据版本号

                            readInt("cversion") //createNode版本为0,增加/删除子节点时父节点+1

                            readInt("aversion") //createNode版本为0,setACL时节点的版本号

                            readLong("ephemeralOwner") // 临时节点表示sessionid,非临时节点这个值为0

                            readLong("pzxid")  //createNode时与Czxid同,增加/删除子节点时为子节点事务号

 

        readString("path") //读取下一个路径

  }

3)  文件尾部校验数据

00 00 00 01 2F  snapshot文件结尾5位数据用来校验snapshot文件是否有效

   00 00 00 01一个int的数值就是数字1,代表后面1一个字符数据

   2F 就是snapshot的结束符/

 

4)Snapshot序列化

 


5)Snapshot反序列化



=====================================斩秋|http://blog.youkuaiyun.com/quhongwei_zhanqiu=======================================

<think>我们正在分一个Maven项目(com.shdky:mrs-measure-listener)的依赖树,特别是关于ZooKeeper的依赖以及可能存在的重复依赖问题。用户之前提到了audience-annotations的依赖问题,现在可能是在类似背景下出现的ZooKeeper依赖问题。 步骤: 1. 生成依赖树:使用`mvn dependency:tree`命令,并可以配合`-Dincludes`参数来过滤出我们关心的依赖(如ZooKeeper相关的依赖和可能冲突的依赖)。 2.依赖树:查看ZooKeeper的版本,以及是否有多个不同的版本被引入(即重复依赖),同时注意传递依赖带来的冲突。 3. 解决冲突:如果存在多个版本,需要确定保留哪个版本(通常选择较新的稳定版本),并通过依赖管理(dependencyManagement)或排除(exclusion)来解决。 假设用户已经遇到了类似之前audience-annotations的冲突问题,现在在ZooKeeper上也可能出现。 具体操作: 1. 生成依赖树命令(在项目根目录下执行): ``` mvn dependency:tree -Dverbose -Dincludes=org.apache.zookeeper:*,*:zookeeper ``` 或者更精确地指定groupId和artifactId(如果知道): ``` mvn dependency:tree -Dverbose -Dincludes=org.apache.zookeeper:zookeeper ``` 使用`-Dverbose`参数可以显示所有冲突的依赖(即被忽略的依赖也会显示)。 2.依赖树输出: 在输出中,我们会看到以树形结构展示的依赖关系。重点关注: - 直接依赖和传递依赖中引入的ZooKeeper版本。 - 是否有多个版本出现?如果有,Maven会根据依赖调解规则(最近路径优先,第一声明优先)选择一个版本,而其他版本会被忽略(但在verbose模式下会显示为omitted for conflict)。 3. 解决冲突: 如果存在多个版本,我们可以在项目的pom.xml中通过以下方式解决: a. 使用`<dependencyManagement>`统一管理版本。 b. 在直接引入ZooKeeper的依赖中明确指定版本(如果项目直接依赖了ZooKeeper)。 c. 排除传递依赖中的旧版本。 示例:假设依赖树显示有两个版本的ZooKeeper:3.4.14和3.6.3,而3.4.14是通过某个传递依赖引入的旧版本,我们希望使用3.6.3。 方法一:在dependencyManagement中指定版本(推荐,尤其对于多模块项目): ```xml <dependencyManagement> <dependencies> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.6.3</version> </dependency> </dependencies> </dependencyManagement> ``` 方法二:排除旧版本的传递依赖: ```xml <dependency> <groupId>some.group</groupId> <artifactId>some-artifact</artifactId> <version>X.Y.Z</version> <exclusions> <exclusion> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> </exclusion> </exclusions> </dependency> ``` 4. 验证:再次运行依赖树命令,确认现在只有一个版本的ZooKeeper被使用。 另外,用户可能还关心其他重复依赖(比如之前遇到的audience-annotations)是否也被解决。我们可以用类似的方法处理。 注意:如果项目使用了Spring Boot,它可能通过parent POM或dependency management已经管理了ZooKeeper的版本。此时,我们应该检查Spring Boot的版本和它管理的ZooKeeper版本,尽量保持一致。 如果用户没有提供具体的依赖树输出,我们可以给出一个示例分: 假设依赖树输出片段如下: ``` [INFO] com.shdky:mrs-measure-listener:jar:1.0.0 [INFO] +- org.springframework.boot:spring-boot-starter:jar:2.5.6 (compile) [INFO] | \- ... [INFO] +- org.apache.zookeeper:zookeeper:jar:3.6.3 (compile) [INFO] | \- ... (传递依赖) [INFO] \- com.some.dependency:some-artifact:jar:1.0.0 (compile) [INFO] \- org.apache.zookeeper:zookeeper:jar:3.4.14 (compile) ``` 这里,我们直接依赖了3.6.3,但是通过some-artifact传递依赖了3.4.14。由于3.6.3在依赖树中更靠近根节点(路径更短)或者声明更早,Maven会选择3.6.3。但是,为了明确和避免潜在的冲突,我们可以排除some-artifact中的zookeeper依赖。 在pom.xml中: ```xml <dependency> <groupId>com.some.dependency</groupId> <artifactId>some-artifact</artifactId> <version>1.0.0</version> <exclusions> <exclusion> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> </exclusion> </exclusions> </dependency> ``` 这样,依赖树中就只有一个版本的zookeeper(3.6.3)了。 如果用户的项目中出现了其他重复依赖,也可以用同样的方法处理。 最后,建议用户运行`mvn clean install`验证构建是否成功,以及运行时是否出现类冲突(如NoClassDefFoundError, NoSuchMethodError等)。 由于用户之前提到过audience-annotations的问题,这里也需要注意,ZooKeeper本身可能依赖了audience-annotations,所以如果之前已经统一了audience-annotations的版本,那么这里应该已经一致了。如果不一致,同样需要在dependencyManagement中统一。 下面,我将按照用户要求,生成一个关于Maven依赖树分的相关问题列表。</think>### Maven依赖树分:`com.shdky:mrs-measure-listener`的ZooKeeper与重复依赖问题 #### 1. **生成依赖树** 执行命令获取完整依赖树: ```bash mvn dependency:tree -Dverbose -Dincludes=org.apache.zookeeper:*,*:zookeeper ``` `-Dverbose`参数显示冲突依赖,`-Dincludes`过滤ZooKeeper相关依赖。 #### 2. **典型问题场景分** ##### 场景1:多版本ZooKeeper冲突 ```text [INFO] com.shdky:mrs-measure-listener:jar:1.0.0 [INFO] +- org.apache.curator:curator-framework:jar:5.3.0 (compile) [INFO] | \- org.apache.zookeeper:zookeeper:jar:3.7.1 (compile) [INFO] \- com.alibaba.dubbo:dubbo-registry-zookeeper:jar:2.7.15 (compile) [INFO] \- org.apache.zookeeper:zookeeper:jar:3.4.14 (compile, omitted for conflict with 3.7.1) ``` **问题**: - Curator引入ZooKeeper 3.7.1 - Dubbo引入ZooKeeper 3.4.14(被Maven忽略) **风险**: 低版本功能缺失(如ACL权限控制) API不兼容导致`NoSuchMethodError`[^1] ##### 场景2:传递依赖重复 ```text [INFO] +- org.apache.hbase:hbase-client:jar:2.4.9 (compile) [INFO] | \- org.apache.zookeeper:zookeeper:jar:3.4.14 (compile) [INFO] \- org.apache.kafka:kafka-clients:jar:3.2.1 (compile) [INFO] \- org.apache.zookeeper:zookeeper:jar:3.8.0 (compile) ``` **问题**: 三个不同版本的ZooKeeper共存(3.4.14, 3.7.1, 3.8.0) #### 3. **解决方案** ##### 步骤1:统一版本(推荐) ```xml <dependencyManagement> <dependencies> <!-- 统一使用ZooKeeper最新稳定版 --> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.8.0</version> </dependency> <!-- 解决相关依赖冲突 --> <dependency> <groupId>org.apache.yetus</groupId> <artifactId>audience-annotations</artifactId> <version>0.12.0</version> </dependency> </dependencies> </dependencyManagement> ``` ##### 步骤2:排除旧版本 ```xml <dependency> <groupId>com.alibaba.dubbo</groupId> <artifactId>dubbo-registry-zookeeper</artifactId> <version>2.7.15</version> <exclusions> <exclusion> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> </exclusion> </exclusions> </dependency> ``` #### 4. **验证结果** ```bash # 验证依赖树 mvn dependency:tree -Dincludes=org.apache.zookeeper:* # 预期输出 [INFO] org.apache.zookeeper:zookeeper:jar:3.8.0 (compile) ``` #### 5. **冲突检测工具** ```xml <!-- 添加maven-enforcer-plugin --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <version>3.3.0</version> <executions> <execution> <id>enforce</id> <goals><goal>enforce</goal></goals> <configuration> <rules> <dependencyConvergence/> <banDuplicateClasses> <ignoreClasses> <ignoreClass>org.slf4j.*</ignoreClass> </ignoreClasses> </banDuplicateClasses> </rules> </configuration> </execution> </executions> </plugin> ``` 此插件将阻止构建并报告: - 版本冲突(dependencyConvergence) - 重复类文件(banDuplicateClasses) --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值