部分來自http://www.jianshu.com/p/8cf609207497
一、總覽
solr的配置重要的有三個:solr.xml、solrConfig.xml、schema.xml
solr.xml 是整個Solr節點的配置,是定義關于core的管理、collection分片、solr雲
和http請求處理,不過目前改動不多,也沒仔細研究。
solrConfig.xml:關于core或collection的主要配置資訊。
schema.xml :定義索引中的文檔結構,包括字段名、字段類型、字段處理方法等,類似于表結構定義,比它更複雜。
二、Solr啟動過程
1、solr啟動的時候會找Java的全局變量:solr.solr.home ,作為根目錄。
在web.xml中配置java全局變量:
<env-entry>
<env-entry-name>solr/home</env-entry-name>
<env-entry-value>D:leaningsolrsolr-home</env-entry-value>
<env-entry-type>java.lang.String</env-entry-type>
</env-entry>
2、solr到根目錄下面的每個子目錄,去查找是否包含core.properties的檔案,有的話自動啟動這個collection或core的恢複工作。
core.properties 配置檔案主要配置,core或collection名字、shard分片資訊、存儲的資料和日志資訊以及定義的schemal.xml等。
在恢複過程中,solr會在這個子目錄下面的conf檔案夾下去找solrconfig.xml的配置。
下圖是solr的例子程式啟動過程:
三、solrconfig.xml 配置說明
3.1 基本概述
具體内容
1、solr使用的Lucene版本、使用到的Jar路徑配置;JMX配置,用于MBeans監控。
2、定義如何處理查詢、如何處理索引的内容。
查詢過程:
solr的查詢過程的詳細情況分為幾個階段,如下圖:
1、請求參數裝飾
1)defaults - 幫忙指定預設參數。
2)invariants-設定特定參數為固定值,重寫用戶端提供的值。
3)append - 在用戶端的參數基礎上進行參數的添加。
2、 第一元件
可選擇配置的,用于查詢處理前的預處理。
3、查詢元件鍊
至少包含查詢元件,用于執行具體的查詢工作。
4、最後元件
用于處理查詢後最後工作,比如拼寫檢查元件。
具體的定義,可以看下solrconfig.xml中提供的一個/browse定義的相關查詢整個過程的配置。
3.3 搜尋器(Searcher)
搜尋器說明
在solr中,具體執行的搜尋工作是通過搜尋器執行的,如上面的圖所示。在一個solr節點中,隻有一個注冊的搜尋器。
它是一個基于Lucene索引的可讀快照,當文檔被添加到索引中,不是立刻可以搜尋到。
讓新添加的文檔可以被搜尋到,需要關閉老的搜尋器,打開新的搜尋器。一般來說commit操作就會執行這個操作。
這個過程是比較耗時的,關閉老的搜尋器的時候,如果有使用者正在查詢,你的關閉動作需要等待。
另外所有的緩存都是基于舊的索引的,是以所有的緩存将失效,除非重新預熱。
預熱搜尋器
如上文所述,搜尋器在commit後需要重新打開,如果原來使用者正在執行查詢,緩存資料完全失效了,會促使重新執行查詢,
導緻使用者體驗差,是以需要預熱。
一般來說,預熱做兩個事情,一執行預熱語句、二用新的查詢到的緩存資料代替老的緩存資料。
注意,多的預熱語句,将會導緻打開新的搜尋器變慢,影響實時性,頻繁送出的話将會導緻記憶體等占用過大問題。
使用冷搜尋器
如果說預熱好的搜尋器稱為熱的搜尋器:)雖然沒看到這個說法,那麼沒有預熱的搜尋器稱為冷搜尋器,配置如下:
false 如果這個配置為true,則來查詢的時候,如果沒有注冊的
搜尋器,有的搜尋器正在預熱,那不管是否預熱完成,直接使用這個搜尋器。
(這裡面有個沖突,既然所有的搜尋器都是在新的預熱好,老的才被關閉的,那麼這種情況怎麼存在,也許是第一次執行查詢的時候)。
最大預熱搜尋器
當每次commit都會打開一個新的搜尋器進行預熱,那麼如果commit操作在程式裡面控制,在并發的情況下,可能有多個搜尋器被打開,
有個配置項:2,通過它來配置可以打開的最大搜尋器的個數,超過這個閥值,
commit操作會失敗,如果經常因為這個失敗,要看下是不是因為預熱的時間過長。
3.4 緩存配置
solr中緩存管理
1)緩存的尺寸和管理政策
Solr中設定緩存的尺寸是對象的數量,當超過這個數量的時候,Solr利用相關政策進行清除。
有兩個主要政策LRU(即Least Recently Used )将最近最少使用的實體移出緩存;
LFU(least frequently used)是将最少使用次數的實體移出緩存,過濾器緩存比較适合LFU政策。
有個誤區是在記憶體準許的情況下,盡可能設定你的緩存為盡可能的大。這個認識是錯誤的。
因為在commit後,緩存會失效,這将導緻JVM回收這些記憶體,緩存大,導緻JVM回收垃圾時間長,
服務被暫停的時間長。
2)緩存的命中和拆遷
命中率是指在緩存中發現一個查詢請求的比例。代表你的程式從緩存中獲得的好處。
期望是100%,驅逐數量顯示根據前面的緩存政策,多少對象被驅逐出緩存,拆遷量大
可能意味着你的緩存設定的小。
3)緩存對象的失效
在solr中,所有的緩存對象和搜尋器都是關聯的,隻要這個搜尋器不關閉,這些緩存就是有效的。
4)自動預熱新緩存
在一個commit之後,新的搜尋器被打開,但是不立刻關閉老的搜尋器,直到這個新的搜尋器被完全預熱。這個晚關閉政策主要用于填充新的搜尋器的緩存。
每個solr緩存都支援一個autowarmCount的屬性去設定最大的對象數量或者老的緩存的尺寸比例,去自動預熱。
過濾器緩存( Filter Cache)
過濾器緩存影響最終文檔結果,不影響打分。當你執行不同的查詢語句,而相同過濾條件的時候,過濾器緩存就可以起作用。
過濾器緩存可以跨查詢應用,可以顯著優化查詢的性能。
配置如下:
size="512"
initialSize="512"
autowarmCount="0"/>
當你的過濾條件複雜,或你索引中的文檔數量很多的時候,過濾器的建立和儲存在記憶體中是很耗時間的,是以你希望可以預熱過濾器緩存。如果一個過濾在你的程式中對很多請求都通用,那麼緩存過濾器是有意義的。
每個對象在緩存中都有個key,在過濾器緩存中,這個key就是過濾器的查詢語句,比如前面例子中:manu:belkin. 當預熱一個過濾器緩存時候,舊的緩存中的key被抽取出來,在新的搜尋器上被重新執行。如果你有上百個過濾器緩存,那麼在預熱的時候,solr必須執行這個100個過濾器的查詢,這将消耗大量的時間。
我們建議預熱的過濾器緩存,應該将autowarmCount設定為一個比較小的值。此外建議使用
LFU政策,下面是建議的配置:
過濾緩存器所占用的記憶體大小,當然和你在記憶體中緩存的文檔數量有關,需要的記憶體是你文檔數這麼多的byte記憶體。
1000萬的文檔數大概占1.2MB記憶體。
查詢結果緩存(Query result cache)
查詢結果集緩存儲存的是查詢結果集。多次執行同一個查詢的時候,後面的查詢結果一般從查詢結果緩存中直接得到,而不是在索引中再次執行相同的查詢,這是優化花費高查詢的強大方法。
查詢結果集緩存定義如下:
size="512" initialSize="512" autowarmCount="0">
查詢結果集緩存了查詢語句作為key,内部的Lucene文檔ID連結清單作為value。
文檔ID在索引中增加新的文檔的時候或合并的時候可能發生變化,是以預熱的時候,
緩存值需要被重新計算。
為了預熱一個結果集,solr必須重新執行查詢,相同的建議是保持autowarmCount為一個較小的值而不是預設的0,你将從中獲益。還有些關于些雜項來設定查詢結果集。
查詢結果視窗大小
查詢視窗 元素,在你執行一個查詢的時候,給你提供額外的頁面。
假設你的程式一頁提供10個文檔,在大多數情況下,使用者隻看第一和第二頁。你可以設定這個值為20,這樣在檢視第二頁的時候就不用再次查詢了。
一般情況下,這個值設定為你一頁需要查詢的文檔數量2-3倍,多了會給你的查詢帶來不必要的負擔。
查詢結果最大文檔緩存
在前面,給緩存設定的值的大小,代表緩存的數量,每個緩存的最大大小也可以設定一個值。
200就是設定一個緩存實體可以緩存的最大文檔數量。
準許延遲字段加載
具體配置為:true,設定了後,如果你的查詢是查詢文檔集
中的一部分,那麼隻有需要的字段才被加載,其他字段不加載。
(預設的值為true。這樣solr在根據讀取Document資訊時,如果enableLazyFieldLoading為True,把要傳回的Field集合封裝為一個SetNonLazyFieldSelector,
這裡的Field的值都是立即加載的,即到索引庫裡把該Field的值取出來儲存到Doc中的。doc的其他的Field的值則是通過延遲加載的。
也是就在document調用具體的get(String name)方式時,由LazyField去取值的。可見設定延遲加載為enableLazyFieldLoading為True,
而且我們要傳回的Field也很少時,那我們去讀索引庫所花的時間就少了)
文檔緩存(Document Cache)
查詢結果緩存是儲存比對查詢的一系列文檔内部ID,即使查詢結果在緩存中。solr仍然需要從磁盤中加載搜尋結果的文檔資訊。文檔緩存,存儲的key為内部文檔ID,值為從磁盤加載進來的文檔内容。是以查詢結果集緩存可以利用文檔緩存去查詢在查詢結果集中對應的文檔資訊。
size="512"
initialSize="512"
autowarmCount="0"/>
字段值緩存(Field Cache)
它在排序的時候使用,嚴格來說屬于Lucen來管理的。字段值緩存提供了通過文檔ID來快速通路字段值。
具體的配置檔案如下:
<?xml version="1.0" encoding="UTF-8" ?> <config> <!-- 在下面的所有配置中,字首"solr"。 為類名 是一個别名,導緻solr搜尋适當的包, 包括org.apache.solr。(search | update | request | core | analysis) 如果你也可以指定一個完全限定的Java類名 有自己的定制插件。 --> <luceneMatchVersion>5.1.0</luceneMatchVersion> <lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-dataimporthandler-.*.jar" /> <lib dir="${solr.install.dir:../../../..}/contrib/extraction/lib" regex=".*.jar" /> <lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-cell-d.*.jar" /> <lib dir="${solr.install.dir:../../../..}/contrib/clustering/lib/" regex=".*.jar" /> <lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-clustering-d.*.jar" /> <lib dir="${solr.install.dir:../../../..}/contrib/langid/lib/" regex=".*.jar" /> <lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-langid-d.*.jar" /> <lib dir="${solr.install.dir:../../../..}/contrib/velocity/lib" regex=".*.jar" /> <lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-velocity-d.*.jar" /> <dataDir>${solr.data.dir:}</dataDir> <!-- DirectoryFactory用于索引。 solr.StandardDirectoryFactory是檔案系統 并嘗試挑選目前的最佳實作 JVM和平台。 solr.NRTCachingDirectoryFactory,預設, 包裝solr.StandardDirectoryFactory并将小檔案緩存在記憶體中 為了更好的NRT性能。 可以通過solr.MMapDirectoryFactory強制實作特定的實作, solr.NIOFSDirectoryFactory或solr.SimpleFSDirectoryFactory。 solr.RAMDirectoryFactory是基于記憶體的,而不是 持久性,并且不能與複制配合使用。 --> <directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}"> <!-- 如果您使用的是solr.HdfsDirectoryFactory, 否則會被忽略。 如果您不打算使用hdfs, 您可以安全地删除此部分 --> <str name="solr.hdfs.home">${solr.hdfs.home:}</str> <str name="solr.hdfs.confdir">${solr.hdfs.confdir:}</str> <str name="solr.hdfs.blockcache.enabled">${solr.hdfs.blockcache.enabled:true}</str> <str name="solr.hdfs.blockcache.global">${solr.hdfs.blockcache.global:true}</str> </directoryFactory> <codecFactory class="solr.SchemaCodecFactory"/> <schemaFactory class="ClassicIndexSchemaFactory"/> <indexConfig> <lockType>${solr.lock.type:native}</lockType> <infoStream>true</infoStream> </indexConfig> <!-- JMX 此示例可在JMX中啟用并且僅當現有的MBeanServer 如果要通過JVM配置JMX,請使用此選項 參數。 删除它以禁用暴露Solr配置并向JMX統計。 --> <jmx /> <updateHandler class="solr.DirectUpdateHandler2"> <!-- 啟用事務日志,用于實時擷取,持久性和 和solr雲複制恢複。 日志可以增長 未送出的索引更改,是以使用硬性的autoCommit被推薦(見下文)。 "dir" - 事務日志的目标目錄,預設為 solr資料目錄。 --> <updateLog> <str name="dir">${solr.ulog.dir:}</str> </updateLog> <!-- AutoCommit 在特定條件下自動執行強制送出。 而不是啟用autoCommit,請考慮在添加文檔時使用"commitWithin"。 http://wiki.apache.org/solr/UpdateXmlMessages maxDocs - 自動觸發新送出之前自上次送出以來要添加的最大文檔數。 maxTime - 在自動觸發新送出之前自添加文檔以來允許通過的最大時間(以ms為機關)。 openSearcher - 如果為false,則送出将導緻最近的索引更改被重新整理到穩定存儲,但不會導緻新的搜尋器被打開以使這些更改可見。 如果啟用了updateLog,那麼強烈建議您使用某種類型的autoCommit來限制日志大小。 --> <autoCommit> <maxTime>${solr.autoCommit.maxTime:15000}</maxTime> <openSearcher>false</openSearcher> </autoCommit> <!--softAutoCommit就像autoCommit,除了它導緻一個"軟"送出, 隻能確定更改是可見的,但不能確定資料被同步到磁盤。 這比一個艱難的承諾更快,更接近實時友好。 --> <autoSoftCommit> <maxTime>${solr.autoSoftCommit.maxTime:-1}</maxTime> </autoSoftCommit> </updateHandler> <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 查詢部分 - 這些設定控制查詢時間,如緩存 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <query> <maxBooleanClauses>1024</maxBooleanClauses> <!-- Solr内部查詢緩存,基于同步的LinkedHashMap和基于ConcurrentHashMap的FastLRUCache, 有兩種可用于Solr,LRUCache的緩存實作。 FastLRUCache在單線程操作中具有更快的擷取速度和更慢的速度,是以當緩存的命中率高(> 75%)時,通常快于LRUCache,并且在多CPU系統的其他情況下可能會更快。 --> <!-- Filter Cache 過濾器緩存 參數: class - SolrCache實作LRUCache或(LRUCache或FastLRUCache) size - 緩存中最大條目數 initialSize - 緩存的初始容量(條目數)。 (參見java.util.HashMap) autowarmCount - 預填充和舊緩存的條目數。 --> <filterCache class="solr.FastLRUCache" size="512" initialSize="512" autowarmCount="0"/> <!-- 查詢結果緩存 緩存搜尋結果 - 基于查詢,排序和請求的文檔範圍的文檔ID(DocList)的有序清單。 --> <queryResultCache class="solr.LRUCache" size="512" initialSize="512" autowarmCount="0"/> <!-- 文檔緩存 緩存Lucene Document對象(每個文檔的存儲字段)。 由于Lucene内部文檔id是短暫的, 此緩存不會被自動加熱。 --> <documentCache class="solr.LRUCache" size="512" initialSize="512" autowarmCount="0"/> <!-- custom cache currently used by block join --> <cache name="perSegFilter" class="solr.search.LRUCache" size="10" initialSize="0" autowarmCount="10" regenerator="solr.NoOpRegenerator" /> <!-- 字段懶加載 如果為true,那麼未請求的存儲字段将被懶惰地加載。 如果通常的情況是不加載所有存儲的字段, 則這可以導緻顯着的速度改善,特别是如果跳過的字段是大的壓縮文本字段。 --> <enableLazyFieldLoading>true</enableLazyFieldLoading> <!--結果視窗大小 與queryResultCache一起使用的優化。 當請求搜尋時,請求所需數量的文檔ID的超集 被收集。 例如,如果搜尋特定查詢請求比對文檔10到19,并且queryWindowSize為50, 那麼檔案0到49将被收集和緩存。 通過緩存可以滿足該範圍内的任何其他請求。 --> <queryResultWindowSize>20</queryResultWindowSize> <!-- queryResultCache中任何條目緩存的最大文檔數。 --> <queryResultMaxDocsCached>200</queryResultMaxDocsCached> <!-- 查詢相關事件偵聽器 各種IndexSearcher相關事件可以觸發偵聽器采取行動。 newSearcher - 每當新的搜尋者正在準備中,并且有一個目前的搜尋者處理請求(也稱為注冊)時就被觸發。 它可以用于提示某些緩存,以防止某些請求的長時間請求。 firstSearcher - 每當一個新的搜尋者準備好,但沒有目前注冊的搜尋者來處理請求或從中擷取自動加密資料時,它們就被觸發。 --> <!-- QuerySenderListener接受NamedList數組,并按順序對每個NamedList執行本地查詢請求。 --> <listener event="newSearcher" class="solr.QuerySenderListener"> <arr name="queries"> <!-- <lst><str name="q">solr</str><str name="sort">price asc</str></lst> <lst><str name="q">rocks</str><str name="sort">weight asc</str></lst> --> </arr> </listener> <listener event="firstSearcher" class="solr.QuerySenderListener"> <arr name="queries"> <lst> <str name="q">static firstSearcher warming in solrconfig.xml</str> </lst> </arr> </listener> <!-- 使用冷搜尋器 如果搜尋請求進入并且沒有目前注冊的搜尋者,則立即注冊仍然變暖的搜尋者并使用它。 如果"false",則所有請求将被阻塞,直到第一個搜尋者完成加溫。 --> <useColdSearcher>false</useColdSearcher> <!-- 最大預熱搜尋器 可能在背景同時預熱的搜尋者的最大數量。 如果超出此限制,則傳回錯誤。 推薦值為1-2for read-only slaves --> <maxWarmingSearchers>2</maxWarmingSearchers> </query> <!-- 請求排程器 requestDispatcher将請求分發給相應的請求處理器 本節包含有關SolrDispatchFilter在處理此SolrCore請求時應如何運作的說明。 handleSelecttrue"是為了向舊版本相容 不必考慮 為了向後相容 --> <requestDispatcher handleSelect="false" > <!-- Request Parsing 設定請求的http表單的一些限制大小等配置 --> <requestParsers enableRemoteStreaming="true" multipartUploadLimitInKB="2048000" formdataUploadLimitInKB="2048" addHttpRequestToContext="false"/> <httpCaching never304="true" /> </requestDispatcher> <!-- 請求處理器 http://wiki.apache.org/solr/SolrRequestHandler 傳入的查詢将根據請求中指定的路徑以名稱的形式發送到特定的請求處理器 --> <requestHandler name="/dataimport" class="solr.DataImportHandler"> <lst name="defaults"> <str name="config">db-data-config.xml</str> </lst> </requestHandler> <requestHandler name="/select" class="solr.SearchHandler"> <!-- 預設值 其中df為預設查詢字段 --> <lst name="defaults"> <str name="echoParams">explicit</str> <int name="rows">10</int> <str name="df">text</str> </lst> <!-- 追加 --> <!-- <lst name="appends"> <str name="fq">inStock:true</str> </lst> --> <!-- 重寫 --> <!-- <lst name="invariants"> <str name="facet.field">cat</str> <str name="facet.field">manu_exact</str> <str name="facet.query">price:[* TO 500]</str> <str name="facet.query">price:[500 TO *]</str> </lst> --> <!-- 如果不希望使用SearchComponent的預設清單,則該清單可以被完全覆寫,也可以将元件添加到預設清單中。 (見下文) <!-- <arr name="components"> <str>nameOfCustomComponent1</str> <str>nameOfCustomComponent2</str> </arr> --> </requestHandler> <requestHandler name="/query" class="solr.SearchHandler"> <lst name="defaults"> <str name="echoParams">explicit</str> <str name="wt">json</str> <str name="indent">true</str> <str name="df">text</str> </lst> </requestHandler> <requestHandler name="/get" class="solr.RealTimeGetHandler"> <lst name="defaults"> <str name="omitHeader">true</str> <str name="wt">json</str> <str name="indent">true</str> </lst> </requestHandler> <requestHandler name="/browse" class="solr.SearchHandler"> <lst name="defaults"> <str name="echoParams">explicit</str> <!-- VelocityResponseWriter settings --> <str name="wt">velocity</str> <str name="v.template">browse</str> <str name="v.layout">layout</str> <!-- Query settings --> <str name="defType">edismax</str> <str name="q.alt">*:*</str> <str name="rows">10</str> <str name="fl">*,score</str> <!-- Faceting defaults --> <str name="facet">on</str> <str name="facet.mincount">1</str> </lst> </requestHandler> <initParams path="/update/**,/query,/select,/tvrh,/elevate,/spell,/browse"> <lst name="defaults"> <str name="df">text</str> </lst> </initParams> <requestHandler name="/update" class="solr.UpdateRequestHandler"> </requestHandler> <!-- Solr Cell Update Request Handler http://wiki.apache.org/solr/ExtractingRequestHandler --> <requestHandler name="/update/extract" startup="lazy" class="solr.extraction.ExtractingRequestHandler" > <lst name="defaults"> <str name="lowernames">true</str> <str name="uprefix">ignored_</str> <!-- capture link hrefs but ignore div attributes --> <str name="captureAttr">true</str> <str name="fmap.a">links</str> <str name="fmap.div">ignored_</str> </lst> </requestHandler> <requestHandler name="/analysis/field" startup="lazy" class="solr.FieldAnalysisRequestHandler" /> <requestHandler name="/analysis/document" class="solr.DocumentAnalysisRequestHandler" startup="lazy" /> <requestHandler name="/admin/" class="solr.admin.AdminHandlers" /> <requestHandler name="/admin/ping" class="solr.PingRequestHandler"> <lst name="invariants"> <str name="q">solrpingquery</str> </lst> <lst name="defaults"> <str name="echoParams">all</str> </lst> </requestHandler> <!-- Echo the request contents back to the client --> <requestHandler name="/debug/dump" class="solr.DumpRequestHandler" > <lst name="defaults"> <str name="echoParams">explicit</str> <str name="echoHandler">true</str> </lst> </requestHandler> <requestHandler name="/replication" class="solr.ReplicationHandler" > </requestHandler> <!-- 搜尋元件 搜尋元件已注冊到SolrCore并由其使用 SearchHandler的執行個體(可以通過名稱通路它們) 預設情況下,以下元件可用: <searchComponent name ="query"class ="solr.QueryComponent"/> <searchComponent name ="facet"class ="solr.FacetComponent"/> <searchComponent name ="mlt"class ="solr.MoreLikeThisComponent"/> <searchComponent name ="highlight"class ="solr.HighlightComponent"/> <searchComponent name ="stats"class ="solr.StatsComponent"/> <searchComponent name ="debug"class ="solr.DebugComponent"/> requestHandler中的預設配置如下所示: <arr name="components"> <str>query</str> <str>facet</str> <str>mlt</str> <str>highlight</str> <str>stats</str> <str>debug</str> </arr> 如果您将searchComponent注冊到其中一個标準名稱, 這将被使用而不是預設值。 要在"标準"元件之前或之後插入元件,請使用: <arr name ="first-components"> <STR> myFirstComponentName </ STR> </ ARR> <arr name ="last-components"> <STR> myLastComponentName </ STR> </ ARR> 注意:使用名稱"debug"注冊的元件将會 總是在"最後的元件"之後執行 --> </config> |