直到现在,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,我们的客户之一,他帮助我们完善了该功能的“为什么”和“如何”。