十多年来,NAS中已经存在的目录和文件达到10亿之多,在设计和开发备份系统的过程中碰到了很多挑战,本文将分享大量文件名记录的树形结构存储实践。
一、引言
既然是定期备份,肯定会有1次以上的备份。对于一个特定目录,每次备份时都要与上次备份时进行比较,以期找出哪些文件被删除了,又新增了哪些文件,这就需要每次备份时把该目录下的所有文件名进行保存。我们首先想到的是把所有文件名用特定字符进行拼接后保存。由于我们使用了MySQL保存这些信息,当目录下文件很多时,这种拼接的方式很可能超出MySQL的Blob长度限制。根据经验,当一个目录有大量文件时,这些文件的名称往往是程序生成的,有一定规律的,而且开头一般是重复的,于是我们想到了使用一种树形结构来进行存储。
例如,一个有abc、abc1、ad、cde 4个文件的目录对应的树如图1所示。
图1 树形结构示例
图1中,R表示根节点,青色节点我们称为结束节点,从R到每个结束节点的路径都表示一个文件名。可以在树中查找是否含有某个文件名、遍历树中所有的文件名、对树序列化进行保存、由序列化结果反序列化重新生成树。
二、涉及的数据结构
注意:我们使用java编写,文中涉及语言特性相关的知识点都是指java。
2.1 Node的结构
包括根节点在内的每个节点都使用Node类来表示。代码如下:
class Node {
private char value;
private Node[]children = new Node[0];
private byte end = 0;
}
字段说明:
- value:该节点表示的字符,当Node表示根节点时,value无值。
- children:该节点的所有子节点,初始化为长度为0的数组。
- end:标记节点是否是结束节点。0不是;1是。叶子节点肯定是结束节点。默认非结束节点。
2.2 Node的操作
public Node(char v);
public Node findChild(char v);
public Node addChild(char v);
操作说明:
- Node:构造方法。将参数v赋值给this.value。
- findChild:查找ch