目前我知道Solr建索引有2種方法,這裡介紹一下: 第一種就是我們常用的SolrServer.add(Collection<SolrInputDocument>),下麵介紹一個各種SolrServer. * HttpSolrServer,這個是我們最常用的就不說了 * ConcurrentUpdat ...
目前我知道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; }