设为首页 收藏本站
查看: 571|回复: 0

[经验分享] zookeeper 存储之文件格式分析

[复制链接]

尚未签到

发表于 2015-11-21 14:02:32 | 显示全部楼层 |阅读模式
zookeeper主要存放了两类文件,一个是snapshot和log,前者是内存数的快照,后者类似mysql的binlog,将所有与修改数据相关的操作记录在log中,

两类文件的目录可在配置文件中指定
下面通过几个典型的场景来分析两种文件的存储格式


snapshot文件格式


详见ZooKeeperServer.takeSnapshot,

列举1个简单的场景说明问题



场景 刚刚装了zookeeper,服务启动后会产生snapshot文件


00000000  5a 4b 53 4e 00 00 00 02  ff ff ff ff ff ff ff ff  |ZKSN............|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000020  ff ff ff ff ff ff ff ff  00 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000060  00 00 00 00 00 00 00 0a  2f 7a 6f 6f 6b 65 65 70  |......../zookeep|
00000070  65 72 00 00 00 00 ff ff  ff ff ff ff ff ff 00 00  |er..............|
00000080  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000000b0  00 00 00 00 00 00 00 00  00 00 00 00 00 10 2f 7a  |............../z|
000000c0  6f 6f 6b 65 65 70 65 72  2f 71 75 6f 74 61 00 00  |ookeeper/quota..|
000000d0  00 00 ff ff ff ff ff ff  ff ff 00 00 00 00 00 00  |................|
000000e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000110  00 00 00 00 00 00 00 00  00 01 2f 00 00 00 00 ab  |........../.....|
00000120  10 2b d2 00 00 00 01 2f                           |.+...../|
00000128


分成4个部分
a)header

  • magic:4个字节,“ZKSN”的int值  对应 0x 5a 4b 53 4e   【对应偏移地址0x 00000000---0x 00000003
  • version:4个字节,默认为2  对应 0x 00 00 00 02 【对应偏移地址0x 00000004---0x 00000007】
  • dbid:8个字节,默认为-1 对应 0x ff ff ff ff ff ff ff ff 【对应偏移地址0x 00000008---0x 0000000f】
b)data


  • count:session个数,4个字节 此时为0,如果不为0,会存放session的id和timeout,对应 0x 00 00 00 00 【对应偏移地址0x 00000010---0x 00000013】
  • 内存树:

    • map: acl 映射的个数 4个字节,此时为0 对应0x 00 00 00 00 【对应偏移地址0x 00000013---0x 00000017
    • 开始递归写node

      • 第一个node路径为""也即根节点

        • path

          • len: 4个字节 ,此时为0 对应 0x 00 00 00 00 【对应偏移地址0x 00000017---0x 0000001b

        • node

          • data

            • len: 4个字节,此时为0 ,对应 0x 00 00 00 00 【对应偏移地址0x 0000001c---0x 0000001f


          • acl: 8个字节,此时-1,对应 0x ff ff ff ff ff ff ff ff 【对应偏移地址0x 00000020---0x 00000027】


          • statpersisted: 状态存储

            • czxid : 8个字节,此时为0 ,对应 0x 00 00 00 00 00 00 00 00 【对应偏移地址0x 00000028---0x 0000002f
            • mzxid : 8个字节,此时为0 ,对应 0x 00 00 00 00 00 00 00 00 【对应偏移地址0x 00000030---0x 00000037】
            • ctime : 8个字节,此时为0 ,对应 0x 00 00 00 00 00 00 00 00 【对应偏移地址0x 00000038---0x 0000003f】
            • mtime : 8个字节,此时为0 ,对应 0x 00 00 00 00 00 00 00 00 【对应偏移地址0x 00000040---0x 00000047】
            • version : 4个字节,此时为0 ,对应 0x 00 00 00 【对应偏移地址0x 00000048---0x 0000004b】
            • cversion : 4个字节,此时为0 ,对应 0x 00 00 00  【对应偏移地址0x 0000004c---0x 0000004f】
            • aversion : 4个字节,此时为0 ,对应 0x 00 00 00 【对应偏移地址0x 00000050---0x 00000053】
            • ephemeralOwner : 8个字节,此时为0 ,对应 0x 00 00 00 00 00 00 00 00 【对应偏移地址0x 00000054---0x 0000005b】
            • pzxid : 8个字节,此时为0 ,对应 0x 00 00 00 00 00 00 00 00 【对应偏移地址0x 0000005c---0x 00000063】



      • 开始序列化第2个节点,即根节点的子节点(/zookeeper)


          • path

            • len: 4个字节 ,此时为/zookeeper的长度10对应 0x 00 00 00 0a 【对应偏移地址0x 00000064---0x 00000067
            • 内容: 10个字节 此时为“/zookeeper”的ascii表示 0x 2f 7a 6f 6f 6b 65 65 70 65 72  【对应偏移地址0x 00000068---0x 00000071



          • node: 此时和节点一样,下面的字节和根节点一样

            • data

              • len: 4个字节,此时为0 ,对应 0x 00 00 00 00 【对应偏移地址0x 00000072---0x 00000075


            • acl: 8个字节,此时-1,对应 0x ff ff ff ff ff ff ff ff 【对应偏移地址0x 00000076---0x 0000007d】


            • statpersisted: 状态存储

              • czxid : 8个字节,此时为0 ,对应 0x 00 00 00 00 00 00 00 00 【对应偏移地址0x 0000007e---0x 00000085
              • mzxid : 8个字节,此时为0 ,对应 0x 00 00 00 00 00 00 00 00 【对应偏移地址0x 00000086---0x 0000008d】
              • ctime : 8个字节,此时为0 ,对应 0x 00 00 00 00 00 00 00 00 【对应偏移地址0x 0000008e---0x 00000095】
              • mtime : 8个字节,此时为0 ,对应 0x 00 00 00 00 00 00 00 00 【对应偏移地址0x 00000096---0x 0000009d】
              • version : 4个字节,此时为0 ,对应 0x 00 00 00 【对应偏移地址0x 0000009e---0x 000000a1】
              • cversion : 4个字节,此时为0 ,对应 0x 00 00 00  【对应偏移地址0x 000000a2---0x 000000a5】
              • aversion : 4个字节,此时为0 ,对应 0x 00 00 00 【对应偏移地址0x 000000a6---0x 000000a9】
              • ephemeralOwner : 8个字节,此时为0 ,对应 0x 00 00 00 00 00 00 00 00 【对应偏移地址0x 000000aa---0x 000000b1】
              • pzxid : 8个字节,此时为0 ,对应 0x 00 00 00 00 00 00 00 00 【对应偏移地址0x 000000b2---0x 000000b9】





        • 开始序列化第3个节点(/zookeeper的子节点/zookeeper/quota

          • path

            • len: 16个字节 ,此时为/zookeeper/quota“的长度16, 对应 0x 00 00 00 10 【对应偏移地址0x 000000ba---0x 000000bd
            • 内容: 10个字节 此时为”/zookeeper/quota“的ascii表示0x 2f 7a 6f 6f 6b 65 65 70 65 72  2f 71 75 6f 74 61
              【对应偏移地址0x 000000be---0x 000000cd



          • node: 此时和根节点一样,下面的字节和根节点一样

            • data

              • len: 4个字节,此时为0 ,对应 0x 00 00 00 00 【对应偏移地址0x 000000ce---0x 000000d1


            • acl: 8个字节,此时-1,对应 0x ff ff ff ff ff ff ff ff 【对应偏移地址0x 000000d2---0x 000000d9】


            • statpersisted: 状态存储

              • czxid : 8个字节,此时为0 ,对应 0x 00 00 00 00 00 00 00 00 【对应偏移地址0x 000000da---0x 000000e1
              • mzxid : 8个字节,此时为0 ,对应 0x 00 00 00 00 00 00 00 00 【对应偏移地址0x 000000e2---0x 000000e9】
              • ctime : 8个字节,此时为0 ,对应 0x 00 00 00 00 00 00 00 00 【对应偏移地址0x 000000ea---0x 000000f1】
              • mtime : 8个字节,此时为0 ,对应 0x 00 00 00 00 00 00 00 00 【对应偏移地址0x 000000f2---0x 000000f9】
              • version : 4个字节,此时为0 ,对应 0x 00 00 00 【对应偏移地址0x 000000fa---0x 000000fd】
              • cversion : 4个字节,此时为0 ,对应 0x 00 00 00  【对应偏移地址0x 000000fe---0x 00000101】
              • aversion : 4个字节,此时为0 ,对应 0x 00 00 00 【对应偏移地址0x 00000102---0x 00000105】
              • ephemeralOwner : 8个字节,此时为0 ,对应 0x 00 00 00 00 00 00 00 00 【对应偏移地址0x 00000106---0x 0000010d】
              • pzxid : 8个字节,此时为0 ,对应 0x 00 00 00 00 00 00 00 00 【对应偏移地址0x 0000010e---0x 00000115】





    • 树的结尾以"/"结束

      • 共5个字节,前4个表示长度为1,后面是"/"的ascii码0x 2f ,总共是0x 00 00  00 01 2f 【对应偏移地址0x 00000116---0x 0000011a


c) 校验码
通过Adler32校验算法,对前面的字节得出的一个校验码,占8个字节  

0x 00 00 00 00 ab 10 2b d2 【对应偏移地址0x 0000011b---0x 00000122


d)结束符
和内存树一样以"/"为结束符
共5个字节,前4个表示长度为1,后面是"/"的ascii码0x 2f ,总共是0x 00 00 00 01 2f 【对应偏移地址0x 00000123---0x 00000127】



log文件格式
详见FileTxnLog.append

场景1) 启动一个客户端
此时会跟据当前事务的id,此时为1,产生log.1的文件

1) fileheader

  • magic:4个字节,“ZKLG”的int值  对应 0x 5a 4b 4c 47   【对应偏移地址0x 00000000---0x 00000003
  • version:4个字节,默认为2  对应 0x 00 00 00 02 【对应偏移地址0x 00000004---0x 00000007
  • dbid:8个字节,默认为0 对应 0x 00 00 00 00 00 00 00 00 【对应偏移地址0x 00000008---0x 0000000f
2)请求内容

  • txnEntryCRC(校验码,对于下面的txEntry

    • 采用和snapshot同样的算法Adler32得到的长整数8个字节 0x 00 00 00 00 59 27 08 06【对应偏移地址0x 00000010---0x 00000017

  • txEntry

    • 内容长度:4个字节  0x 00 00 00 24 【对应偏移地址0x 00000018---0x 000001b



    • hdr


    • clientId:长整数8个字节 0x 01 3a 69 4e 19 1a 00 00 【对应偏移地址0x 0000001c---0x 00000023
    • cxid:此时为整数0,4个字节  0x 00 00 00 00 【对应偏移地址0x 00000024---0x 00000027
    • zxid:此时为整数1,8个字节 0x 00 00 00 00 00 00 00 01 【对应偏移地址0x 00000028---0x 0000002f
    • time:整数8个字节 , 00 00 01 3a 69 4e ab af 【对应偏移地址0x 00000030---0x 00000037
    • type:操作码(码表见org.apache.zookeeper.ZooDefs.OpCode)此时为整数-10,4个字节  0x ff ff ff f6 【对应偏移地址0x 00000038---0x 0000003b


    • txn



      • timeOut:此时整数400000,4个字节  0x 00 06 1a 80【对应偏移地址0x 0000003c---0x 0000003f


  • EOR

    • 写入一个固定的字节作为结尾:0x 42 【对应偏移地址0x 00000040


      


此时为
1234567800000000  5a 4b 4c 47 00 00 00 02  00 00 00 00 00 00 00 00  |ZKLG............|00000010  00 00 00 00 59 27 08 06  00 00 00 24 01 3a 69 4e  |....Y'.....$.:iN|00000020  19 1a 00 00 00 00 00 00  00 00 00 00 00 00 00 01  |................|00000030  00 00 01 3a 69 4e ab af  ff ff ff f6 00 06 1a 80  |...:iN..........|00000040  42 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |B...............|00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|*04000010





场景2) 添加节点
zk.create("/root", "mydata".getBytes(), Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);


开始添加txnEntry

  • txnEntryCRC(校验码)

            采用和snapshot同样的算法Adler32得到的长整数8个字节,
           0x 00 00 00 00 ba 26 0c  5e  【对应偏移地址0x 00000041---0x 00000048



  • txnEntry

    • 内容长度:4个字节 , 0x 00 00 00 53 【对应偏移地址0x 00000049---0x 000004c



    • hdr:entry 头信息


    • clientId:此时为长整数,8个字节 0x 01 3a 69 4e 19 1a 00 00 【对应偏移地址0x 0000004d---0x 00000054
    • cxid:此时为整数2,4个字节, 0x 00 00 00  02 【对应偏移地址0x 00000055---0x 00000058
    • zxid:此时为整数2,8个字节,0x 00 00 00 00 00 00 00 02 【对应偏移地址0x 00000059---0x 00000060
    • time:此时为整数8个字节, 0x 00 00 01 3a 69 4f 3f  a5 【对应偏移地址0x 00000061---0x 00000068
    • type:此时为整数1,4个字节, 0x 00 00 00 01 【对应偏移地址0x 00000069---0x 0000006c


    • txn:   节点内容


    • path:此时为“/root”, 占用9个字节,前4个表示长度5,后5个为"/root"5个字符的ascii码, 0x 00 00 00 05 2f 72 6f 6f 74 【对应偏移地址0x 0000006d---0x 00000075
    • data:此时为"mydata"的字节数组,占用10个字节,前4个为长度6,后6个为"mydata"的字节数组,
          0x 00 00  00 06 6d 79 64 61 74 61  【对应偏移地址0x 00000076---0x 0000007f
    • 开始写acl信息

      • acl: acl长度,占用4个字节,此时长度为1, 0x 00 00 00 01 【对应偏移地址0x 00000080---0x 00000083
      • e1:一条acl具体信息

        • perms:4个字节,此时为整数31, 0x 00 00 00 1f 【对应偏移地址0x 00000084---0x 00000087
        • id

          • scheme:此时为字符串“world”,占用9个字节,前4个为长度5,后5个world5个字符的ascii码,
                   0x 00 00 00 05 77 6f 72 6c 64 【对应偏移地址0x 00000088---0x 00000090

          • id:此时为字符串“anyone”,占用10个字节,前4个为长度6,后6个anyone”6个字符的ascii码,
                   0x  00 00 00 06 61 6e 79  6f 6e 65 【对应偏移地址0x 00000091---0x 0000009a


    • ephemeral:此时为“false”,占用1个字节,如果true,写1,false写0 , 0x 00 【对应偏移地址0x 0000009b
    • parentCVersion:此时为整数1,占用4个字节,0x  00 00 00 01 【对应偏移地址0x 0000009c---0x 0000009f



  • EOR

    • 写入一个固定的字节作为结尾:0x 42 【对应偏移地址0x 000000a0




123456789101112131400000000  5a 4b 4c 47 00 00 00 02  00 00 00 00 00 00 00 00  |ZKLG............|00000010  00 00 00 00 59 27 08 06  00 00 00 24 01 3a 69 4e  |....Y'.....$.:iN|00000020  19 1a 00 00 00 00 00 00  00 00 00 00 00 00 00 01  |................|00000030  00 00 01 3a 69 4e ab af  ff ff ff f6 00 06 1a 80  |...:iN..........|00000040  42 00 00 00 00 ba 26 0c  5e 00 00 00 53 01 3a 69  |B.....&.^...S.:i|00000050  4e 19 1a 00 00 00 00 00  02 00 00 00 00 00 00 00  |N...............|00000060  02 00 00 01 3a 69 4f 3f  a5 00 00 00 01 00 00 00  |....:iO?........|00000070  05 2f 72 6f 6f 74 00 00  00 06 6d 79 64 61 74 61  |./root....mydata|00000080  00 00 00 01 00 00 00 1f  00 00 00 05 77 6f 72 6c  |............worl|00000090  64 00 00 00 06 61 6e 79  6f 6e 65 00 00 00 00 01  |d....anyone.....|000000a0  42 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |B...............|000000b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|*04000010

场景3)再添加一个节点
String realPath = zk.create("/root/childone",
"childone".getBytes(), Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);

123456789101112131415161718192000000000  5a 4b 4c 47 00 00 00 02  00 00 00 00 00 00 00 00  |ZKLG............|00000010  00 00 00 00 59 27 08 06  00 00 00 24 01 3a 69 4e  |....Y'.....$.:iN|00000020  19 1a 00 00 00 00 00 00  00 00 00 00 00 00 00 01  |................|00000030  00 00 01 3a 69 4e ab af  ff ff ff f6 00 06 1a 80  |...:iN..........|00000040  42 00 00 00 00 ba 26 0c  5e 00 00 00 53 01 3a 69  |B.....&.^...S.:i|00000050  4e 19 1a 00 00 00 00 00  02 00 00 00 00 00 00 00  |N...............|00000060  02 00 00 01 3a 69 4f 3f  a5 00 00 00 01 00 00 00  |....:iO?........|00000070  05 2f 72 6f 6f 74 00 00  00 06 6d 79 64 61 74 61  |./root....mydata|00000080  00 00 00 01 00 00 00 1f  00 00 00 05 77 6f 72 6c  |............worl|00000090  64 00 00 00 06 61 6e 79  6f 6e 65 00 00 00 00 01  |d....anyone.....|000000a0  42 00 00 00 00 bc 21 10  aa 00 00 00 5e 01 3a 69  |B.....!.....^.:i|000000b0  4e 19 1a 00 00 00 00 00  04 00 00 00 00 00 00 00  |N...............|000000c0  03 00 00 01 3a 69 6a 30  9c 00 00 00 01 00 00 00  |....:ij0........|000000d0  0e 2f 72 6f 6f 74 2f 63  68 69 6c 64 6f 6e 65 00  |./root/childone.|000000e0  00 00 08 63 68 69 6c 64  6f 6e 65 00 00 00 01 00  |...childone.....|000000f0  00 00 1f 00 00 00 05 77  6f 72 6c 64 00 00 00 06  |.......world....|00000100  61 6e 79 6f 6e 65 00 00  00 00 01 42 00 00 00 00  |anyone.....B....|00000110  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|*04000010这个也是产生节点,和上面类似,不再赘述,可以分析出来
字节范围从 000000a1---0000010b

此次的cxid为4,zxid为3,type还是1


场景4)修改节点数据

zk.setData("/root/childone", "childonemodify".getBytes(), -1);




123456789101112131415161718192021222324252600000000  5a 4b 4c 47 00 00 00 02  00 00 00 00 00 00 00 00  |ZKLG............|00000010  00 00 00 00 59 27 08 06  00 00 00 24 01 3a 69 4e  |....Y'.....$.:iN|00000020  19 1a 00 00 00 00 00 00  00 00 00 00 00 00 00 01  |................|00000030  00 00 01 3a 69 4e ab af  ff ff ff f6 00 06 1a 80  |...:iN..........|00000040  42 00 00 00 00 ba 26 0c  5e 00 00 00 53 01 3a 69  |B.....&.^...S.:i|00000050  4e 19 1a 00 00 00 00 00  02 00 00 00 00 00 00 00  |N...............|00000060  02 00 00 01 3a 69 4f 3f  a5 00 00 00 01 00 00 00  |....:iO?........|00000070  05 2f 72 6f 6f 74 00 00  00 06 6d 79 64 61 74 61  |./root....mydata|00000080  00 00 00 01 00 00 00 1f  00 00 00 05 77 6f 72 6c  |............worl|00000090  64 00 00 00 06 61 6e 79  6f 6e 65 00 00 00 00 01  |d....anyone.....|000000a0  42 00 00 00 00 bc 21 10  aa 00 00 00 5e 01 3a 69  |B.....!.....^.:i|000000b0  4e 19 1a 00 00 00 00 00  04 00 00 00 00 00 00 00  |N...............|000000c0  03 00 00 01 3a 69 6a 30  9c 00 00 00 01 00 00 00  |....:ij0........|000000d0  0e 2f 72 6f 6f 74 2f 63  68 69 6c 64 6f 6e 65 00  |./root/childone.|000000e0  00 00 08 63 68 69 6c 64  6f 6e 65 00 00 00 01 00  |...childone.....|000000f0  00 00 1f 00 00 00 05 77  6f 72 6c 64 00 00 00 06  |.......world....|00000100  61 6e 79 6f 6e 65 00 00  00 00 01 42 00 00 00 00  |anyone.....B....|00000110  af 4a 0f 23 00 00 00 48  01 3a 69 4e 19 1a 00 00  |.J.#...H.:iN....|00000120  00 00 00 07 00 00 00 00  00 00 00 04 00 00 01 3a  |...............:|00000130  69 74 8f f3 00 00 00 05  00 00 00 0e 2f 72 6f 6f  |it........../roo|00000140  74 2f 63 68 69 6c 64 6f  6e 65 00 00 00 0e 63 68  |t/childone....ch|00000150  69 6c 64 6f 6e 65 6d 6f  64 69 66 79 00 00 00 01  |ildonemodify....|00000160  42 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |B...............|00000170  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|*04000010这个也是修改节点,和上面类似,不再赘述,可以分析出来
字节范围从 0000010c---00000160


此次的cxid为7,zxid为4,type还是5(从org.apache.zookeeper.ZooDefs.OpCode看到5就是setData)






运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-141855-1-1.html 上篇帖子: 基于zookeeper3.4.6的源码研究(二) 下篇帖子: zookeeper watch
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表