Java、Lucene:在Java中设置IndexWriter的锁定超时。

2024-04-13

我正在致力于将 Lucene 与我们基于 Spring-MVC 的应用程序集成。目前我们已经可以使用它了,但是我们很少得到cannot obtain lock错误。之后我必须手动删除锁定文件才能正常工作。

如何在 Java 中设置锁定索引的超时时间?我没有任何 Lucene 的 XML 配置。我通过POM.xml在maven中添加了项目库并实例化了所需的类。

Code :

public void saveIndexes(String text, String tagFileName, String filePath, long groupId, boolean type, int objectId) {
        try {
            // path is the indexing directory. 
            File testDir;
            Path suggestionsPath;
            Directory suggestionsDir;

            Path phraseSuggestPath;
            Directory phraseSuggestDir;

            Directory directory = org.apache.lucene.store.FSDirectory.open(path);
            IndexWriterConfig config = new IndexWriterConfig(new SimpleAnalyzer());
            IndexWriter indexWriter = new IndexWriter(directory, config);

            org.apache.lucene.document.Document doc = new org.apache.lucene.document.Document();
            if (filePath != null) {
                File file = new File(filePath); // current directory
                doc.add(new TextField("path", file.getPath(), Field.Store.YES));
            }
            doc.add(new StringField("id", String.valueOf(objectId), Field.Store.YES));
            //  doc.add(new TextField("id",String.valueOf(objectId),Field.Store.YES));
            if (text == null) {
                if (filePath != null) {
                    FileInputStream is = new FileInputStream(filePath);
                    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
                    StringBuilder stringBuffer = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        stringBuffer.append(line).append("\n");
                    }
                    stringBuffer.append("\n").append(tagFileName);
                    reader.close();
                    doc.add(new TextField("contents", stringBuffer.toString(), Field.Store.YES));
                }
            } else {

                FieldType fieldType = new FieldType(TextField.TYPE_STORED);
                fieldType.setTokenized(false);
                doc.add(new Field("contents", text+"\n"+tagFileName, fieldType));
            }
            indexWriter.addDocument(doc);
            indexWriter.commit();
            indexWriter.flush();
            indexWriter.close();
            directory.close();

            StandardAnalyzer analyzer = new StandardAnalyzer();
            AnalyzingInfixSuggester wordSuggester = new AnalyzingInfixSuggester(suggestionsDir, analyzer);

            ArrayList<String> words = new ArrayList<>();
            if (text != null) {
                text = html2text(text);
                Pattern pt = Pattern.compile("[^\\w\\s]");
                Matcher match = pt.matcher(text);
                while (match.find()) {
                    String s = match.group();
                    text = text.replaceAll("\\" + s, "");
                }

                if (text.contains(" ")) {
                    Collections.addAll(words, text.split(" "));

                } else {
                    words.add(text);
                }
                SuggestionIterator suggestionIterator = new SuggestionIterator(words.iterator());
                wordSuggester.build(suggestionIterator);
                wordSuggester.close();
                suggestionsDir.close();
            }

            AnalyzingInfixSuggester phraseSuggester = new AnalyzingInfixSuggester(phraseSuggestDir, analyzer);
            if (text != null) {
                text = html2text(text);
                ArrayList<String> phrases = new ArrayList<>();
                phrases.add(text);
                SuggestionIterator suggestionIterator = new SuggestionIterator(phrases.iterator());
                phraseSuggester.build(suggestionIterator);
                phraseSuggester.close();
                phraseSuggestDir.close();
            }

        } catch (Exception ignored) {
        }
    }

谢谢。


我引用两件事IndexWriter 文档 https://lucene.apache.org/core/6_5_0/core/org/apache/lucene/index/IndexWriter.html,

打开 IndexWriter 会为正在使用的目录创建一个锁定文件。 尝试在同一目录上打开另一个 IndexWriter 将导致 LockObtainFailedException。

and

注意:IndexWriter 实例是完全线程安全的,这意味着 多个线程可以同时调用其任何方法。如果你的 应用程序需要外部同步,您不应该 在 IndexWriter 实例上同步,因为这可能会导致死锁; 请使用您自己的(非 Lucene)对象。

因此,如果 IndexWriter 已经在其他地方打开且未关闭,则无法再次打开它。就您而言,当两个用户位于同一代码块中时,碰巧会出现一些不幸的时机。

您可以通过两种方式解决这个问题,

1.指定关键部分:将具有编写器打开、使用和关闭操作的代码部分标记为关键部分,并在该关键部分上应用 Java 同步。使用一些应用程序 Singleton bean 进行同步。因此,当另一个用户遇到该块时,他将等待第一个用户完成并释放锁。

2.单写入器实例:在您的应用程序中开发一种机制,在应用程序的生命周期内仅打开和关闭编写器一次,并在服务代码中传递该单个实例,以便编写器方法可以被尽可能多的用户调用,因为编写器实例是线程安全的卢森人。 我想,这可以通过 Singleton Spring bean 并将该 bean 注入到您的服务中来实现。

第二种方法的缺点是 - 单个全局索引目录的多服务器部署,以及是否有其他应用程序尝试在该全局索引上打开写入器。这个问题可以通过将索引编写器实例创建代码包装在某种全局服务中来解决,该服务不断将相同的实例返回给尝试使用它的应用程序。

这不是一个您试图通过删除锁定文件或引入超时来解决的简单问题。您必须根据 IndexWriter 文档对您的设计进行建模,而不是相反。

拥有单个编写器实例也会带来一些性能改进。

另外,练习在创建 writer 后立即进行空提交。这帮助我解决了过去的一些问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java、Lucene:在Java中设置IndexWriter的锁定超时。 的相关文章

随机推荐