Hibernate Search 是一个库,它通过自动索引实体将 Hibernate ORM 与 Apache Lucene 或 Elasticsearch 集成,实现高级搜索功能:全文、地理空间、聚合等。有关更多信息,请参阅 hibernate.org 上的 Hibernate Search。

直到现在,Hibernate Search 都是在事务提交阶段发送索引请求。现在,JMS 后端可以以数据库更改的 事务方式 发送其索引请求。这有什么用?请继续阅读。

一些背景信息

当您更改索引实体时,Hibernate Search 会收集这些更改,并在数据库事务中进行等待,直到事务成功后再将它们推送到后端。

Hibernate Search 有几个后端

  • lucene:这个使用 Lucene 索引实体

  • JMS:这个发送包含索引更改列表的 JMS 消息。然后由一个主程序读取这个 JMS 队列,并使用 Lucene 后端。

  • 还有几个在这里不感兴趣的

在事务之后(具体在 afterTransaction 阶段)运行后端通常是您想要的。仅举几个例子

  • 您不希望索引更改被执行,如果数据库事务回滚

  • 您不希望数据库更改失败,因为索引失败:您总是可以从数据库中重建索引。

  • 并且大多数后端都不支持事务

Hibernate Search 允许您注册一个 错误回调,以便在出现这些索引问题时通知您,并按您的意愿反应(记录日志、抛出异常、重试等)。

为什么让 JMS 后端参与事务

如果您使 JMS 后端参与事务,那么要么数据库更改发生并且 JMS 消息被队列接收,要么什么也不发生(没有数据库更改也没有 JMS 消息)。

非事务性方法仍然是我们的推荐方法。但也有一些原因,您希望进行事务处理。

没有代码来处理消息失败

它消除了编写错误回调和处理这个棘手情况的需求。

更简单的利用过程

它简化了您的利用过程。您可以专注于监控您的JMS队列(进入消息的速率,出站消息的速率),这将为您提供Hibernate Search工作健康状况的准确状态。

事务性大规模索引

在更改大量索引实体时,通常使用以下伪模式来避免OutOfMemoryException

for (int i = 0 ; i < workLoadSize ; i++) {
    // do changes
    if ( i % 500 == 0 ) {
        fullTextSession.flush();
        fullTextSession.flushToIndexes();
        fullTextSession.clear();
    }
}

如果您使用事务性JMS后端,那么所有消息都将发送,或者没有任何消息。

确保您的JMS实现和您的JTA事务管理器足够智能,不要将消息保留在内存中,否则您可能遇到OutOfMemoryException

更一致的批处理框架流程

如果您使用Spring Batch这样的批处理框架,它在数据库中保留其“完成”状态,您就可以保证更改、索引请求和批处理状态都是一致的。

如何使用此功能

现在,此功能已集成到master中,并将很快在Hibernate Search版本中发布。

我们将配置保持尽可能简单。只需添加以下属性

hibernate.search.worker.enlist_in_transaction=true

如果您尝试在非事务性后端(即非JMS)上使用此选项,Hibernate Search会提醒您。

请确保使用XA JMS队列,并且您的数据库支持XA,因为我们正在讨论协调事务性系统。

感谢Yoann,我们的客户之一,他帮助我们完善了该功能的“为什么”和“如何”。


返回顶部