Потокобезопасная запись в индексные файлы Lucene - PullRequest
0 голосов
/ 30 января 2012

У меня есть приложение, которое сканирует сайт и записывает содержимое в виде файлов индекса lucene в физический каталог.

Когда я использую потоки для этой цели, я получаю ошибки записи или ошибки из-за блокировок.

Я хочу использовать несколько потоков и записывать в файлы индекса, не пропуская задачу ни одного из потоков.

public class WriteDocument
{
    private static Analyzer _analyzer;

    private static IndexWriter indexWriter;

    private static string Host;

    public WriteDocument(string _Host)
    {
        Host = _Host;
        Lucene.Net.Store.Directory _directory = FSDirectory.GetDirectory(Host, false);
        _analyzer = new StandardAnalyzer();
        bool indexExists = IndexReader.IndexExists(_directory);
        bool createIndex = !indexExists;

        indexWriter = new IndexWriter(_directory, _analyzer, true);
    }
    public void AddDocument(object obj)
    {
           DocumentSettings doc = (DocumentSettings)obj;               
           Field urlField = new Field("Url", doc.downloadedDocument.Uri.ToString(), Field.Store.YES, Field.Index.TOKENIZED);
            document.Add(urlField);
            indexWriter.AddDocument(document);

            document = null;
            doc.downloadedDocument = null;

            indexWriter.Optimize();
            indexWriter.Close();
      }
}

В вышеприведенный класс я передаю значения, подобные этим:

DocumentSettings writedoc = new DocumentSettings()
{
      Host = Host,
      downloadedDocument = downloadDocument
};
Thread t = new Thread(() =>
{
doc.AddDocument(writedoc);
});
t.Start();

Если я добавлю t.Join(); после t.Start();, код работает для меня без каких-либо ошибок.Но это замедляет мой процесс, и фактически оно равно выводу, который я получаю без использования потоков.

Я получаю сообщение об ошибке типа:

Cannot rename /indexes/Segments.new to /indexes/Segments 
the file is used by some other process.

Может кто-нибудь помочь мне с этим кодом?

Ответы [ 2 ]

0 голосов
/ 18 апреля 2012

Подход, который вы можете использовать, состоит в том, чтобы создать отдельный индекс для каждого из потоков и объединить их все в конце. например index1, index2 ... indexn (соответствует потокам 1..n) и объединить их.

0 голосов
/ 30 января 2012

IndexWriter не является потокобезопасным, поэтому это невозможно.

Если вы хотите использовать несколько потоков для загрузки, вам нужно будет создать своего рода «насос сообщений», который является однопоточным, к которомувы можете кормить загружаемые и создаваемые документы и помещать их в очередь.

Например, в вашем методе AddDocument вместо непосредственного использования индекса просто отправьте их в службу, которая в конечном итоге проиндексирует его.

Эта служба должна пытаться все время индексировать все в очереди, и если у нее пока нет очереди, поспите некоторое время.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...