Solr——软提交和硬提交

1,293 阅读5分钟

前言

在Solr中有两种方式索引数据:硬提交和软提交。

软提交是在Solr4.0开始,增加的一个新功能。

那么为什么需要软提交呢?我们先在这里简单介绍一下,后续有详细介绍软提交和硬提交的区别。SolrJ方法

没有软提交之前我们提交索引是这么实现的:


client = new HttpSolrClient("http://localhost:8080/solr/"); //简写
SolrinputDocurnent doc= new SolrinputDocurnent() ; 

doc.addF工eld(fieldName , fieldValue) ; 
client .add(doc) ;
client.commit();

通过上述代码我们可以看到,我们每次添加一下索引,都要commit()一下,这个操作极其耗费资源,平均耗时600毫秒。

所以我们改用另一种方式来进行提交——软提交。

软提交和硬提交

硬提交是关于持久化的,软提交是关于可见性的。

硬提交

硬提交是将数据持久化到磁盘里面,并且能够查询到这条数据。

硬提交可以通过客户端显式调用实现,也可以通过在solrconfig.xml配置文件中添加相关配置实现。

为了达到灵活提交目的,Solr为硬提交和软提交设计了自动提交策略,自动提交主要靠maxDocs和maxTime两个参数控制,maxTime参数表示每间隔多少毫秒就触发一次索引提交,maxDocs表示当队列中累计了多少个索引文档就触发一次索引提交。两个条件只要满足其中之一即可。

硬提交使用事务日志来获取最新的Document ID,同时对索引文件调用fsync方法确保索引数据写入到磁盘,并且保证即便在断电的极端情况下也不会造成数据丢失。

硬提交它会要求所有的段文件必须立即合并为一个段文件,并重写整个索引,这个操作执行开销很大,不能执行太频繁。段文件合并应该合理配置合并策略,并定期执行索引优化,提升查询性能。

配置文件

        <!-- 自动(硬)提交策略 -->
        <!-- autoCommit是硬提交, 开启后会进行如下操作: -->
        <!-- 生成一个新的tlog文件, 删除旧的tlog文件; -->
        <!-- 把内存中缓存的文档fsync(OS内部的函数)到磁盘中, 并创建一个index descriptor, 用来记录各个文档的存储位置;此时就算JVM奔溃或系统宕机, 也不影响这部分数据, 不利之处是: 占用资源较多; -->
        <!-- 如果<openSearcher>true</openSearcher>, 就会打开查询器, 让此次硬提交的文档可供搜索. -->
        <autoCommit>
            <!-- 多少个文档提交一次: 要添加的文档数达到此值时自动触发新的提交 -->
            <maxDocs>${solr.autoCommit.maxDocs:1000}</maxDocs>
            <!-- 多少毫秒提交一次: 添加文档操作的时间持续到此值时自动触发新的提交, 与maxDocs配置其一即可 -->
            <maxTime>${solr.autoCommit.maxTime:1000}</maxTime>
            <!-- 如果为false, 提交操作会将最近的更改信息刷新到磁盘, 但不会立即打开查询器 - 也就是说客户端查询不到;
         实时性要求高的项目, 需要设置为true - 在6.0之后的版本中默认为true -->
            <openSearcher>true</openSearcher>
        </autoCommit>

软提交

软提交并没有将数据持久化到硬盘上,只是将更新的索引数据对查询请求可见。

配置文件

        <!-- 软提交策略,配置后会进行如下操作 -->
        <!-- 把内存中缓存的文档fsync(OS内部的函数)到磁盘中, 但不会创建index descriptor——也就是说各个文档的真实存储位置并没有被记录下来; -->
        <!-- 打开文档查询器, 涉及到的索引数据可以被查询到——近实时(NRT)更好; -->
        <!-- 软提交不会等待后台合并、整理文档等操作, 只确保了修改的可见行, 没有获取到文档的具体存储位置 —— 也就是说如果此时JVM奔溃或系统宕机, 就找不到这些数据了. -->
        <!-- 软提交比硬提交更快, 更能做到近实时查询, 但是如果服务器不稳定, 或JVM奔溃, 会导致提交的数据无法被检索到. -->
        <autoSoftCommit> 
            <maxTime>${solr.autoSoftCommit.maxTime:-1}</maxTime>
        </autoSoftCommit>

Transaction Log(tlog)

Transaction Log:事务日志,记录了原始文档,用于索引恢复功能。 此处未完待续………………

配置文件

    <!-- The default high-performance update handler -->
    <!-- 更新处理器 -->
    <!-- Solr默认使用的高可用的updateHandler是下面这个: -->
    <updateHandler class="solr.DirectUpdateHandler2">
        <!-- 索引库的事务日志 -->
        <!-- 默认路径: ${SOLR_HOME}/data/tlog. -->
        <!-- 启用事务日志用于实时查询、持久化索引数据、Solr Cloud中副本的恢复... -->
        <!-- 随着索引库的频繁更新, tlog日志文件会越来越大, 所以建议提交索引时采用硬提交 - 即批量提交的方式 - hard autoCommit. -->
        <updateLog>
            <!-- dir: 事务日志的存储目录 -->
            <str name="dir">${solr.data.dir:}</str>
        </updateLog>

        <maxPendingDeletes>100000</maxPendingDeletes>
        <autoCommit>
            <maxDocs>${solr.autoCommit.maxDocs:1000}</maxDocs>
            <maxTime>${solr.autoCommit.maxTime:1000}</maxTime>
            <openSearcher>true</openSearcher>
        </autoCommit>

        <autoSoftCommit> 
            <maxTime>${solr.autoSoftCommit.maxTime:-1}</maxTime>
        </autoSoftCommit>
 
    </updateHandler>

区别

软提交的速度更快

  • 索引软提交之所以比较快速,是因为它只是使用更新的索引数据能够对查询请求可见,但是并没有刷新硬盘上的索引文件或者是硬盘上创建任何文件。如果JVM崩溃了或者服务器断电了,那么上一次硬提交之后的所有索引更新数据将会被丢失。

执行频率

  • 软提交可以频繁执行,但是硬提交不可以。

耗时

  • 软提交因为不会将数据刷新到硬盘上,索引耗时较少。

吞吐量

  • 软提交因为需要频繁执行,所以会降低索引的吞吐量。

相关知识

prepareCommit和commit区别

在Lucene中,索引提交分两个阶段提交,prepareCommit操作属于第一个阶段。第一个阶段会做一些准备工作,比如将队列中待添加和标记为待删除的索引文档刷新到索引文件中,然后同步索引文件、创建并写入段文件,当第一阶段执行完之后,需要显式调用commit结束提交操作,或者调用rollback去回滚提交操作。如果直接调用commit。那么内部会隐式的先调用prepareCommit。

参考文档