事务性Lucene

许多用户不喜欢Lucene API的事务性语义,以及这在搜索应用程序中如何有用。 首先,Lucene实现了ACID属性:

  • 一个 tomicity:当您在更改(添加,删除文件) IndexWriter会话,然后提交,要么全部(如果提交成功)或无的更改(如果提交失败)将是可见的,从来没有的东西在两者之间。 某些方法具有其自己的原子行为:如果调用updateDocument ,该方法实现为在删除之后添加的实现,即使打开了近实时(NRT)阅读器或从单独的线程提交。 同样,如果使用相对较新的 addDocuments方法添加文档块,则在获得的任何阅读器中都不会看到任何文档或全部文档。
  • Çonsistency:如果计算机或操作系统崩溃,或JVM崩溃或被杀,或断电,你的指数将保持不变(即,未破坏)。 请注意,其他问题(例如RAM损坏,CPU翻转或文件系统损坏)仍然很容易损坏索引!
  • 我这样想 :在IndexWriter进行更改时,任何搜索索引的IndexReader都不可见,直到您提交或打开新的NRT阅读器。 一次仅一个IndexWriter实例可以更改索引。
  • d urability:一旦commit的回报,所有的改变都被写入持久性存储器(假设你的I / O系统正确实现fsync )。 如果计算机或操作系统崩溃,或者JVM崩溃或被杀死,或者计算机断电,则所有更改仍将存在于索引中。

Lucene提供了两阶段的提交 API:调用prepareCommit方法来完成所有艰苦的工作(应用缓冲的删除,编写缓冲的文档,fsync文件)。 如果出现问题(例如磁盘已满),几乎肯定会在第一阶段发生。 然后,调用commit完成事务。

当您关闭IndexWriter ,它commitIndexWriter调用commit 。 相反,如果您想放弃自上次提交以来的所有更改,请调用rollback方法,该方法也将关闭编写器。 您甚至可以回滚CREATE :如果您已有索引,并使用OpenMode.CREATE在其上打开IndexWriter ,然后回滚,则索引将保持不变。 同样,如果调用deleteAll然后回滚。

注意,仅在新目录上打开IndexWriter并不会创建空提交。 也就是说,您必须先调用commit才能在目录上打开IndexReader

Lucene本身并没有实现事务日志 ,但是很容易在顶层构建该层。 例如,流行的搜索服务器(例如SolrElasticSearch )就是这样做的。

在一个索引中多次提交

一个Lucene索引可以自由包含多个提交; 这是一个功能强大但经常被忽略的功能。 每个提交都拥有创建提交时所存在的索引的时间点视图。

这类似于ZFS和新兴的Btrfs等现代文件系统中可用的快照和可写克隆。 实际上,Lucene能够基于相同的根本原因有效地公开多个提交:所有索引段和文件都是一次写入的,就像ZFS和Btrfs中的文件块一样。

要在索引中保存多个提交,只需实现自己的IndexDeletionPolicy并将其传递给IndexWriter 。 这是Lucene用来了解应删除哪些提交的类: IndexWriter在打开索引时以及每次提交成功时都会调用它。 默认策略KeepOnlyLastCommitDeletionPolicy删除除最后一次提交以外的所有内容。 如果您使用NoDeletionPolicy则将保留每次提交!

您可以将userDataMap<String,String> )传递给commit ,以记录有关该提交的自定义信息(对Lucene不透明),然后使用IndexReader.listCommits在索引中查找所有提交。 找到提交后,您可以在其上打开IndexReader来搜索该提交时的索引。

您还可以在先前的提交上打开IndexWriter ,以有效地回滚之后的所有更改:这与rollback方法一样,不同之处在于它使您可以提交进行回滚,而不仅仅是在当前IndexWriter会话中进行的更改。

即使使用OpenMode.CREATE打开索引,旧提交仍将保留。 当IndexReader仍在搜索旧提交时,也可以通过OpenMode.CREATE 。 这可以实现有趣的用例,例如在每次提交之间完全重新索引您的内容,而不会影响任何开放的读者。

结合所有这些有趣的事务功能,您可以做一些很酷的事情:

  • 使用SnapshotDeletionPolicyPersistentSnapshotDeletionPolicy 热备份 :这些删除策略使“实时”备份索引变得很简单,而不会阻止使用IndexWriter进行的更改。 备份可以轻松进行增量备份(只需复制新文件,然后删除已删除的文件),就可以自由限制IO,以最大程度地减少对搜索的干扰。
  • 搜索不同的目录版本:也许您运行了一个电子商务网站,但是却发布了多个版本的目录。 在这种情况下,您可以保留较旧的提交,每次提交都搜索目录的特定版本,从而使用户可以选择要搜索的目录。
  • 来自相同初始索引的可重复索引测试:也许您想运行一堆性能测试,也许从一个大的初始索引开始尝试不同的RAM缓冲区大小或合并因子。 为此,只需运行每个测试,但是最后,不要关闭IndexWriter ,而使用rollback方法将索引快速返回其初始状态,以准备进行下一个测试。
  • 强制将所有索引段合并到单个段,但也保留先前的多段提交。 然后,您可以进行测试以比较多段性能与单段性能。
  • NFS文件系统上建立索引并进行搜索:由于NFS不能保护仍处于打开状态的文件不被删除,因此必须使用IndexDeletionPolicy保留每个提交,直到所有打开的阅读器都完成了提交(即,重新打开为新的提交)。 简单的方法是基于时间的,例如:不要删除提交,直到提交时间为15分钟,然后始终每5分钟重新打开阅读器一次。 没有这个,在NFS上进行搜索时,您将遇到各种可怕的异常。
  • 分布式提交:如果您还有其他资源必须随同Lucene索引的更改一起自动提交,则可以使用两阶段提交API。 这很简单,但是很容易在第二阶段失败。 为了从这种情况下恢复过来,例如,如果Lucene完成了其第二阶段提交,但是数据库的第二阶段遇到了一些错误,崩溃或断电,则可以通过在先前提交时打开IndexWriter轻松回滚Lucene的提交。
  • 实验性索引更改:也许您想尝试以新的方式重新索引索引的某些子集,但是您不确定该索引是否会奏效。 在这种情况下,只需保留旧的提交,然后在不成功的情况下回滚,或者如果旧的删除则删除。
  • 基于时间的快照:也许您希望自由地回滚到1天,1周前,1个月前等索引的索引,因此可以根据提交的年龄来保留提交。

请记住,保持多个提交活动必定会占用额外的磁盘空间,但是,开销通常很小,因为多个提交通常会共享公共段,尤其是较大的旧段。

参考:来自我们的JCG合作伙伴 Michael Mc Candless的事务性Lucene,来自“ 更改比特”博客。

翻译自: https://www.javacodegeeks.com/2013/06/transactional-lucene.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值