zoukankan      html  css  js  c++  java
  • solr亿万级索引优化实践-自动生成UUID

    solr亿万级索引优化实践(三)

    原创 2017年03月14日 17:03:09
           本篇文章主要介绍下如何从客户端solrJ以及服务端参数配置的角度来提升索引速度。

           solrJ6.0提供的Java客户端主要有下面几种接口:HttpSolrClient,ConcurrentUpdateSolrClient,CloudSolrClient。下面分别对这三种接口做一个简单的比较。HttpSolrClient在定义的时候需要明确指定一个solr节点路径,他在提交数据的时候也只能提交到这个节点上;ConcurrentUpdateSolrClient接口在同样是指定具体solr节点路径的,但不一样的事,这是个异步提交的模式,即我们在对客户端添加数据的时候,客户端会将文档缓存到内存队列中,让队列中的数据达到一定数量时,客户端会自动一次性向solr服务器发起一个http请求;CloudSolrClient就比较简单了,这个在定义时只需要指定zookeeper地址就好了,因为solr节点注册时,会将节点信息同步到zookeeper中,在提交数据时,CloudSolrClient会和zookeeper进行通信,发现solr云中的索引库,然后利用LBHttpSolrClient来提交数据。通过对比发现,ConcurrentUpdateSolrClient和CloudSolrClient这两个接口比较优秀,后者比较适用于哈希路由的模式,而前者则比较适合指定路由的模式。

          CloudSolrClient

    	public SolrClient CreateCloudSolrClient() {
    		CloudSolrClient csClient = new CloudSolrClient(zkUrl);
    		csClient.setZkConnectTimeout(zkConnectTimeOut);
    		csClient.setZkClientTimeout(zkClientTimeOut);
    		csClient.setDefaultCollection(collectionName);
    		csClient.setParallelUpdates(true);
    		csClient.setRequestWriter(new BinaryRequestWriter());
    		csClient.connect();
    		return csClient;
    	}

           ConcurrentUpdateSolrClient

    public SolrClient CreateHttpClient() {
    		ModifiableSolrParams params = new ModifiableSolrParams();
    		params.set(HttpClientUtil.PROP_MAX_CONNECTIONS, 128);
    		params.set(HttpClientUtil.PROP_MAX_CONNECTIONS_PER_HOST, 32);
    		params.set(HttpClientUtil.PROP_FOLLOW_REDIRECTS, false);
    		params.set(HttpClientUtil.PROP_ALLOW_COMPRESSION, true);
    		params.set(HttpClientUtil.PROP_USE_RETRY, true);
    		HttpClient httpClient = HttpClientUtil.createClient(params);
    		httpLists.add(httpClient);
    		ConcurrentUpdateSolrClient client = new ConcurrentUpdateSolrClient(solrUrl + "/" + collectionName, 50, 1);
    		client.setConnectionTimeout(zkClientTimeOut);
    		client.setSoTimeout(zkConnectTimeOut);
    		client.setPollQueueTime(500);
    		client.setParser(new BinaryResponseParser());
    		client.setRequestWriter(new BinaryRequestWriter());
    		return client;
    	}

            上篇文章介绍过,在多线程配合指定路由的模式下,集群的性能能够水平拓展,这个时候再配合ConcurrentUpdateSolrClient客户端,单个节点速度也会有比较大的提升。需要注意的是,有两个参数需要慎重设置,第一个是队列大小,这个指的是队列中最多存储多少个请求之后向服务器进行提交,另一个是线程数,表示内部开几个线程来提交数据。这两个参数需要根据自己应用程序的JVM来设置,如果设置的过大,会导致内存溢出。

             由于是异步请求的方式,所以如果在建立索引的过程中出现了异常,异常信息是不会抛给应用程序的,后来通过调试源码发现,solrJ自己在内部处理了这个异常(其实什么都没做,预留了一个空方法),我们可以在选择修改源码来捕捉异常数据,或者将此异常抛出,由应用程序来捕捉异常,持久化异常数据。

              在服务器端,我们也可以通过一些优化,来提高建立索引速度。

              1   段合并

            solr的索引是由段组成,更新索引的时候是写入一个段的信息,几个段共同组成一个索引,在solr优化索引的时候或其他的时候,solr的段是会合并的。所以我们可以对相关参数进行控制,对段的大小以及合并的频率进行调整,来提交系统资源利用效率。

            mergeFactor这个参数是合并因子,只当内存中有N个文档时则合并成一个段,当存在N个段文件时则合并成一个新的段文件。

            minMergeSize,指定最小的合并段大小,如果段的大小小于这个值,则可以参加合并。

            maxMergeSize,当一个段的大小大于这个值的时候就不参与合并了。

            maxMergeDocs,当文档数据量大于这个的时候,这个段就不参与合并了。

    在实际场景中,应该根据物理机的资源,来配置这些参数,适量加大mergeFactor参数,来降低合并频率,频繁的段合并会消耗大量系统资源。

         

             2  自动生成ID

             在Solr中,每一个索引,都要有一个唯一的ID,类似于关系型数据库表中的主键。我们在创建文档的时候,需要自己生成一串UUID来标示文档,但是由于ID比较长,在索引过程中,会占用一些额外的网速和内存等资源,我们可以控制在服务器端让solr自己生成UUID,具体配置步骤如下:

            1)修改schema.xml文件,将ID字段修改为UUID类型

     <field name="id" type="uuid" indexed="true" stored="true" required="true" multiValued="false" /> 
     <fieldType name="uuid" class="solr.UUIDField" indexed="true" />

            2)配置solrconfig.xml文件,添加更新策略配置,生成UUID

    <updateRequestProcessorChain name="uuid">
         <processor class="solr.UUIDUpdateProcessorFactory">
              <str name="fieldName">id</str>
         </processor>
         <processor class="solr.LogUpdateProcessorFactory" />
         <processor class="solr.DistributedUpdateProcessorFactory" />
         <processor class="solr.RunUpdateProcessorFactory" />
    </updateRequestProcessorChain>

            3)配置requestHandler

    <requestHandler name="/dataimport" class="solr.DataImportHandler">
        <lst name="defaults">
          <str name="config">tika-data-config.xml</str>
          <str name="update.chain">uuid</str>    
       </lst>
    </requestHandler>
    
    <requestHandler name="/update" class="solr.UpdateRequestHandler">
           <lst name="defaults">
            <str name="update.chain">uuid</str>
           </lst>  
    </requestHandler>
    
      <!-- for back compat with clients using /update/json and /update/csv -->  
      <requestHandler name="/update/json" class="solr.JsonUpdateRequestHandler">
            <lst name="defaults">
             <str name="stream.contentType">application/json</str>
             <str name="update.chain">uuid</str>
            </lst>
      </requestHandler>
      <requestHandler name="/update/csv" class="solr.CSVRequestHandler">
            <lst name="defaults">
             <str name="stream.contentType">application/csv</str>
             <str name="update.chain">uuid</str>
            </lst>
      </requestHandler>
    
      <requestHandler name="/update/extract"
                      startup="lazy"
                      class="solr.extraction.ExtractingRequestHandler" >
        <lst name="defaults">
          <str name="xpath">/xhtml:html/xhtml:body/descendant:node()</str>
          <str name="capture">content</str>
          <str name="fmap.meta">attr_meta_</str>
          <str name="uprefix">attr_</str>
          <str name="lowernames">true</str>
          <str name="update.chain">uuid</str>
        </lst>
    </requestHandler>
        这样solr即可自动生成UUID,不需要再客户端额外生成。
  • 相关阅读:
    整数参数求和
    《Objective-C 程序设计》读后感
    构建之法前三章精读读后感
    《java编程思想》读后感
    《JAVA核心技术》观后感
    构建之法读后感
    一、构建之法读后感
    开发MIS系统需要的技术及其含义、作用
    阅读笔记一
    Java课后练习9(异常处理)
  • 原文地址:https://www.cnblogs.com/Lxiaojiang/p/8639204.html
Copyright © 2011-2022 走看看