深入浅出 jackrabbit 九 索引合并(下)
2009-09-17 00:00:00 来源:WEB开发网由此可见,IndexInfos确实有把新添加的PersistentIndex对应的目录持久化起来,什么时候做这件事情呢,当然是在添加索引介绍的时候,比如说flush的时候,没错,就是前面讲到的multiIndex#update中的三大方法中的flush(记住它的触发条件哦),flush的时候,内存中的有效的索引目录的信息就会被持久化到磁盘上。
同样的道理,deletable中也是这样的逻辑,要删除的目录也会被持久化起来。
既然保存下来了,我们不妨看看什么时候会用到,于是乎查看read方法:
Java代码
void read(File dir) throws IOException {
InputStream in = new FileInputStream(new File(dir, name));
try {
DataInputStream di = new DataInputStream(in);
counter = di.readInt();
for (int i = di.readInt(); i > 0; i--) {
String indexName = di.readUTF();
indexes.add(indexName);
names.add(indexName);
}
} finally {
in.close();
}
}
果不其然,有这么一个read方法,这个方法就是负责解析文件,并把文件中的数据拿出来放到内存中。那么这个方法是谁来调用的呢:ctrl+shift+g.
发现在MultiIndex的构造方法里确实用到了:
Java代码
MultiIndex(File indexDir,
SearchIndex handler,
Set excludedIDs,
NamespaceMappings mapping) throws IOException {
this.indexDir = indexDir;
this.handler = handler;
this.cache = new DocNumberCache(handler.getCacheSize());
this.redoLog = new RedoLog(new File(indexDir, REDO_LOG));
this.excludedIDs = new HashSet(excludedIDs);
this.nsMappings = mapping;
if (indexNames.exists(indexDir)) {
/*读取有效的目录*/
indexNames.read(indexDir);
}
if (deletable.exists(indexDir)) {
/*读取无效的目录信息*/
deletable.read(indexDir);
}
// try to remove deletable files if there are any
/*删除之*/
attemptDelete();
……….
}
通过这种方式,jackrabbit就可以保证在程序在不执行添加索引,或者索引合并(因为这两个操作中都有AddIndex和DeleteIndex被执行,也就是说这个两个操作都会导致目录变更)的时候突然拓机的情况下,程序重启还能正常提供服务。
如果程序正在执行merge操作,产生了新目录,需要删除老的目录,这个时候情况比较麻烦:
1在这两个信息没有被持久化到磁盘上之前程序歇菜了,那可能还好办,毕竟原始的数据还在磁盘上,不过产生的新目录不能被读取到,因为不在indexes文件里。
2但是indexNames持久化成功,deletable持久化失败,那就没有办法了,这样就会导致这些个需要删除的目录信息不存在于 deletable中,而新的有效目录也存在于indexNames中,那么程序重启的时候能读到这个目录,但是不知道哪些目录需要被删除。
在这样的场景下会产生一些冗余目录和冗余文件,但是不影响正常数据,后面会讲到redolog和indexes的关系,很重要,是保证数据完整性的重要一步。
总结
真相如此简单,但是却不得不考虑,由此证明,写代码,写框架,尤其数据库之类的东西,重要的是逻辑的严谨性,最重要的还是逻辑的严谨性,如同设计模式这类的东西只是辅助技巧,切不可舍本求末,亦不可舍主求次。主次分明才是最好的平衡。
Tags:深入浅出 jackrabbit 索引
编辑录入:爽爽 [复制链接] [打 印]更多精彩
赞助商链接