在分佈式環境中搜索主 - 碎片實施時,我正面臨着漫長的搜索時間(以秒爲單位的順序)。然而,通過Luke進行的相同查詢以毫秒爲單位返回。如何提高分佈式環境中的Lucene性能?
該應用程序是一個分佈式系統。所有節點共享一個共同的NFS掛載位置的索引所在。爲了簡單起見,我們考慮兩個節點Node1
和Node2
。 /etc/fstab
條目如下。
nfs:/vol/indexes /opt/indexes nfs rw,suid,nodev,rsize=32768,wsize=32768,soft,intr,tcp 0 0
有多個Feed(比方說Feed1
和Feed2
)擊中系統並且存在用於每個每個節點進料和爲每個頻道的主的碎片。該指數看起來像
Feed1-master
Feed1-shard-Node1.com
Feed1-shard-Node1.com0
Feed1-shard-Node1.com1
,做搜索是
FeedIndexManager fim = getManager(feedCode);
searcher = fim.getSearcher();
TopDocs docs = searcher.search(q, filter, start + max, sort);
private FeedIndexManager getManager(String feedCode) throws IOException {
if (!_managers.containsKey(feedCode)) {
synchronized(_managers) {
if (!_managers.containsKey(feedCode)) {
File shard = getShardIndexFile(feedCode);
File master = getMasterIndexFile(feedCode);
_managers.put(feedCode, new FeedIndexManager(shard, master));
}
}
}
return _managers.get(feedCode);
}
的FeedIndexManager是如下的代碼。
public class FeedIndexManager implements Closeable {
private static final Analyzer WRITE_ANALYZER = makeWriterAnalyzer();
private final Directory _master;
private SearcherManager _searcherManager;
private final IndexPair _pair;
private int _numFailedMerges = 0;
private DateTime _lastMergeTime = new DateTime();
public FeedIndexManager(File shard, File master) throws IOException {
_master = NIOFSDirectory.open(master, new SimpleFSLockFactory(master));
IndexWriter writer = null;
try {
writer = new IndexWriter(_master,
WRITE_ANALYZER,
MaxFieldLength.LIMITED);
} finally {
if (null != writer) {
writer.close();
}
writer = null;
}
_searcherManager = new SearcherManager(_master);
_pair = new IndexPair(_master,
shard,
new IndexWriterBuilder(WRITE_ANALYZER));
}
public IndexPair getIndexWriter() {
return _pair;
}
public IndexSearcher getSearcher() {
try {
return _searcherManager.get();
}
catch (IOException ioe) {
throw new DatastoreRuntimeException(
"When trying to get an IndexSearcher for " + _master, ioe);
}
}
public void releaseSearcher(IndexSearcher searcher) {
try {
_searcherManager.release(searcher);
}
catch (IOException ioe) {
throw new DatastoreRuntimeException(
"When trying to release the IndexSearcher " + searcher
+ " for " + _master, ioe);
}
}
/**
* Merges the changes from the shard into the master.
*/
public boolean tryFlush() throws IOException {
LOG.debug("Trying to flush index manager at " + _master
+ " after " + _numFailedMerges + " failed merges.");
if (_pair.tryFlush()) {
LOG.debug("I succesfully flushed " + _master);
_numFailedMerges = 0;
_lastMergeTime = new DateTime();
return true;
}
LOG.warn("I couldn't flush " + _master + " after " + _numFailedMerges
+ " failed merges.");
_numFailedMerges++;
return false;
}
public long getMillisSinceMerge() {
return new DateTime().getMillis() - _lastMergeTime.getMillis();
}
public long getNumFailedMerges() {
return _numFailedMerges;
}
public void close() throws IOException {
_pair.close();
}
/**
* Return the Analyzer used for writing to indexes.
*/
private static Analyzer makeWriterAnalyzer() {
PerFieldAnalyzerWrapper analyzer =
new PerFieldAnalyzerWrapper(new LowerCaseAnalyzer());
analyzer.addAnalyzer(SingleFieldTag.ID.toString(), new KeywordAnalyzer());
// we want tokenizing on the CITY_STATE field
analyzer.addAnalyzer(AddressFieldTag.CITY_STATE.toString(),
new StandardAnalyzer(Version.LUCENE_CURRENT));
return analyzer;
}
}
消耗的等待時間爲約95-98%的殺傷是此呼叫時,它需要大約20秒的搜索,而如果索引經由盧克打開它的單位是毫秒。
TopDocs docs = searcher.search(q, filter, start + max, sort);
我有以下問題
它是明智的讓每個飼料多個主機或者我應該將其降低到只有一個主?該指數中的元素數量約爲5000萬。
對於實體數量少於一百萬(次要響應)的訂閱源,延遲較低。實體超過200萬的訂閱源大約需要20秒。我應該每個節點只維護每個節點1個碎片對每個節點1個碎片?
從碎片到主人的合併每15秒嘗試一次。這個參數是否應該調整?
我目前使用的是Lucene 3.1.0和JDK 1.6。這些盒子是兩個64位的內核,其中有8個 GB的RAM。目前JVM最多可以運行4 GB。
任何提高性能的建議都受到高度讚賞。我已經執行了Lucene通常規定的所有標準性能調整。非常感謝您閱讀這篇冗長的文章。
我不明白這裏發佈了什麼。你說:「所有的節點共享一個共同的NFS掛載索引所在。」所以所有部件都在同一個物理系統上? NFS很可能會損害性能,就是這種情況。 – 2011-06-15 06:36:17