zk中的文件快照

萝らか妹 提交于 2019-11-30 12:07:16

zk中的数据在内存中是DataTree为数据结构存储的

快照是间隔时间段将整个DataTree持久化

快照是备份版本,所以并不是最新数据

 

接口所在位置org.apache.zookeeper.server.persistence

**
 * snapshot interface for the persistence layer.
 * implement this interface for implementing
 * snapshots.
 */
public interface SnapShot {

    /**
     * 将数据反序列化
     * deserialize a data tree from the last valid snapshot and
     * return the last zxid that was deserialized
     * @param dt the datatree to be deserialized into
     * @param sessions the sessions to be deserialized into
     * @return the last zxid that was deserialized from the snapshot
     * @throws IOException
     */
    long deserialize(DataTree dt, Map<Long, Integer> sessions) throws IOException;

    /**
     * 持久化datatree 和会话
     * persist the datatree and the sessions into a persistence storage
     * @param dt the datatree to be serialized
     * @param sessions the session timeouts to be serialized
     * @param name the object name to store snapshot into
     * @param fsync sync the snapshot immediately after write
     * @throws IOException
     */
    void serialize(DataTree dt, Map<Long, Integer> sessions, File name, boolean fsync) throws IOException;

    /**
     * 查找最近的快照文件
     * find the most recent snapshot file
     * @return the most recent snapshot file
     * @throws IOException
     */
    File findMostRecentSnapshot() throws IOException;

    /**
     * 获取快照信息
     * get information of the last saved/restored snapshot
     * @return info of last snapshot
     */
    SnapshotInfo getLastSnapshotInfo();

    /**
     * 关闭资源
     * free resources from this snapshot immediately
     * @throws IOException
     */
    void close() throws IOException;

}

实现类

 

属性

File snapDir;
SnapshotInfo lastSnapshotInfo = null;
private volatile boolean close = false;
private static final int VERSION = 2;
private static final long dbId = -1;
private static final Logger LOG = LoggerFactory.getLogger(FileSnap.class);
public static final int SNAP_MAGIC = ByteBuffer.wrap("ZKSN".getBytes()).getInt();

public static final String SNAPSHOT_FILE_PREFIX = "snapshot";

方法

/**
 * deserialize a data tree from the most recent snapshot
 * @return the zxid of the snapshot
 */
public long deserialize(DataTree dt, Map<Long, Integer> sessions) throws IOException {
    // we run through 100 snapshots (not all of them)
    // if we cannot get it running within 100 snapshots
    // we should  give up
    List<File> snapList = findNValidSnapshots(100);
    if (snapList.size() == 0) {
        return -1L;
    }
    File snap = null;
    boolean foundValid = false;
    for (int i = 0, snapListSize = snapList.size(); i < snapListSize; i++) {
        snap = snapList.get(i);
        LOG.info("Reading snapshot " + snap);
        try (CheckedInputStream snapIS = SnapStream.getInputStream(snap)) {
            InputArchive ia = BinaryInputArchive.getArchive(snapIS);
            deserialize(dt, sessions, ia);
            SnapStream.checkSealIntegrity(snapIS, ia);
            if (dt.deserializeZxidDigest(ia)) {
                SnapStream.checkSealIntegrity(snapIS, ia);
            }

            foundValid = true;
            break;
        } catch (IOException e) {
            LOG.warn("problem reading snap file " + snap, e);
        }
    }
    if (!foundValid) {
        throw new IOException("Not able to find valid snapshots in " + snapDir);
    }
    dt.lastProcessedZxid = Util.getZxidFromName(snap.getName(), SNAPSHOT_FILE_PREFIX);
    lastSnapshotInfo = new SnapshotInfo(dt.lastProcessedZxid, snap.lastModified() / 1000);

    // compare the digest if this is not a fuzzy snapshot, we want to compare
    // and find inconsistent asap.
    if (dt.getDigestFromLoadedSnapshot() != null) {
        dt.compareSnapshotDigests(dt.lastProcessedZxid);
    }
    return dt.lastProcessedZxid;
}


/**
 * find the last (maybe) valid n snapshots. this does some
 * minor checks on the validity of the snapshots. It just
 * checks for / at the end of the snapshot. This does
 * not mean that the snapshot is truly valid but is
 * valid with a high probability. also, the most recent
 * will be first on the list.
 * @param n the number of most recent snapshots
 * @return the last n snapshots (the number might be
 * less than n in case enough snapshots are not available).
 * @throws IOException
 */
private List<File> findNValidSnapshots(int n) throws IOException {
    List<File> files = Util.sortDataDir(snapDir.listFiles(), SNAPSHOT_FILE_PREFIX, false);
    int count = 0;
    List<File> list = new ArrayList<File>();
    for (File f : files) {
        // we should catch the exceptions
        // from the valid snapshot and continue
        // until we find a valid one
        try {
            if (SnapStream.isValidSnapshot(f)) {
                list.add(f);
                count++;
                if (count == n) {
                    break;
                }
            }
        } catch (IOException e) {
            LOG.info("invalid snapshot " + f, e);
        }
    }
    return list;
}


/**
 * deserialize the datatree from an inputarchive
 * @param dt the datatree to be serialized into
 * @param sessions the sessions to be filled up
 * @param ia the input archive to restore from
 * @throws IOException
 */
public void deserialize(DataTree dt, Map<Long, Integer> sessions, InputArchive ia) throws IOException {
    FileHeader header = new FileHeader();
    header.deserialize(ia, "fileheader");
    if (header.getMagic() != SNAP_MAGIC) {
        throw new IOException("mismatching magic headers " + header.getMagic() + " !=  " + FileSnap.SNAP_MAGIC);
    }
    SerializeUtils.deserializeSnapshot(dt, ia, sessions);
}




序列化函数
/**
 * serialize the datatree and sessions
 * @param dt the datatree to be serialized
 * @param sessions the sessions to be serialized
 * @param oa the output archive to serialize into
 * @param header the header of this snapshot
 * @throws IOException
 */
protected void serialize(
    DataTree dt,
    Map<Long, Integer> sessions,
    OutputArchive oa,
    FileHeader header) throws IOException {
    // this is really a programmatic error and not something that can
    // happen at runtime
    if (header == null) {
        throw new IllegalStateException("Snapshot's not open for writing: uninitialized header");
    }
    header.serialize(oa, "fileheader");
    SerializeUtils.serializeSnapshot(dt, oa, sessions);
}


public static void serializeSnapshot(DataTree dt, OutputArchive oa, Map<Long, Integer> sessions) throws IOException {
    HashMap<Long, Integer> sessSnap = new HashMap<Long, Integer>(sessions);
    oa.writeInt(sessSnap.size(), "count");
    for (Entry<Long, Integer> entry : sessSnap.entrySet()) {
        oa.writeLong(entry.getKey().longValue(), "id");
        oa.writeInt(entry.getValue().intValue(), "timeout");
    }
    dt.serialize(oa, "tree");
}

快照和事务日志的区别?

快照什么时候会用到?

snapshot.打头的文件存储在哪里?

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!