web-dev-qa-db-ja.com

LockObtainFailedExceptionsolrを使用してLucene検索インデックスを更新する

私はこれをたくさんググった。これらの問題のほとんどは、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コードを読み始めようとしています。私がこれをする必要がないのでどんな助けでも素晴らしいでしょう!

編集:私の更新はすべて次のコード(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検索インデックスを更新する2つの別々のプロセスがあります。

1)サーブレット2)コマンドラインツール

コマンドラインツールはEmbeddedSolrServerを使用していたため、最終的にLockObtainFailedExceptionでクラッシュしました。 StreamingUpdateSolrServerを使い始めたとき、問題は解決しました。

EmbeddedSolrServerがまったく機能するかどうかはまだ少し混乱しています。誰かがこれを説明できますか?私はそれがサーブレットプロセスでうまく機能し、他の人が書いている間待つだろうと思いました。

13
three-cups

私はあなたが次のようなことをしていると仮定しています:

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

これが機能しない理由は、ライターを閉じない限り、ライターが開いたままになるためです。そう writer1書き込みとは、書き込みが完了した後でも、ロックを保持します。 (ライターがロックを取得すると、破棄されるまで解放されません。)writer2は、writer1がまだロックを保持しているため、ロックを取得できません。そのため、LockObtainFailedExceptionをスローします。

2人のライターを使用する場合は、次のような操作を行う必要があります。

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

一度に開くことができるライターは1つだけなので、これにより、複数のライターを使用することで得られるメリットはほとんどなくなります。 (ウォームアップペナルティを常に支払うため、常にそれらを開いたり閉じたりするのは実際にははるかに悪いです。)

したがって、私が疑う答えは、根本的な質問です。複数のライターを使用しないでください。複数のスレッドがアクセスする単一のライターを使用します(IndexWriterはスレッドセーフです)。 RESTまたはその他のHTTPAPIを介してSolrに接続している場合、1人のSolrライターで多くのリクエストを処理できるはずです。

あなたのユースケースが何であるかはわかりませんが、別の可能な答えは、複数のインデックスを管理するための Solrの推奨事項 を参照することです。特に、コアをホットスワップする機能は興味深いかもしれません。

13
Xodarap

>> しかし、複数のSolrサーバーが同じ場所に書き込んでいますよね?

何も間違っていません。 SolrはLuceneライブラリを使用しており、「Lucene in Action」*には、一度に1つのプロセス/スレッドのみがインデックスに書き込むことができると記載されています。そのため、ライターはロックをかけます。

書き込もうとしている並行プロセスは、おそらく、ライターをインスタンス化するときに_org.Apache.lucene.store.LockObtainFailedException_例外をチェックする可能性があります。

たとえば、_writer2_をインスタンス化するプロセスを待機ループに入れて、アクティブな書き込みプロセスが終了してwriter1.close();を発行するまで待機します。これにより、ロックが解放され、Luceneインデックスが使用可能になります。もう一度書く。または、複数のLuceneインデックス(異なる場所にある)を同時に書き込むことができます。検索を実行するときは、それらすべてを検索する必要があります。

*「一度​​に1人のライターを強制するために、つまりIndexWriterまたはIndexReaderが削除または基準の変更を行うために、Luceneはファイルベースのロックを使用します。ロックファイル(デフォルトではwrite.lock)がインデックスに存在する場合ディレクトリ、ライターは現在インデックスを開いています。同じインデックスに別のライターを作成しようとすると、LockObtainFailedExceptionが発生します。これは、2つのライターが誤って単一のインデックスに作成された場合、非常に迅速に発生するため、重要な保護メカニズムです。インデックスの破損。」

セクション2.11.3、 Luceneの動作、第2版、Michael McCandless、Erik Hatcher、およびOtisGospodnetić、2010年

6
trouble