gpt4 book ai didi

java - 在 Lucene 中,如何确定 IndexSearcher 或 IndexWriter 是否正在另一个线程中使用?

转载 作者:行者123 更新时间:2023-12-03 23:08:24 26 4
gpt4 key购买 nike

Lucene 文档指出 IndexSearcher 和 IndexWriter 的单个实例应该用于整个应用程序中的每个索引,并跨所有线程。此外,在重新打开索引之前,对索引的写入将不可见。

因此,我尝试在多线程设置中遵循这些指南。 (几个线程写作,多个用户线程搜索)。我不想在每次更改时都重新打开索引,相反,我想让搜索器实例不超过一定时间(比如 20 秒)。

中央组件负责打开索引读取器和写入器,并保持单个实例并同步线程。我跟踪任何用户线程最后一次访问 IndexSearcher 的时间,以及它变脏的时间。如果更改后 20 秒后有人需要访问它,我想关闭搜索器并重新打开它。

问题是我不确定之前对搜索器的请求(由其他线程发出)是否已经完成,以便我可以关闭 IndexSearcher。这意味着如果我关闭并重新打开在所有线程之间共享的单个 IndexSearcher 实例,则可能会在其他线程中同时进行搜索。

更糟糕的是,理论上可能会发生以下情况:始终可以同时执行多项搜索。 (假设您有成千上万的用户在同一个索引上运行搜索)。单个 IndexSearcher 实例可能永远不会空闲,因此可以将其关闭。理想情况下,我想创建另一个 IndexSearcher 并将新请求定向到它(而旧的仍然打开并运行之前已经请求的搜索)。在旧实例上运行的搜索完成后,我想关闭它。

同步 IndexSearcher(或 IndexWriter)的多个用户以调用 close() 方法的最佳方法是什么? Lucene 是否为此提供任何功能/设施,或者应该完全由用户代码完成(例如使用搜索器计算线程数,并在每次使用时增加/减少计数)?

对于上述设计有什么建议/想法吗?

最佳答案

值得庆幸的是,在最近的版本(3.x 或 2.x 后期)中,他们添加了一个方法来告诉您在打开搜索器后是否有任何文字。 IndexReader.isCurrent() 将告诉您自此阅读器打开后是否发生了任何更改。因此,您可能会创建一个简单的包装器类来封装读取和写入,并且通过一些简单的同步,您可以提供一个类来管理所有线程之间的所有这些。

我大致是这样的:

  public class ArchiveIndex {
private IndexSearcher search;
private AtomicInteger activeSearches = new AtomicInteger(0);
private IndexWriter writer;
private AtomicInteger activeWrites = new AtomicInteger(0);

public List<Document> search( ... ) {
synchronized( this ) {
if( search != null && !search.getIndexReader().isCurrent() && activeSearches.get() == 0 ) {
searcher.close();
searcher = null;
}

if( search == null ) {
searcher = new IndexSearcher(...);
}
}

activeSearches.increment();
try {
// do you searching
} finally {
activeSearches.decrement();
}
// do you searching
}


public void addDocuments( List<Document> docs ) {
synchronized( this ) {
if( writer == null ) {
writer = new IndexWriter(...);
}
}
try {
activeWrites.incrementAndGet();
// do you writes here.
} finally {
synchronized( this ) {
int writers = activeWrites.decrementAndGet();
if( writers == 0 ) {
writer.close();
writer = null;
}
}
}
}
}

所以我有一个单独的类供读者和作者使用。注意这个类允许同时写和读,多个读者可以同时搜索。唯一的同步是快速检查以查看是否需要重新打开搜索器/编写器。我没有在方法级别上同步,这一次只允许一个读取器/写入器,这在性能方面很糟糕。如果那里有活跃的搜索者,你就不能放弃搜索者。所以如果你有很多读者进来,它只是简单地搜索而不做任何改变。一旦它精简,下一个单独的搜索器将重新打开脏搜索器。这对于流量会暂停的低流量站点可能非常有用。它仍然可能导致饥饿(即你总是在阅读越来越旧的结果)。你可以添加逻辑来简单地停止并重新初始化,如果它被注意到脏的时间比 X 早,否则我们像现在一样懒惰。这样你就可以保证搜索永远不会早于 X。

作家可以用同样的方式处理。我倾向于记得定期关闭编写器,以便读者会注意到它的更改(提交)。我没有很好地描述它,但这与搜索方式大致相同。如果那里有活跃的作家,你就不能关闭作家。如果你是最后一个出门的作家,请关闭作家。你明白了。

关于java - 在 Lucene 中,如何确定 IndexSearcher 或 IndexWriter 是否正在另一个线程中使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8195166/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com