Skip to content

Commit faa5faf

Browse files
committed
Use separate searchers for "search visibility" vs "move indexing buffer to disk (#26972)
Today, when ES detects it's using too much heap vs the configured indexing buffer (default 10% of JVM heap) it opens a new searcher to force Lucene to move the bytes to disk, clear version map, etc. But this has the unexpected side effect of making newly indexed/deleted documents visible to future searches, which is not nice for users who are trying to prevent that, e.g. #3593. This is also an indirect spinoff from #26802 where we potentially pay a big price on rebuilding caches etc. when updates / realtime-get is used. We are refreshing the internal reader for realtime gets which causes for instance global ords to be rebuild. I think we can gain quite a bit if we'd use a reader that is only used for GETs and not for searches etc. that way we can also solve problems of searchers being refreshed unexpectedly aside of replica recovery / relocation. Closes #15768 Closes #26912
1 parent c02e9fa commit faa5faf

File tree

8 files changed

+220
-94
lines changed

8 files changed

+220
-94
lines changed

core/src/main/java/org/elasticsearch/action/termvectors/TermVectorsResponse.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,9 @@ private void buildFieldStatistics(XContentBuilder builder, Terms curTerms) throw
305305
long sumDocFreq = curTerms.getSumDocFreq();
306306
int docCount = curTerms.getDocCount();
307307
long sumTotalTermFrequencies = curTerms.getSumTotalTermFreq();
308-
if (docCount > 0) {
309-
assert ((sumDocFreq > 0)) : "docCount >= 0 but sumDocFreq ain't!";
310-
assert ((sumTotalTermFrequencies > 0)) : "docCount >= 0 but sumTotalTermFrequencies ain't!";
308+
if (docCount >= 0) {
309+
assert ((sumDocFreq >= 0)) : "docCount >= 0 but sumDocFreq ain't!";
310+
assert ((sumTotalTermFrequencies >= 0)) : "docCount >= 0 but sumTotalTermFrequencies ain't!";
311311
builder.startObject(FieldStrings.FIELD_STATISTICS);
312312
builder.field(FieldStrings.SUM_DOC_FREQ, sumDocFreq);
313313
builder.field(FieldStrings.DOC_COUNT, docCount);

core/src/main/java/org/elasticsearch/index/engine/Engine.java

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090
import java.util.concurrent.locks.Lock;
9191
import java.util.concurrent.locks.ReentrantLock;
9292
import java.util.concurrent.locks.ReentrantReadWriteLock;
93-
import java.util.function.Function;
93+
import java.util.function.BiFunction;
9494

9595
public abstract class Engine implements Closeable {
9696

@@ -465,8 +465,9 @@ public enum SyncedFlushResult {
465465
PENDING_OPERATIONS
466466
}
467467

468-
protected final GetResult getFromSearcher(Get get, Function<String, Searcher> searcherFactory) throws EngineException {
469-
final Searcher searcher = searcherFactory.apply("get");
468+
protected final GetResult getFromSearcher(Get get, BiFunction<String, SearcherScope, Searcher> searcherFactory,
469+
SearcherScope scope) throws EngineException {
470+
final Searcher searcher = searcherFactory.apply("get", scope);
470471
final DocIdAndVersion docIdAndVersion;
471472
try {
472473
docIdAndVersion = VersionsAndSeqNoResolver.loadDocIdAndVersion(searcher.reader(), get.uid());
@@ -494,23 +495,40 @@ protected final GetResult getFromSearcher(Get get, Function<String, Searcher> se
494495
}
495496
}
496497

497-
public abstract GetResult get(Get get, Function<String, Searcher> searcherFactory) throws EngineException;
498+
public abstract GetResult get(Get get, BiFunction<String, SearcherScope, Searcher> searcherFactory) throws EngineException;
499+
498500

499501
/**
500502
* Returns a new searcher instance. The consumer of this
501503
* API is responsible for releasing the returned searcher in a
502504
* safe manner, preferably in a try/finally block.
503505
*
506+
* @param source the source API or routing that triggers this searcher acquire
507+
*
504508
* @see Searcher#close()
505509
*/
506510
public final Searcher acquireSearcher(String source) throws EngineException {
511+
return acquireSearcher(source, SearcherScope.EXTERNAL);
512+
}
513+
514+
/**
515+
* Returns a new searcher instance. The consumer of this
516+
* API is responsible for releasing the returned searcher in a
517+
* safe manner, preferably in a try/finally block.
518+
*
519+
* @param source the source API or routing that triggers this searcher acquire
520+
* @param scope the scope of this searcher ie. if the searcher will be used for get or search purposes
521+
*
522+
* @see Searcher#close()
523+
*/
524+
public final Searcher acquireSearcher(String source, SearcherScope scope) throws EngineException {
507525
boolean success = false;
508526
/* Acquire order here is store -> manager since we need
509527
* to make sure that the store is not closed before
510528
* the searcher is acquired. */
511529
store.incRef();
512530
try {
513-
final SearcherManager manager = getSearcherManager(); // can never be null
531+
final SearcherManager manager = getSearcherManager(source, scope); // can never be null
514532
/* This might throw NPE but that's fine we will run ensureOpen()
515533
* in the catch block and throw the right exception */
516534
final IndexSearcher searcher = manager.acquire();
@@ -536,6 +554,10 @@ public final Searcher acquireSearcher(String source) throws EngineException {
536554
}
537555
}
538556

557+
public enum SearcherScope {
558+
EXTERNAL, INTERNAL
559+
}
560+
539561
/** returns the translog for this engine */
540562
public abstract Translog getTranslog();
541563

@@ -768,7 +790,7 @@ public final boolean refreshNeeded() {
768790
the store is closed so we need to make sure we increment it here
769791
*/
770792
try {
771-
return getSearcherManager().isSearcherCurrent() == false;
793+
return getSearcherManager("refresh_needed", SearcherScope.EXTERNAL).isSearcherCurrent() == false;
772794
} catch (IOException e) {
773795
logger.error("failed to access searcher manager", e);
774796
failEngine("failed to access searcher manager", e);
@@ -1306,7 +1328,7 @@ public void release() {
13061328
}
13071329
}
13081330

1309-
protected abstract SearcherManager getSearcherManager();
1331+
protected abstract SearcherManager getSearcherManager(String source, SearcherScope scope);
13101332

13111333
/**
13121334
* Method to close the engine while the write lock is held.

0 commit comments

Comments
 (0)