Hibernate Search 中文操作指南
5. Architecture
5.1. Components of Hibernate Search
从用户的角度来看,Hibernate Search 由以下两个组件组成:
Mapper
映射器将用户模型“映射”到索引模型,并提供与用户模型一致的 API 来执行索引和搜索。
大多数应用程序依赖于 Hibernate ORM mapper,它提供索引 Hibernate ORM 实体属性的能力,但也存在一个可以在不使用 Hibernate ORM 时使用的 Standalone POJO mapper。
部分通过领域模型上的注释,部分通过配置属性来配置映射器。
Backend
后端是全文引擎的抽象,其中“完成任务”。通过“索引管理器”实现通用索引和搜索接口,每个管理器提供对一个索引的访问。
例如, Lucene backend委托给 Lucene 库,而 Elasticsearch backend委托给远程 Elasticsearch 集群。
后端部分由映射程序配置,它会告诉后端哪些索引必须存在以及它们必须有什么字段,部分通过配置属性配置。
映射程序和后端协同工作,提供以下三个主要功能:
Mass indexing
这就是 Hibernate Search 如何根据数据库的内容从零重建索引。
映射程序查询数据库以检索每个实体的标识符,然后批量处理这些标识符,加载实体并对其进行处理,以生成要发送到后端进行索引的文档。后端将文档放入内部队列中,并将在后台进程中批量处理文档,并在完成后通知映射程序。
有关详细信息,请参阅 Indexing a large amount of data with the MassIndexer 。
Explicit and listener-triggered indexing
显式和侦听器触发的索引依赖于索引计划 ( SearchIndexingPlan ) 来基于有限更改索引特定实体。
使用 explicit indexing时,调用方会将实体更改的信息显式传给 indexing plan;使用 listener-triggered indexing时,实体更改在 the Hibernate ORM integration(带有 a few exceptions)中以透明方式检测到,并自动添加到索引计划中。
侦听器触发的索引仅在 the Hibernate ORM integration 的上下文中才有意义;有 no such feature available for the Standalone POJO Mapper 。在两种情况下, indexing plan 会从这些更改中推断出实体是否需要重新索引,可能是更改的实体本身或 other entities that embed the changed entity in their index 。
在事务提交时,将处理索引计划中的更改(在同一线程或后台进程中,具体取决于 coordination strategy),生成文档,然后将其发送到后端进行索引。后端将文档放入内部队列中,并在后台进程中分批索引文档,并在完成时通知映射器。
有关详细信息,请参见 Implicit, listener-triggered indexing。
Searching
这就是 Hibernate Search 提供查询索引的方法。
映射程序公开对搜索 DSL 的入口点,允许选择要查询的实体类型。当选择一个或多个实体类型时,映射程序将委派给相应的索引管理器以提供搜索 DSL,并最终创建搜索查询。在查询执行时,后端会向映射程序提交实体引用的列表,然后映射程序加载相应的实体。然后由查询返回实体。
有关详细信息,请参见 Searching。
5.2. Examples of architectures
5.2.1. Overview
表 2. 架构的比较
Architecture |
|||
Compatible mappers |
Application topology |
||
Single-node |
Single-node or multi-node |
Extra bits to maintain |
Indexes on filesystem |
Elasticsearch cluster |
Guarantee of index updates |
Non-transactional, after the database transaction / SearchSession.close() returns |
|
Visibility of index updates |
|||
Native features |
Mostly for experts |
For anyone |
Overhead for application threads |
Overhead for the database |
|||
Impact on database schema |
None |
||
Limitations |
监听器触发索引忽略: JPQL/SQL queries, asymmetric association updates |
在极少数情况下索引不同步: concurrent @IndexedEmbedded, backend I/O errors |
No other known limitation |
5.2.2. Single-node application with the Lucene backend
Pros and cons
优点:
-
简单性:无需外部服务,所有内容都存在于同一服务器上。
-
Immediate visibility(~毫秒)的索引更新。虽然其他体系结构对于大多数用例都能执行得很好,但如果您需要在数据库更改后立即可见更改,那么单节点 Lucene 后端是实现索引的最佳方式。
缺点:
-
Without coordination, backend errors during indexing may lead to out-of sync indexes.
-
不易扩展:经验丰富的开发者可以通过提供本机 Lucene 对象来访问许多 Lucene 特性,甚至包括 Hibernate Search 未公开的特性;然而,对于不熟悉 Lucene 的开发者来说,Lucene API 并不是非常容易理解。如果您感兴趣,请参阅 Query-based predicates 。
-
应用程序线程开销:重新索引直接在应用程序线程中完成,可能需要额外时间来加载必须从数据库索引的数据。根据需要加载的数据量,这可能会增加应用程序的延迟和/或降低其吞吐量。
-
无水平可扩展性:只能有一个应用程序节点,所有索引都需要驻留在同一服务器上。
Getting started
若要实现此架构,请使用以下 Maven 依赖项:
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-mapper-orm</artifactId>
<version>7.2.0.Alpha2</version>
</dependency>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-backend-lucene</artifactId>
<version>7.2.0.Alpha2</version>
</dependency>
With the Standalone POJO Mapper (no Hibernate ORM)
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-mapper-pojo-standalone</artifactId>
<version>7.2.0.Alpha2</version>
</dependency>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-backend-lucene</artifactId>
<version>7.2.0.Alpha2</version>
</dependency>
5.2.3. Single-node or multi-node application, without coordination and with the Elasticsearch backend
Description
使用 Elasticsearch backend时,索引不绑定到应用程序节点。它们由一个单独的 Elasticsearch 节点集群管理,并通过对 REST API 的调用来访问。
因此,可以按以下方式设置多个应用程序节点,使它们全部独立执行索引更新和搜索查询,而无需相互协调。
Pros and cons
优点:
-
易于扩展:您可以通过提供 JSON 来轻松访问大多数 Elasticsearch 功能,即使 Hibernate Search 中没有提供这些功能。例如,请参阅 JSON-defined predicates或 JSON-defined aggregations或 leveraging advanced features with JSON manipulation。
-
索引的水平可扩展性:您可以根据需要调整 Elasticsearch 集群的大小。请参阅 "Scalability and resilience" in the Elasticsearch documentation。
-
应用程序的水平可扩展性:您可以拥有任意数量的应用程序实例(虽然高并发性增加了此体系结构中出现某些问题的可能性,请参阅下文的“缺点”)。
缺点:
-
Without coordination, backend errors during indexing may lead to out-of sync indexes.
-
需要管理一个附加服务:Elasticsearch 集群。
-
应用程序线程开销:重新索引直接在应用程序线程中完成,可能需要额外时间来加载必须从数据库索引的数据。根据需要加载的数据量,这可能会增加应用程序的延迟和/或降低其吞吐量。
-
~1 秒的索引更新(近乎实时)。虽然在数据库更改后,立即就可以看到更改,但 Elasticsearch 属于 near-real-time,如果您需要在数据库更改后立即看到更改,那么它的性能不会很好。
Getting started
若要实现此架构,请使用以下 Maven 依赖项:
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-mapper-orm</artifactId>
<version>7.2.0.Alpha2</version>
</dependency>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-backend-elasticsearch</artifactId>
<version>7.2.0.Alpha2</version>
</dependency>
With the Standalone POJO Mapper (no Hibernate ORM)
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-mapper-pojo-standalone</artifactId>
<version>7.2.0.Alpha2</version>
</dependency>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-backend-elasticsearch</artifactId>
<version>7.2.0.Alpha2</version>
</dependency>
5.2.4. Multi-node application with outbox polling and Elasticsearch backend
以下列出的特性尚处于 incubating 阶段:它们仍在积极开发中。
通常 compatibility policy 不适用:孵化元素(例如类型、方法、配置属性等)的契约在后续版本中可能会以向后不兼容的方式更改,甚至可能被移除。
我们建议您使用孵化特性,以便开发团队可以收集反馈并对其进行改进,但在需要时您应做好更新依赖于这些特性的代码的准备。
Description
使用 Hibernate Search 的 outbox-polling coordination strategy ,实体更改事件不会在出现它们的 ORM 会话中立即处理,而是推送到数据库中的出站表中。
一个后台进程轮询出站表以查找新事件,并异步处理它们,根据需要更新索引。由于该队列 can be sharded,多个应用程序节点可以共享索引工作负载。
这需要 Elasticsearch backend,以便索引不绑定到单个应用程序节点,并且可以从多个应用程序节点更新或查询。
Pros and cons
优点:
-
Safest:
在这里消除了其他体系结构中导致不同步索引的事件,因为实体更改事件 are persisted in the same transaction as the entity changes允许无限次重试。
在这里消除了其他体系结构中导致不同步索引的事件,因为在重新索引之前 each entity instance is reloaded from the database within a new transaction。
-
在这里消除了其他体系结构中导致不同步索引的事件,因为实体更改事件 are persisted in the same transaction as the entity changes允许无限次重试。
-
在这里消除了其他体系结构中导致不同步索引的事件,因为在重新索引之前 each entity instance is reloaded from the database within a new transaction。
-
易于扩展:您可以通过提供 JSON 来轻松访问大多数 Elasticsearch 功能,即使 Hibernate Search 中没有提供这些功能。例如,请参阅 JSON-defined predicates或 JSON-defined aggregations或 leveraging advanced features with JSON manipulation。
-
应用程序线程的开销最小:应用程序线程 only need to append events to the queue,它们不会自己执行重新索引。
-
索引的水平可扩展性:您可以根据需要调整 Elasticsearch 集群的大小。请参阅 "Scalability and resilience" in the Elasticsearch documentation。
-
应用程序的水平可扩展性:您可以拥有任意数量的应用程序实例。
缺点:
-
需要管理一个附加服务:Elasticsearch 集群。
-
索引更新的可见性延迟(~1 秒或更多,取决于负载和硬件)。一方面是因为 Elasticsearch 属于 near-real-time,另一方面是因为 the event queue introduces additional delays。
-
对数据库模式的影响: additional tables must be created in the database持有协调所需的数据。
-
数据库的开销:读取实体更改并执行重新索引 needs to read changed entities from the database的后台进程。
Getting started
outbox-polling 协调策略需要额外的依赖关系。若要实现此架构,请使用以下 Maven 依赖项:
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-mapper-orm</artifactId>
<version>7.2.0.Alpha2</version>
</dependency>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-mapper-orm-outbox-polling</artifactId>
<version>7.2.0.Alpha2</version>
</dependency>
<dependency>
<groupId>org.hibernate.search</groupId>
<artifactId>hibernate-search-backend-elasticsearch</artifactId>
<version>7.2.0.Alpha2</version>
</dependency>
With the Standalone POJO Mapper (no Hibernate ORM)
目前,这种架构无法使用独立 POJO 映射器实现,因为此映射器 does not support coordination 。