提交和事务日志
在 Solr 中,文档在“提交”更新 Lucene 索引文件之前不可用于搜索。提交策略将确定何时可以搜索文档的添加、删除或更改。事务日志记录自上次“硬”提交点以来接收到的文档更新。
solrconfig.xml 中的 <updateHandler>
此部分中的设置在 solrconfig.xml 中的 <updateHandler> 元素中配置,并且可能影响索引更新的性能。这些设置影响内部执行更新的方式。
<updateHandler> 元素采用一个类参数,该参数必须为 solr.DirectUpdateHandler2。Solr 附带的 _default configset 已定义此部分,但下面讨论的许多参数的值可能需要针对您的应用程序进行自定义。
<config>
<updateHandler class="solr.DirectUpdateHandler2">
...
</updateHandler>
</config>
请注意,<updateHandler> 配置不影响处理客户端更新请求的 请求处理程序 的更高级配置。
提交
发送到 Solr 的数据在提交到索引之前不可搜索。原因是,在某些情况下,提交可能会很慢,并且应将其与其他可能的提交请求隔离进行,以避免覆盖数据。
硬提交与软提交
Solr 支持两种类型的提交:硬提交和软提交。
硬提交对索引文件调用 fsync 以确保它们已刷新到稳定存储。当前事务日志关闭,并打开一个新事务日志。有关在没有硬提交的情况下如何恢复数据,请参见下文 事务日志 部分。硬提交还可以选择使文档可供搜索,但在某些用例中这可能不是理想选择,因为它比软提交更昂贵。默认情况下,提交操作会将所有 Lucene 索引文件硬提交到稳定存储(磁盘)。
软提交更快,因为它只使索引更改可见,并且不 fsync 索引文件,不启动新段,也不启动新事务日志。具有 NRT 要求的搜索集合将希望经常软提交,以满足应用程序的可见性要求。softCommit 可能“比硬提交(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
,则提交将把最近的索引更改刷新到稳定存储,但不会导致打开新的搜索器以使这些更改可见。
如果达到 maxDocs
、maxTime
或 maxSize
限制中的任何一项,Solr 会自动执行提交操作。达到这些阈值中的第一个阈值将触发提交。
如果 solrconfig.xml
中缺少 autoCommit
标记,则只有显式提交才会更新索引。是否使用 autoCommit 的决定取决于应用程序的需求。
<autoCommit>
<maxDocs>10000</maxDocs>
<maxTime>30000</maxTime>
<maxSize>512m</maxSize>
<openSearcher>false</openSearcher>
</autoCommit>
您还可以使用 autoSoftCommit
标记指定“软”autoCommit。
<autoSoftCommit>
<maxTime>5000</maxTime>
</autoSoftCommit>
AutoCommit 最佳实践
确定最佳 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
。
commitWithin
设置允许在定义的时间段内强制执行文档提交。这最常与 近实时用例 一起使用,因此默认执行软提交。但是,这不会将新文档复制到用户管理的群集中的跟随服务器。如果这是您实现的要求,您可以通过添加参数来强制执行硬提交,如下例所示
<commitWithin>
<softCommit>false</softCommit>
</commitWithin>
使用此配置,当您在更新消息中调用 commitWithin
时,它将自动每次执行硬提交。
事务日志
事务日志 (tlog) 是自上次硬提交以来更新的“滚动窗口”。每次发生任何类型的硬提交时,当前事务日志都会关闭,并打开一个新事务日志。软提交对事务日志没有影响。
启用 tlog 时,添加到索引中的文档将写入 tlog,然后索引调用才会返回到客户端。在非正常关闭(断电、JVM 崩溃、kill -9
等)的情况下,在 Solr 停止时写入 tlog 但尚未通过硬提交提交的任何文档都会在启动时重播。因此,数据不会丢失。
当 Solr 正常关闭(使用 bin/solr stop
命令)时,Solr 将关闭 tlog 文件和索引段,因此在启动时无需重播。
一个令人困惑的点是事务日志中包含多少数据。tlog 不包含所有文档,只包含自上次硬提交以来的文档。不再需要时,旧的事务日志文件将被删除。
上述隐含含义是,如果禁用硬提交,事务日志将无限增长。因此,在索引时启用硬提交非常重要。 |
事务日志配置
所有 SolrCloud 群集以及 实时获取 功能都需要事务日志。它在 solrconfig.xml
的 updateHandler
部分中进行配置。
事务日志在 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>