目前我知道Solr建索引有2种方法,这里介绍一下:
第一种就是我们常用的SolrServer.add(Collection<SolrInputDocument>),下面介绍一个各种SolrServer.
* HttpSolrServer,这个是我们最常用的就不说了
* ConcurrentUpdateSolrServer, 这个是创建和更新时使用,查询时不要用。保存了一个HttpSolrServer,用多线程技术并发向服务端提交索引数据,提高建索引的速度。
* LBHttpSolrServer, 这个保存了多个HttpSolrServer,进行负载均衡,提交查询时会判断哪个Server的压力最小,向那个Server提交请求。和上面相反,查询时使用,创建和更新索引时不建议使用。
* CloudSolrServer, 这个保存了一个LBHttpSolrServer,查询时和LBHttpSolrServer类似,但创建和更新索引时,在客户端会根据索引信息提交到对应的服务端。而HttpSolrServer是在服务端判断索引需要提交到哪个对应服务端,然后进行转发
* EmbeddedSolrServer,这个本地Server,单机使用,索引是保存在本地
这种建索引的方法,除EmbeddedSolrServer外,客户端除了发送数据外,服务端做了剩余的全部工作,想要提高建索引速度,就2个方案,1客户端用多线程提交索引,提高数据发送速度,但这个还取决于服务端接收数据的速度,服务端在高负荷的时候,速度就不会再提高了。2增加服务端节点数,这个就不说了,主要看硬件资源
另一种并不常见,我看了solr-map-reduce部分的代码才发现的。把建索引的过程分为了2步,
* 第一步利用EmbeddedSolrServer先在本地创建索引文件,这样客户端就分担了大部分的服务端的工作,
* 第二步利用合并索引的功能把本地索引文件提交到服务端,这里有个关键问题,就是合并索引时不再是http方式,而是磁盘目录的方式,所以本地索引文件位置必须对服务端是可见,所以要把本地索引文件共享出来,可以用NFS的方式,另一种方法就是用hdfs,solr源码里是用的hdfs。
这种建索引的方法,好处是客户端分担了不少服务端的压力,而不像前一种,除了发送数据外,其他时间都闲置了。我们可以用多线程技术,对数据分片,让客户端一边建索引,服务端同时合并已经建好的本地索引,性能大幅度的提升了。
下面贴2段关键代码,从solr源码里考出来的。
创建EmbeddedSolrServer
public EmbeddedSolrServer createEmbeddedSolrServer(Path solrHomeDir, FileSystem fs, Path outputShardDir) throws IOException { if (solrHomeDir == null) { throw new IOException("Unable to find solr home setting"); } System.out.println("Creating embedded Solr server with solrHomeDir: " + solrHomeDir + ", fs: " + fs + ", outputShardDir: " + outputShardDir); Path solrDataDir = new Path(outputShardDir, "data"); String dataDirStr = solrDataDir.toUri().toString(); SolrResourceLoader loader = new SolrResourceLoader(solrHomeDir.toString(), null, null); System.out.println(String .format( "Constructed instance information solr.home %s (%s), instance dir %s, conf dir %s, writing index to solr.data.dir %s, with permdir %s", solrHomeDir, solrHomeDir.toUri(), loader.getInstanceDir(), loader.getConfigDir(), dataDirStr, outputShardDir)); // TODO: This is fragile and should be well documented System.setProperty("solr.directoryFactory", HdfsDirectoryFactory.class.getName()); System.setProperty("solr.lock.type", "hdfs"); System.setProperty("solr.hdfs.nrtcachingdirectory", "false"); System.setProperty("solr.hdfs.blockcache.enabled", "false"); System.setProperty("solr.autoCommit.maxTime", "600000"); System.setProperty("solr.autoSoftCommit.maxTime", "-1"); CoreContainer container = new CoreContainer(loader); container.load(); Properties props = new Properties(); props.setProperty(CoreDescriptor.CORE_DATADIR, dataDirStr); CoreDescriptor descr = new CoreDescriptor(container, "core1", solrHomeDir.toString(), props); SolrCore core = container.create(descr); if (!(core.getDirectoryFactory() instanceof HdfsDirectoryFactory)) { throw new UnsupportedOperationException( "Invalid configuration. Currently, the only DirectoryFactory supported is " + HdfsDirectoryFactory.class.getSimpleName()); } EmbeddedSolrServer solr = new EmbeddedSolrServer(container, "core1"); return solr; }
合并索引
public Request call() { Request req = new Request(); LOG.info("Live merge " + dir.getPath() + " into " + mergeUrl); final HttpSolrServer server = new HttpSolrServer(mergeUrl); try { CoreAdminRequest.MergeIndexes mergeRequest = new CoreAdminRequest.MergeIndexes(); mergeRequest.setCoreName(name); mergeRequest.setIndexDirs(Arrays.asList(dir.getPath().toString() + "/data/index")); try { mergeRequest.process(server); req.success = true; } catch (SolrServerException e) { req.e = e; return req; } catch (IOException e) { req.e = e; return req; } } finally { server.shutdown(); } return req; }