solr的软硬提交

最近又被soft commit 和 hard commit搞得有点迷糊,其实都怪自己没有早点看源代码。问题出自这段代码,这也是我一开始接触solr时,查到的代码sample(事实证明问题都出在这里,引以为戒,有问题真的不要不求甚解)

if (rs.next()){
    while (true) {
        NiuniuSolrInputDocument doc = new NiuniuSolrInputDocument(rs);
        docs.add(doc);
        idx++;
        if(idx>=1000){
            httpSolrServer.add(docs);
            httpSolrServer.commit();
            docs.clear();
            idx = 0;
        }
        if (!rs.next())
            break;
    }
    if(idx!=0){
        httpSolrServer.add(docs);
        httpSolrServer.commit();
    }
}

问题


可以看到我每次执行完add方法以后,都会commit一下,认为只有commit过后文档才会真正的提交。如果按照这个思路走,批量建索引等可能问题不算大,但是如果研究solrconfig的autoCommit和autoSoftCommit就会有问题了。

问题来了,如果有autoCommit那我为毛要手动commit?

事实是,每次执行httpSolrServer.add(docs)方法,就会进行如下工作:

public UpdateResponse add(Iterator<SolrInputDocument> docIterator) throws SolrServerException, IOException {
    UpdateRequest req = new UpdateRequest();
    req.setDocIterator(docIterator);
    return req.process(this);
  }

即add方法已经把文档加入到solr中了,只要你的solr设置过autoCommit,那么每隔一段时间或者每当累积的文档到达一定数量,就会进行一次commit。

hard commit AND soft commit

看了manual里的autoCommit和autoSoftCommit的介绍,autoCommit就是自动commit,这里的commit指的是hard commit,里面有几个参数:
maxDocs:add到solr缓冲区的文档数量超过这个值时,自动执行commit把结果写入到磁盘索引文件中
maxTime:最长多久执行一次commit,即如果文档一直没有通过commit沉淀到磁盘上,那么持久性就可能出问题,所以要隔一段时间就执行一次commit
openSearcher:要不要新开一个searcher,如果要新开,那么目前已有的cache就会失效,具体代码可以看SolrIndexSearcher,它里面有几个Cache成员变量,如果你新建立一个searcher那么cache失效也是正常的了,除非你有autoWarming机制。在详细一点,就是,如果不执行softCommit(autoSoftCommit的maxTime设置成-1),同时在hard commit的时候openSearcher=false,那么执行完hard commit之后,磁盘文件虽然改变了,但是searcher没有新开,需要reload或者重启,才能看到索引中的新文档。所以相当于softCommit本身就自带openSearcher,那么,如果autoCommit的openSearcher=false,就一定要做softCommit,或者就索性不autoSoftCommit,而是使用autoCommit + openSearcher=true。

上面提到了hard commit,那么对应的就是softCommit,softCommit和NRTCachingDirectoryFactory息息相关。NRT是Near Realtime的缩写,即近实时的索引方式。

<directoryFactory name="DirectoryFactory"
                    class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}"/

solr.NRTCachingDirectoryFactory, the default,
wraps solr.StandardDirectoryFactory and caches small files in memory
for better NRT performance.

   solr.RAMDirectoryFactory is memory based, not
   persistent, and doesn't work with replication

这个有什么用呢?淘宝的增量商品架构走的就是这种方式,解释一下用它的理由:

  1. 用户增量添加商品,我们需要让这些增量商品尽早能被检索到
  2. 按照标准的索引文件的格式,文档想要被检索到就需要改写磁盘上的文件,频繁的改写带来了难以接受的IO开销
  3. 那么我们需要一种折中的方案,可以先把这部分增量放到内存中,这也是cache的意思,在检索时会去索引文件和内存中都去查询,这样的话就能实时把文档检索到,同时不会太频繁的更新磁盘
  4. 放在内存而不是磁盘就意味着存在persistence的问题,如果服务crash,内存中的文档就会丢失,这个时候我们就需要autoCommit了。

所以如果我们面临的是heavy index和heavy query的场景,需要在提交后就能立马检索到,就需要对每次增量都进行soft commit,然后设置一个我们能够容忍的时间interval或者数量上限,定时或者定量去执行一次hard commit,这样即使系统crash我们也只会丢失这个时间段的文档,而之前的文档已经都持久化了。而如果能够容忍提交后隔20秒才能搜索到,那么就设置autoSoftCommit参数为20000就好了,这样add到index中的文档每隔20s就会自动softCommit一次,就能被检索到了。

最终方案,我们把UpdateHandler的参数设置成:

<autoCommit>
  <maxTime>600000</maxTime>
  <openSearcher>false</openSearcher>
</autoCommit>

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

然后在增量提交文档时,不需要指定commit或者softCommit,新的文档会根据autoSoftCommit来自动进行软提交,然后会根据autoCommit来自定进行hard commit,这样新添加的文档在5秒之内就可以被检索到,然后每隔10分钟,这些文档就会写到磁盘上。
curl
http://localhost:8080/solr/niuniu_resource/update? -H "Content-Type: text/xml" --data-binary
'
<add>
<doc>
<field name="raw_id">123478</field>
</doc>
</add>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值