Lucene 如何热备份

参考http://www.manning.com/hatcher3

或者看《Lucene in action》第二版中关于Hot backup部分,也可以直接采用下面的代码。

为什么要热备份

  1. Lucene对索引是没有保证的(说的有点别扭原文用词是guarantee),意思是因为各种原因导致的索引破坏,这个真的不能怪它,倒排索引使用了大量类似指针链的方式来记录数据,所以部分的损坏就会导致整个完蛋。当然这不是说它就不可靠了,os也有crash的时候,大多数时候还是非常稳定的;
  2. 索引备份采用最多的当然是拷贝,可是在IndexWriter打开的情况下索引文件是不稳定实时变化的,所以必须在IndexWriter关闭的情况下才能拷贝。对于一个在线的网站来说这个是不能忍受的,特别是对于数据量比较大的站点,拷贝可能需要很长时间;
  3. 倒排索引之所以快是因为花费了大量时间先做分词,所以当索引crash后变成了不可再利用的垃圾,最好的办法也是官方推荐的办法就是重建,为了不让用户等待太久,最好的当然是从一个现有的最近的备份来恢复更新;
  4. 很多站点不允许停止搜索服务去备份,咱也不愿意大半夜去备份不是;

热备份

最理想的方式就是能always online的前提下备份,于是在2.3版本中引入了SnapshotDeletionPolicy,它的原理就是lucene可以保留一个commit了,这个commit就是snapshot,我觉得这是个很牛比的东西,就跟数据库的snapshot一样,不是谁都能轻轻松松做出来的,下面是实现新建一个保留最后一次提交策略的IndexWriter。

新建一个支持Sanpshot的writer
  1. IndexDeletionPolicy policy = new KeepOnlyLastCommitDeletionPolicy();
  2. SnapshotDeletionPolicy snapshotter = new SnapshotDeletionPolicy(policy);
  3. IndexWriter writer = new IndexWriter(dir, analyzer, snapshotter,
  4. IndexWriter.MaxFieldLength.UNLIMITED);

下面是需要热备份时调用的代码

备份的代码
  1. try {
  2. IndexCommit commit = snapshotter.snapshot();
  3. Collection<String> fileNames = commit.getFileNames();
  4. /*<iterate over & copy files from fileNames>*/
  5. } finally {
  6. snapshotter.release();
  7. }

使用热备份需要注意的地方

  1. snapshotter每次备份完要release(),不然writer不会删除这个commit;
  2. 如果你有多个writer,那么自求多福吧,我一直认为多个w是自己抽自己的行为;
  3. 每次getFileNames()出来可以做一个比较,因为lucene是一次写入的,意思是尽量重用已经写入的数据,所以只要文件名相同不需要hash检查可以武断的认为他们的数据是一样的,更新的时候可以删除没有在这个list的文件,segment是每次都会被重写的,这个谁都知道;
  4. 使用热备份肯定会比原来多出很多文件,占用空间增加也是正常的,所以要留好足够的空间;
  5. 有经常开关writer的同学要注意,在section2代码中拷贝时不能关闭writer,如果你一定要这么干,可以写一个保留当前commit的策略,当然同时还会带来其它问题;
原文地址:https://www.cnblogs.com/jinzhao/p/2859715.html