导航菜单
路很长,又很短
博主信息
昵   称:Cocodroid ->关于我
Q     Q:2531075716
博文数:360
阅读量:2225734
访问量:259916
至今:
×
云标签 标签球>>
云标签 - Su的技术博客
Tags : Solr,源码分析发表时间: 2016-02-12 00:10:05

题记:本来计划的SolrCloud的Recovery策略的文章是3篇的,但是没想到Recovery的内容蛮多的,前面三章分别介绍了Recovery的原理和总体流程,PeerSync策略,Replication策略。本章主要介绍我在实际生产环境中碰到的recovery的几个问题,以及前面漏下的几个点。solr_logo1

一. 日志中多次出现"Stopping recovery for zkNodeName= ..."

        我在公司的生产环境中总是会看到连续多次出现 " WARN : Stopping recovery for zkNodeName= ..." 或者 "INFO : Starting recovery process.  core=..." 这样的日志(由于公司的东西无法拿出了,所以只能意会下日志了)。

        这种现象的原因是因为:前文讲到过出现Recovery的原因之一是Leader转发update request到replica后没有接收到replica的表示成功的返回,那么这是Leader会发送RequestRecovery request给replia,命令它进行recovery。这是一次转发失败的过程。而每当Solr出现Leader转发update失败时候往往不会只出现一次,所以Leader会发送多次RequestRecovery request给replia。

        Relica的Recovery过程起始于DefaultSolrCoreState类的doRecovery()函数,在进行doRecovery()时候Replica会取消之前的Recovery。所以出现上述现象的根本原因就在于cancelRecovery上。需要指出的是DefaultSolrCoreState类的doRecovery()函数不但在RequestRecovery请求后会被调用,在leader 选举失败的时候也会被掉用。

 1   @Override
 2   public void cancelRecovery() {
 3     synchronized (recoveryLock) {
 4       if (recoveryStrat != null && recoveryRunning) {
 5         recoveryStrat.close();
 6         while (true) {
 7           try {
 8             recoveryStrat.join();
 9           } catch (InterruptedException e) {
10             // not interruptible - keep waiting
11             continue;
12           }
13           break;
14         }
15         
16         recoveryRunning = false;
17         recoveryLock.notifyAll();
18       }
19     }
20   }

 

 

 1   @Override
 2   public void close() {
 3     close = true;
 4     try {
 5       prevSendPreRecoveryHttpUriRequest.abort();
 6     } catch (NullPointerException e) {
 7       // okay
 8     }
 9     log.warn("Stopping recovery for zkNodeName=" + coreZkNodeName + "core=" + coreName);
10   }

 

 

 

二. Recovery过程中的rollback

      之前有@从前 网友给我留言说出现了"持续向solrcloud提交数据的同时调用了optimize 方法。导致索引文件同步失败,就一直无法recovery。"的现象。造成这个现象的原因大致由以下两点:

  • optimize的操作的本质是Merge策略中的forceMerge,默认情况下一旦触发了forceMerge,那么Solr会把所有的Segment合并成一个Segment。可以想象下,几十甚至几百GB的数据合成一个Segment,这样的符合会有多大?而且这还不算,一旦触发了forceMerge,如果有实时数据进来,那么它会把新进来的数据也merge进去,也就是说会一直merge进去根本不会停下来。关于forceMerge的具体情况,将在接下来介绍Merge的文章中详述。
  • Replication策略介绍的时候提到,如果isFullCopyNeeded为false,那么Solr就会调用closeIndexWriter.
1         if (!isFullCopyNeeded) {
2           // rollback - and do it before we download any files
3           // so we donx27t remove files we thought we didnx27t need
4           // to download later
5           solrCore.getUpdateHandler().getSolrCoreState()
6           .closeIndexWriter(core, true);
7         }

 

 

         我们很容会忽视closeIndexWriter传入的true参数,如果传入的为true,表示Solr关闭IndexWriter时候会进行回滚rollback,它的作用就是将IndexWriter退回到上次commit之后的状态,清空上次commit之后的所有add进来的数据。

 1       if (indexWriter != null) {
 2         if (!rollback) {
 3           try {
 4             log.info("Closing old IndexWriter... core=" + coreName);
 5             indexWriter.close();
 6           } catch (Exception e) {
 7             SolrException.log(log, "Error closing old IndexWriter. core="
 8                 + coreName, e);
 9           }
10         } else {
11           try {
12             log.info("Rollback old IndexWriter... core=" + coreName);
13             indexWriter.rollback();
14           } catch (Exception e) {
15             SolrException.log(log, "Error rolling back old IndexWriter. core="
16                 + coreName, e);
17           }
18         }
19       }

 

 

        那么问题就出在rollback中,Lucene的IndexWriter在进行回滚的时候会尝试去关闭正在进行的mergePolicy和mergeScheduler,如果发现还有segment正在进行那么它会一直等待,所以当optimize(forceMerge)进行时且有实时数据进来,那么Recovery就会一直停在那里直到超时。

 1 ...阅读原文





        
文章来源:itd4j 类别:搜索引擎| 阅读(1450)
推荐文章