概述

  • Transaction log(tlog) 记录原始文档用于recovery,solrcloud中每个节点都自己的tlog。在更新时整个文档会被写入tlog,对于原子(atomic)更新,不光要更新整个文档需要写入tlog,该文档的历史版本也会被写入。总的来说tlog主要是保证文档的一致性,当JVM意外停止的时候,保证索引时最新的。

    • 注意:如果服务没有优雅的终止的话,在下次启动的时候将使用tlog进行重演。所以如果tlog很大的话,实例启动将会变得很慢。
  • 硬提交(Hard Commit) 硬提交可以通过客户端调用,同时在solrconfig.xml也有硬提交的选项<autoCommit>用于决定多长时间进行一次硬提交。

    • openSearcher <autoCommit>下的子选项,这回决定新提交的数据能不能被后续的搜索可见。
    • 硬提交是截断tlog的,一旦执行完硬提交就意味着索引已经写硬盘了。
  • 软提交(Soft Commit) 相对于设置为openSearcher=true的硬提交而言,软提交成本比较低。另外软提交是不会截断日志的。

    • 注意:软提交并不是没有成本,所以要控制好软提交的时间。
  • fsynch 底层的IO通信,一旦fsynch调用返回就意味着字节已经在磁盘上写成功,所以这和普通的java应用写数据不同,普通java程序的写数据只保证数据已经提交给操作系统了,至于什么时候落盘,操作系统会选择一个合适的时间。

  • flush 仅仅将数据提交给操作系统

    • 在solrcloud中,每个shard上通常会有多个replica,丢失数据就意味着所有的节点同时都挂掉了,这似乎不太可能。
    • 通常在flush之后,操作系统会在10-50ms内写入硬盘。即使JVM crashes,操作系统仍然会将数据写入硬盘。

tlog

tlog是在solr4后引入的,我们来看一下solrcloud下索引的流程:

  • 客户端提交更新文档给shard leader

  • shard leader再把所有数据发送给该shard上所有replica

  • shard leader响应数据的提交者

  • 当客户端收到成功响应,这个时候所有文档已经被flush至集群中所有节点的tlog中。

  • 如果JVM crashes,文档仍然会被会安全的写到磁盘,除非是操作系统崩溃。

    • JVM crashes也要分情况,如果普通的停止,solr会有硬提交触发。如果是类似于kill -9这样的退出,在服务重启后,tlog会被重演。
    • 我们也可以在solrconfig.xml中配置flush返回前进行fsynch,但是这基本上没什么必要,因为在同一个时刻所有节点硬件崩溃的可能性太小了。

硬提交将会触发tlog "rolled over",即关闭老的,打开新的。
tlog中会保存历史的100个文档,这是什么意思呢,比如你每次批量提交更新25个文档,每提交完做一次硬提交,那么磁盘上一直会存在5个tlog文件,每次提交完,生成一个新的tlog,删除最老的一个tlog,其它4个tlog保存历史上的100个文档。

注意:tlog文件只有当硬提交发生时才会回滚,如果一直不提交,那么一个tlog文件将会很大。比如我们每秒钟更新100个文档,一小时做一次硬提交,那么单个tlog就会保存360000个文档。

soft commit

软提交关心可见性,硬提交关心持久性。

软提交保证文档对后续的搜索可见,但是这也是存在代价的,新的searcher会被打开,searcher会进行预热,"top level" cache将会失效,如solfconfig.xml中配置的缓存(filterCache、queryResultCache)。另外FieldValueCache也会失效,所以facet查询将会一直等待,直到缓存刷新完。
因为各种缓存的失效,所以soft commit的频率是值得商榷的,虽然频繁会保证文档即时可见,但是也会让缓存的可用性降低。

soft commit不会使得用于function查询、sort上的"segment level caches"失效。

这就意味着我们在设置soft commit时,需要考虑以下一些东西:

  • tlog会继续增长
  • 文档会被检索到
  • 一些缓存必须要重新加载
  • searcher的预热将会执行

hard commit

硬提交有一个可选项:openSearcher=true/false,但是无论对于那种设置硬提交都会触发下面事件:

  • tlog截断,新的tlog会被打开,如果历史tlog中文档超过100个,最老的tlog会被删除。
  • 当前的索引段会被close和flush
  • 段合并会在后台启动

对于openSearcher=true,还会触发soft commit中的一些事件,打开新searcher、所有缓存失效等等。

Recovery

当机器crashes,JVM退出,集群可能会有以下情况:

  • 最新更新成功返回,集群中所有文档写入了tlog

  • 受到影响的机器重启后,它会联系shard leader以及一些其他事:

    • 如果主节点接受的新更新小于100个,则从自己的tlog进行重演。注意:如果重演过程中,又有更新进来,这些更新将会写入tlog的末尾。
    • 在该节点离线期间,如果主节点上已经做了100+次update,将会从主节点做一次全量同步。

建议

优雅的关闭服务
能不用kill -9就不要使用,优雅关闭可以使得服务在退出前进行硬提交。

索引更新量大

  • 将soft commit设置的尽量长一些,比如说10分钟
  • 将硬提交时间设置的短一些,同时openSearcher=false,比如说15秒

索引更新量大,但是查询负载低

  • 将soft commit设置的尽量长一些,接近你的最大接受界限。
  • 将硬提交设置为15秒,openSearcher=false

索引更新少
除非也别需要近实时,否则的话不要设置soft commit,对于hard commit设置为5-10分钟,openSearcher=true

索引更新量大,query负载高

  • 将soft commit尽量设置的长一点。

    这句话我必须要原封不动的贴出来:Don’t listen to your product manager who says “we need no more than 1 second latency”

  • 将硬提交设置为15秒,openSearcher=false

本文翻译至:(Understanding Transaction Logs, Soft Commit and Commit in SolrCloud)[https://lucidworks.com/2013/08/23/understanding-transaction-logs-softcommit-and-commit-in-sorlcloud/]