LockObtainFailedException обновление поискового индекса Lucene с использованием solr - PullRequest
13 голосов
/ 16 марта 2011

Я много гуглил.Большинство этих проблем вызвано блокировкой, оставшейся после сбоя JVM.Это не мой случай.

У меня есть индекс с несколькими читателями и писателями.Я пытаюсь сделать массовое обновление индекса (удалить и добавить - вот как lucene делает обновления).Я использую встроенный сервер Solr (org.apache.solr.client.solrj.embedded.EmbeddedSolrServer).Другие авторы используют удаленный, не потоковый сервер (org.apache.solr.client.solrj.impl.CommonsHttpSolrServer).

Я запускаю это массовое обновление, оно некоторое время работает нормально, а затем умирает сa

Причина: org.apache.lucene.store.LockObtainFailedException: истекло время ожидания блокировки: NativeFSLock @ / ... / lucene-ff783c5d8800fd9722a95494d07d7e37-write.lock

1010 ** Я настроил время ожидания блокировки в solrconfig.xml
<writeLockTimeout>20000</writeLockTimeout>
<commitLockTimeout>10000</commitLockTimeout>

Я собираюсь начать читать код lucene, чтобы понять это.Любая помощь, поэтому мне не нужно это делать, было бы здорово!

РЕДАКТИРОВАТЬ: Все мои обновления проходят через следующий код (Scala):

val req = new UpdateRequest
req.setAction(AbstractUpdateRequest.ACTION.COMMIT, false, false)
req.add(docs)

val rsp = req.process(solrServer)

solrServer является экземпляромorg.apache.solr.client.solrj.impl.CommonsHttpSolrServer, org.apache.solr.client.solrj.impl.StreamingUpdateSolrServer или org.apache.solr.client.solrj.embedded. * EmbeddedSolrServer * * 10 * 21 * 10.ДРУГОЕ РЕДАКТИРОВАНИЕ: я перестал использовать EmbeddedSolrServer, и теперь он работает.У меня есть два отдельных процесса, которые обновляют индекс поиска solr:

1) Сервлет 2) Инструмент командной строки

Инструмент командной строки использовал EmbeddedSolrServer, и в конечном итоге он завершится с ошибкой LockObtainFailedException.Когда я начал использовать StreamingUpdateSolrServer, проблемы исчезли.

Я все еще немного озадачен тем, что EmbeddedSolrServer будет работать вообще.Может кто-нибудь объяснить это.Я думал, что это будет хорошо с процессом Servlet, и они будут ждать, пока другой пишет.

Ответы [ 2 ]

13 голосов
/ 18 марта 2011

Я предполагаю, что вы делаете что-то вроде:

writer1.writeSomeStuff();
writer2.writeSomeStuff();  // this one doesn't write

Причина, по которой это не сработает, заключается в том, что писатель остается открытым, пока вы его не закроете.Таким образом, writer1 пишет, а удерживает блокировку даже после того, как запись завершена.(Как только писатель получает блокировку, он никогда не снимает, пока не будет уничтожен.) writer2 не может получить блокировку, так как writer1 все еще удерживает ее, поэтому он выдает LockObtainFailedException.

Если выЕсли вы хотите использовать двух писателей, вам нужно сделать что-то вроде:

writer1.writeSomeStuff();
writer1.close();
writer2.open();
writer2.writeSomeStuff();
writer2.close();

Поскольку вы можете одновременно открыть только одного писателя, это в значительной степени сводит на нет все преимущества, которые вы получите от использования нескольких писателей.(На самом деле гораздо хуже открывать и закрывать их все время, так как вы будете постоянно платить штраф за разминку.)

Поэтому ответ на ваш основной вопрос: не используйте несколько авторов,Используйте один модуль записи с несколькими потоками, обращающимися к нему (IndexWriter является потокобезопасным).Если вы подключаетесь к Solr через REST или какой-либо другой HTTP API, один писатель Solr должен иметь возможность обрабатывать много запросов.

Я не уверен, каков ваш вариант использования, но другой возможный ответ - посмотреть Рекомендации Solr для управления несколькими индексами.Особенно интересна возможность горячей замены ядер.

6 голосов
/ 04 февраля 2012

>> Но у вас есть несколько серверов Solr, пишущих в одно и то же место, верно?

Нет, не так. Solr использует библиотеки Lucene, и в «Lucene in Action» * указано, что одновременно в индекс может быть записан только один процесс / поток. Вот почему писатель берет замок.

Ваши параллельные процессы, которые пытаются записать, могут, возможно, проверить исключение org.apache.lucene.store.LockObtainFailedException при создании экземпляра модуля записи.

Вы можете, например, поместить процесс, который создает экземпляр writer2, в цикл ожидания, чтобы дождаться завершения активного процесса записи и выдать writer1.close();, который затем снимет блокировку и сделает индекс Lucene доступным для записи снова. В качестве альтернативы, вы можете одновременно записать несколько индексов Lucene (в разных местах), и при выполнении поиска вам нужно будет выполнить поиск по всем из них.

* "Для принудительного применения одного средства записи за раз, что означает, что IndexWriter или IndexReader выполняют удаление или изменяют нормы, Lucene использует блокировку на основе файлов: если существует файл блокировки (write.lock по умолчанию) в вашей директории индекса у писателя в настоящее время открыт индекс. Любая попытка создать другую запись по тому же индексу приведет к возникновению исключения LockObtainFailedException. Это жизненно важный механизм защиты, потому что если два автора случайно создаются по одному индексу, это очень быстро привести к повреждению индекса. "

Раздел 2.11.3, Lucene в действии , второе издание, Майкл МакКэндлесс, Эрик Хэтчер и Отис Господнетич, 2010

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