2011-06-04 21 views
11

Dağıtılmış bir ortamda master - shard uygulamasında arama yaparken uzun arama süreleriyle (10 saniyelik sipariş) karşılaşıyorum. Ancak Luke ile aynı sorgu, milisaniye cinsinden döner.Dağınık bir ortamda Lucene performansını nasıl iyileştirirsiniz?

Uygulama dağıtılmış bir sistemdir. Tüm düğümler, dizinlerin bulunduğu ortak bir NFS bağını paylaşır. Basitlik için, iki düğüm Node1 ve Node2'u düşünelim. /etc/fstab girişleri aşağıdaki gibidir.

nfs:/vol/indexes /opt/indexes nfs rw,suid,nodev,rsize=32768,wsize=32768,soft,intr,tcp 0 0 

sistemini vurmak ve düğüm başına besleme ve her Yem için bir usta her biri için bir shard orada birden beslemeleri (Feed1 ve Feed2 diyelim) vardır. indeksleri

Feed1-master 
Feed1-shard-Node1.com 
Feed1-shard-Node1.com0 
Feed1-shard-Node1.com1 

gibi arama şöyle FeedIndexManager olan

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); 
} 

olduğunu yapan kodlar bak.

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; 
    } 
} 

gecikme yaklaşık 95-98% tüketir katil, bu çağrıdır endeksi Luke ile açıldığında eğer milisaniye cinsinden ise bu bir arama için yaklaşık 20 saniye sürer.

TopDocs docs = searcher.search(q, filter, start + max, sort); 

Ben ettik Aşağıdaki sorular

  1. o yem başına birden ustaları var ya ben sadece bir usta azaltacaktır aklı başında mı? Endekste yer alan eleman sayısı 50 milyon civarındadır. birimi sayısını milyon (alt ikinci tepki) daha az olduğu

  2. gecikme beslemeler üzerinde düşüktür. Varlıkların 2 milyonun üzerinde olduğu feed'ler yaklaşık 20 saniye sürüyor. Her bir düğümde her bir düğüm başına 1 Shard'e karşı sadece 1 Shard tutmalı mıyım?

  3. usta Shard adlı den birleştirme her 15 saniyede bir çalışılır. Bu parametre değiştirilmeli mi?

Şu anda Lucene 3.1.0 ve JDK 1.6 kullanıyorum. Kutular, 8   GB RAM'lik iki 64 bit çekirdektir. Şu anda JVM, 4   GB max ile çalışır.

performansını artırmak için herhangi bir öneri

çok değerlidir. Genelde Lucene tarafından reçete edilen tüm standart performans ayarlamalarını gerçekleştirdim. Bu uzun mesajı okumak için çok teşekkürler.

+0

Burada neyin dağıtıldığını anlamıyorum. "Tüm düğümler, dizinlerin bulunduğu ortak bir NFS bağını paylaşır" diyorsunuz. Yani tüm parçalar aynı fiziksel sistemde mi? Muhtemelen NFS performansa zarar veriyor, bu durumda. –

cevap

2

Bu belki de aradığınız cevap değil, ama Elastic Search de bakabilirsiniz. Lucene etrafında dağıtılmış, kümelenmiş bir hizmet katmanıdır, bu HTTP üzerinden sorgulanır veya gömülü olarak çalıştırılabilir.

Ve hızlı, oldukça gülünç öyle. Kullanmanız gerekiyorsa Lucene konfigürasyon seçeneklerini hala sergilerken, Lucene'i kapakların altında düzgün bir şekilde ayarlamış gibi görünüyor. Lucene dağıtılmış bir ortamda gerçekleştirmek yapma

Eğer keşfettiğimiz üzere, seni yaramaz kilitleme sorunları ile sona, zordur. ElasticSearch bu sorunu çözmek için tasarlanmıştır, bu yüzden diğerlerini çözebilirsiniz.

+1

Hey, hızlı yanıt için teşekkürler. Infact ES ve SOLR tabloda yer almaktadır. ama burada savaştığım şey miras aldığım eski kod. Ben dilediğim anahtarı çevirebilirim. Arama optimizasyonu işinde değilim ve bu alandaki uzmanlara bırakacağım. Bunu söyledikten sonra, ES'nin SOLR üzerinden herhangi bir kıyaslamasını yaptınız mı? ve/veya diğeri için bir öneriniz var. – Andy