使用IndexMergeTool后,导致solrcloud的主从同步失败的解决方案

 

   在使用 solrcloud 的时候,很多人都会使用主从同步实现负载均衡与索引的容错性,当索引经过修改,删除或者新增了数据后,索引的段数会不断增多,累积得越多,索引的搜索速度越慢.这时很多人都会提出使用 optimize 优化索引.没错,这一个的确是一个相当重要的手段,而且 solrcloud 也提供了相关的功能即可.本来看似很简单就能解决的问题,深究下去,还是有点意思的.再来一种情况就是,有时候需要把几个 code 合并成一个大的 core ,当然了solrcloud 也有提供相关的功能.但似乎实际用起来并非这么的顺手.出现很多类似时间超时,连接超时等一大堆的问题.

 

   所以我们使用了 lucene 的 misc 包提供的叫 IndexMergeTool 的工具类,在 solrcloud 的官方文件中也有提及,此类除了用于合并索引后,其实还可以用于优化索引,原理都相似.

 

 问题的发现

 

   最近在一次的索引优化中,我们设想就是一个 leader 完成索引优化后,索引发生改变了,其他的 replica 则会把优化后的索引同步过去,我是使用 IndexMergeTool 去优化索引的.但当优化后,其他的 replica 并没有执行同步,我尝试重启 leader , replica 同样没有同步的操作,而看日志的确也没有发生同步.到底是怎么回事?

 

 问题的根源

 

    我开始以为是版本有问题,就尝试更换到 solrcloud 4.7.1 ,我发现把replica关闭,然后先写到 leader 再重启 replica 数据的确能同步,我通过 solrcloud 后台的 optimize 索引后,同样能正常同步.现在的问题看似是因为我使用了 IndexMergeTool 作为合并的工具而导致了不能同步了.

 

    对比情况

             我用 IndexMergeTool 合并完的索引与 solrcloud 后台操作优化索引对比了一下,大小与结构上差别不大,而且两份索引搜索出来的结果是相同的,证明索引是没有因为优化而损坏.通过 solrcloud 后台对比后有了一个发现,

    正常能同步的索引显示

             

 

              而通过IndexMergeTool 后,索引版本成为

                  

             看来,因为是版本问题导致了索引并不能正常同步成功了.再查看 solrcloud 优化的 handle 的源码后,恍然大悟,原来 solrcloud在优化索引后做了一些额外的处理

     

// 此类为 DirectUpdateHandler2 类,的 commit(CommitUpdateCommand cmd) 方法里面.
IndexWriter writer = iw.get();
        if (cmd.optimize) {
     // 普通的索引优化处理,跟IndexMergeTool 处理是一样的.
          writer.forceMerge(cmd.maxOptimizeSegments);
        } else if (cmd.expungeDeletes) {
          writer.forceMergeDeletes();
        }
        
        if (!cmd.softCommit) {
          synchronized (solrCoreState.getUpdateLock()) { // sync is currently needed to prevent preCommit
                                // from being called between preSoft and
                                // postSoft... see postSoft comments.
            if (ulog != null) ulog.preCommit(cmd);
          }
          
          // SolrCore.verbose("writer.commit() start writer=",writer);
     // 这里却添加在索引合并完后,添加了这一个对合并完操作后的版本时间写入
          if (writer.hasUncommittedChanges()) {
            final Map<String,String> commitData = new HashMap<String,String>();
            commitData.put(SolrIndexWriter.COMMIT_TIME_MSEC_KEY,
                String.valueOf(System.currentTimeMillis()));
            writer.setCommitData(commitData);
            writer.commit();
          } else {
            log.info("No uncommitted changes. Skipping IW.commit.");
          }

 

    通过源码可以看到,除了做合并后,最后还向索引中添加了一个叫"commitTimeMSec"的时间点,经后面发现那个时间点跟显示的 version 为一致的,说明就是那个时间点作为同步的依据了.同时查看了 msic 包下面的 IndexMergerTool 源码,因为本来就是 lucene 的包,所以不会象 solrcloud 再做这样子的处理了,后面添加上后,索引版本号就能正常显示也能正常同步了.

 

   解决方案

     修改IndexMergerTool 代码,红色框中所显示的

     

 

                            欢迎连载,但请注明出处及作者     

             http://kernaling-wong.iteye.com/blog/2066793

                 by kernaling.wong

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值