• Zookeeper原理分析之存储结构TxnLog


    Zookeeper事物日志文件用于记录事物操作,如添加,删除节点等等,都会在事务日志中记录一条记录。下面我们就详细分析一下txnLog事务日志文件。

    txnLog事务日志文件文件由三部分组成:

    • 日志文件头FileHeader
    • TxnList代表记录记录集合
    • ZeroPad文件尾部

    FileHeader

    public class FileHeader implements Record {
      private int magic;//(ZKLG) 常量代表文件魔数
      private int version;//常量2 
      private long dbid;//常量,默认0
    }
    

    头文件是固定长度 16 = 4 + 4 + 8数据,它的值也固定。

    TxnList

    TxnList代表记录记录集合,txn代表一条记录,把一条txn添加到日志文件代码如下:

    	//序列化TxnHeader Record记录到byte[]
        byte[] buf = Util.marshallTxnEntry(hdr, txn);
        if (buf == null || buf.length == 0) {
            throw new IOException("Faulty serialization for header " +
                    "and txn");
        }
        Checksum crc = makeChecksumAlgorithm();
    	//根据指定数组更新校验值
        crc.update(buf, 0, buf.length);
        oa.writeLong(crc.getValue(), "txnEntryCRC");
    	 //将TxnHeader Record数据写入到输出流
       //1.先计算buf数据长度写入
       //2.写入buf数组数据
       //3.记录尾部以’B’字符结尾,写入0x42
        Util.writeTxnBytes(oa, buf);
    

    checksum校验位计算,是由Adler32校验算法计算TxnHeader Record序列化后的字节码.TxnHeader的定义如下:

    public class TxnHeader implements Record {
      private long clientId;
      private int cxid;// 与客户端交互的xid
      private long zxid;// 服务器端生成的事务id
      private long time;
      private int type;  // 事务操作的类型
    }
    

    Record:事务记录的内容,由jute规范定义了序列化反序列化流程,各个事务操作都实现了Record接口,下面看下创建的事务操作记录

    public class CreateTxn implements Record {
      private String path;//创建路径
      private byte[] data;//节点数据内容
      private java.util.List<org.apache.zookeeper.data.ACL> acl;//节点权限
      private boolean ephemeral; //是否临时节点
      private int parentCVersion;//父节点的版本号
      //序列化过程
    
    	public void serialize(OutputArchive a_, String tag) throws java.io.IOException {
        a_.startRecord(this,tag);
        a_.writeString(path,"path");
        a_.writeBuffer(data,"data");
        {
          a_.startVector(acl,"acl");
          if (acl!= null) {          int len1 = acl.size();
              for(int vidx1 = 0; vidx1<len1; vidx1++) {
                org.apache.zookeeper.data.ACL e1 = (org.apache.zookeeper.data.ACL) acl.get(vidx1);
        a_.writeRecord(e1,"e1");
              }
          }
          a_.endVector(acl,"acl");
        }
        a_.writeBool(ephemeral,"ephemeral");
        a_.writeInt(parentCVersion,"parentCVersion");
        a_.endRecord(this,tag);
      }
     //反序列化过程
     public void deserialize(InputArchive a_, String tag) throws java.io.IOException {
        a_.startRecord(tag);
        path=a_.readString("path");
        data=a_.readBuffer("data");
        {
          Index vidx1 = a_.startVector("acl");
          if (vidx1!= null) {          acl=new java.util.ArrayList<org.apache.zookeeper.data.ACL>();
              for (; !vidx1.done(); vidx1.incr()) {
        org.apache.zookeeper.data.ACL e1;
        e1= new org.apache.zookeeper.data.ACL();
        a_.readRecord(e1,"e1");
                acl.add(e1);
              }
          }
        a_.endVector("acl");
        }
        ephemeral=a_.readBool("ephemeral");
        parentCVersion=a_.readInt("parentCVersion");
        a_.endRecord(tag);
    }
    

    每条事务记录尾部以’B’字符结尾就是0x42

    ZeroPad文件尾部

    每个文件尾部都用一个字符 0 填充, 工具Util.padLogFile扩充文件的时候在尾部填写上

        public static long padLogFile(FileOutputStream f,long currentSize,
                long preAllocSize) throws IOException{
            long position = f.getChannel().position();
            if (position + 4096 >= currentSize) {
                currentSize = currentSize + preAllocSize;
                fill.position(0);
                f.getChannel().write(fill, currentSize-fill.remaining());
            }
            return currentSize;
        }
    
  • 相关阅读:
    JAVA程序员面试32问
    在做物流的库存管理系统里,需要注意。。。。。
    在写自动更新程序中出现的问题
    数据库设计中的五个范式
    cPickle / pickle
    python总结1
    python总结2
    汉明距离(Hamming distance)
    python中pickle的用法
    NET面试题
  • 原文地址:https://www.cnblogs.com/senlinyang/p/8408906.html
Copyright © 2020-2023  润新知