提交和事务日志

在 Solr 中,文档只有在“提交”更新 Lucene 索引文件后才可用于搜索。您的提交策略将决定何时可以搜索文档添加、删除或更改。事务日志记录自上次“硬”提交点以来收到的文档更新。

solrconfig.xml 中的 <updateHandler>

本节中的设置在 solrconfig.xml<updateHandler> 元素中配置,可能会影响索引更新的性能。这些设置会影响内部如何进行更新。

<updateHandler> 元素接受一个 class 参数,该参数必须是 solr.DirectUpdateHandler2。Solr 包含的 _default configset 已经定义了此部分,但是下面讨论的许多参数的值可能需要针对您的应用程序进行自定义。

<config>
  <updateHandler class="solr.DirectUpdateHandler2">
    ...
  </updateHandler>
</config>

请注意,<updateHandler> 配置不影响处理客户端更新请求的请求处理器的更高级别配置。

提交

发送到 Solr 的数据在提交到索引之前是不可搜索的。原因是,在某些情况下,提交可能会很慢,并且应与其他可能的提交请求隔离进行,以避免覆盖数据。

硬提交与软提交

Solr 支持两种类型的提交:硬提交和软提交。

硬提交 对索引文件调用 fsync 以确保它们已刷新到稳定存储。当前的事务日志已关闭,并打开一个新的事务日志。有关在没有硬提交的情况下如何恢复数据,请参阅下面的事务日志部分。可以选择,硬提交还可以使文档可用于搜索,但在某些用例中这可能不是理想的,因为它比软提交更昂贵。默认情况下,提交操作会导致将所有 Lucene 索引文件硬提交到稳定存储(磁盘)。

软提交(soft commit)速度更快,因为它仅使索引更改可见,而不会执行 fsync 索引文件、启动新段或启动新的事务日志。具有近实时(NRT)要求的搜索集合通常会频繁进行软提交,以满足应用程序的可见性要求。软提交可能比硬提交 (openSearcher=true) “开销更小”,但并非免费。建议根据应用程序的要求,尽可能长时间地设置此值。

硬提交意味着,如果服务器崩溃,Solr 将确切知道您的数据存储在哪里;软提交意味着数据已存储,但位置信息尚未存储。权衡之处在于,软提交可提供更快的可见性,因为它不会等待后台合并完成。

显式提交

当客户端在更新请求中包含 commit=true 参数时,这可确保更新操作中添加和删除影响的所有索引段在索引更新完成后立即写入磁盘。

如果指定了附加参数 softCommit=true,则 Solr 将执行软提交。这是近实时存储的一种实现,该功能可提高文档的可见性,因为您不必等待后台合并和存储(如果使用 SolrCloud,则为 ZooKeeper)完成即可继续执行其他操作。

有关在索引编制期间使用显式提交请求的详细信息,请参阅使用更新处理程序进行索引部分。

有关近实时操作的更多信息,请参阅近实时用例

自动提交

为了避免在索引编制期间发送显式提交命令,并提供对提交发生时间的控制,可以在 solrconfig.xml 中配置 autoCommit 参数。

这比从索引客户端发送显式提交更可取,因为它提供了对提交策略的更多控制。请注意,solrconfig.xml 中提供了默认值,但它们很可能没有根据您的需求进行调整,如果未有效调整,可能会导致性能问题。

这些设置控制待处理的更新自动推送到索引的频率。

maxDocs

可选

默认值:无

自上次提交以来发生的更新次数。

maxTime

可选

默认值:无

自最早的未提交更新以来的毫秒数。当发送大量文档时,此参数比 maxDocs 更可取。

maxSize

可选

默认值:无

磁盘上事务日志 (tlog) 的最大大小,超过此大小后将触发硬提交。当文档的大小未知且打算将事务日志的大小限制在合理大小时,这非常有用。

有效值可以是字节(默认值,不带后缀)、千字节(如果使用 k 后缀定义,例如 25k)、兆字节 (m) 或千兆字节 (g)。

openSearcher

可选

默认值:true

是否在执行提交时打开新的搜索器。如果此值为 false,则提交会将最近的索引更改刷新到稳定存储,但不会导致打开新的搜索器以使这些更改可见。

如果达到 maxDocsmaxTimemaxSize 限制中的任何一个,Solr 会自动执行提交操作。首先达到这些阈值的将触发提交。

如果 solrconfig.xml 中缺少 autoCommit 标记,则只有显式提交才会更新索引。是否使用 autoCommit 的决定取决于应用程序的需求。

<autoCommit>
  <maxDocs>10000</maxDocs>
  <maxTime>30000</maxTime>
  <maxSize>512m</maxSize>
  <openSearcher>false</openSearcher>
</autoCommit>

您还可以使用 autoSoftCommit 标记指定“软”自动提交。

<autoSoftCommit>
  <maxTime>5000</maxTime>
</autoSoftCommit>

自动提交最佳实践

确定最佳 autoCommit 设置是在性能和准确性之间进行权衡。导致频繁更新的设置将提高搜索的准确性,因为新内容将更快地可搜索,但由于频繁更新,性能可能会受到影响。更新频率较低可能会提高性能,但更新在查询中显示的时间会更长。

以下是两种提交方式的示例 NRT 配置,每 60 秒进行一次硬提交,每 10 秒进行一次软提交。请注意,这些不是 Solr 附带示例中的值!

<autoCommit>
  <maxTime>${solr.autoCommit.maxTime:60000}</maxTime>
  <openSearcher>false</openSearcher>
</autoCommit>

<autoSoftCommit>
   <maxTime>${solr.autoSoftCommit.maxTime:10000}</maxTime>
 </autoSoftCommit>
这些参数可以在运行时通过定义 Java“系统变量”来覆盖,例如,指定 `-Dsolr.autoCommit.maxTime=15000 将使用 15 秒的值覆盖硬提交间隔。

autoCommit(使用 openSearcher=false)和 autoSoftCommit 的选择有不同的后果。在非正常关闭的情况下,Solr 可能需要长达 autoCommit 中指定的时间才能从事务日志中重播未提交的文档。

autoSoftCommit 选择的时间确定了文档发送到 Solr 后变为可搜索的最大时间,并且不会影响事务日志。

为此值选择应用程序可以容忍的最长间隔,通常 15-60 秒是合理的,甚至更长,具体取决于要求。在将时间设置为非常短的间隔(例如 1 秒)的情况下,请考虑禁用缓存(尤其是 queryResultCache 和 filterCache),因为它们几乎没有用处。

对于极高的大容量索引编制,尤其是在没有搜索的初始加载时,请考虑通过为 maxTime 参数指定值 -1 来关闭 autoSoftCommit

在一段时间内提交

autoCommit 的替代方法是使用 commitWithin,可以在向 Solr 发出更新请求时(即在推送文档时)或在更新请求处理程序中定义该方法。

commitWithin 设置允许强制文档在定义的时间段内进行提交。这最常用于近实时用例,因此默认设置为执行软提交。但是,这不会将新文档复制到用户管理的群集中的 follower 服务器。如果这是您的实现的要求,您可以添加一个参数来强制进行硬提交,如本例所示

<commitWithin>
  <softCommit>false</softCommit>
</commitWithin>

使用此配置,当您在更新消息中调用 commitWithin 时,它每次都会自动执行硬提交。

事务日志

事务日志(tlog)是自上次硬提交以来更新的“滚动窗口”。每次发生任何类型的硬提交时,都会关闭当前事务日志并打开一个新的事务日志。软提交对事务日志没有影响。

启用 tlog 后,添加到索引的文档会在索引调用返回到客户端之前写入 tlog。在发生非正常关闭(断电、JVM 崩溃、kill -9 等)的情况下,写入 tlog 但在 Solr 停止时尚未通过硬提交提交的任何文档将在启动时重播。因此,数据不会丢失。

当 Solr 正常关闭(使用 bin/solr stop 命令)时,Solr 将关闭 tlog 文件和索引段,因此启动时无需重播。

一个令人困惑的点是事务日志中包含多少数据。tlog 不包含所有文档,仅包含自上次硬提交以来的文档。不再需要时,将删除较旧的事务日志文件。

上述隐含的意思是,如果禁用硬提交,事务日志将永远增长。因此,在索引编制时启用硬提交非常重要。

事务日志配置

所有 SolrCloud 集群以及实时获取功能都需要事务日志。它在 solrconfig.xmlupdateHandler 部分中配置。

事务日志在 solrconfig.xml 中配置,如下所示

<updateLog>
  <str name="dir">${solr.ulog.dir:}</str>
</updateLog>

唯一需要的参数是

dir

必需

默认值:无

事务日志的位置。在 Solr 的默认 solrconfig.xml 文件中,这定义为 ${solr.ulog.dir:}

如默认值所示,事务日志的位置可以在任何地方,只要它在 solrconfig.xml 中定义,并且 Solr 可写入和读取即可。

还有三个额外的专家级配置设置,这些设置会影响索引性能以及副本在必须进入完全恢复之前可以在更新上滞后多少。这些设置主要会影响 SolrCloud 群集配置

numRecordsToKeep

可选

默认值:100

在所有事务日志文件中保留的最小更新记录数。

maxNumLogsToKeep

可选

默认值:10

要保留的最大事务日志文件数。

numVersionBuckets

可选

默认值:65336

在检查重新排序的更新时,用于跟踪最大版本值的存储桶数。增加此值可减少在高容量索引编制期间同步对版本存储桶的访问的成本。这需要每个 Solr 核心 (8 字节 (long) * numVersionBuckets) 的堆空间。

syncLevel

可选

默认值:FLUSH

事务日志文件的同步级别。可以是 NONE、FLUSH 或 FSYNC,如果未设置任何内容,则 FLUSH 为默认值。

这些配置选项的工作方式如下

  • FSYNC:Solr 内部缓冲区被显式刷新到基础文件系统特定的缓冲区,该缓冲区也被刷新到事务日志文件。这是一种开销更大的操作,但更安全,因为内容已写入事务日志文件。

  • FLUSH:我们仅将 Solr 内部缓冲区显式刷新到基础文件系统特定的缓冲区,但此缓冲区不会显式刷新到事务日志文件。这开销更小,但也更不安全,因为如果在文件系统特定缓冲区也被刷新之前发生崩溃,则会丢失其中的数据。

  • NONE:没有缓冲区的显式刷新。此配置选项开销最少,但安全性也最低。

以下是在 solrconfig.xml<updateHandler> 下包含的示例,其中采用了上述高级设置

<updateLog>
  <str name="dir">${solr.ulog.dir:}</str>
  <int name="numRecordsToKeep">500</int>
  <int name="maxNumLogsToKeep">20</int>
  <int name="numVersionBuckets">65536</int>
  <str name="syncLevel">FSYNC</str>
</updateLog>

事件侦听器

UpdateHandler 部分也是可以配置与更新相关的事件侦听器的位置。可以在任何提交之后 (event="postCommit") 或仅在优化命令之后 (event="postOptimize") 触发这些事件。

用户可以在 Solr 插件中编写自定义的更新事件侦听器类。从 Solr 7.1 开始,出于安全原因,删除了 RunExecutableListener

其他 <updateHandler> 选项

在某些情况下,复杂的更新(例如空间/形状)可能需要很长时间才能完成。在默认配置中,属于同一内部版本存储桶的其他更新将无限期地等待。最终,这些未完成的请求可能会堆积起来,导致线程耗尽,并可能导致 OutOfMemory 错误。

参数 versionBucketLockTimeoutMs 通过为长时间运行的更新请求指定超时来帮助防止这种情况。如果达到此限制,更新将失败,但不会永远阻止所有其他更新。

此设置存在内存成本。大于默认值 0(无限制超时)的值会导致 Solr 使用不同的版本存储桶内部实现,这将每个 Solr 核心的内存消耗从约 1.5MB 增加到约 6.8MB。

solrconfig.xml<config> 部分下指定此选项的示例

<updateHandler class="solr.DirectUpdateHandler2">
  ...
  <int name="versionBucketLockTimeoutMs">10000</int>
</updateHandler>