Подтвердить что ты не робот

LockObtainFailedException обновление индекса поиска Lucene с использованием solr

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

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

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

Вызвано: org.apache.lucene.store.LockObtainFailedException: Время ожидания блокировки: NativeFSLock @/.../Lucene-ff783c5d8800fd9722a95494d07d7e37-write.lock

Я скорректировал таймауты блокировки в файле solrconfig.xml

<writeLockTimeout>20000</writeLockTimeout>
<commitLockTimeout>10000</commitLockTimeout>

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

EDIT: все мои обновления проходят через следующий код (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.

ДРУГОЕ ИЗМЕНЕНИЕ: Я прекратил использование EmbeddedSolrServer, и теперь он работает. У меня есть два отдельных процесса, которые обновляют индекс поиска solr:

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

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

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

4b9b3361

Ответ 1

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

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 Рекомендации для управления несколькими индексами. В частности, интерес может иметь возможность "горячей" замены ядер.

Ответ 2

Но у вас есть несколько серверов 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 in Action, второе издание, Michael McCandless, Erik Hatcher и Otis Gospodnetić, 2010