store the translog id in the commit point data of a lucene commit point. work done towards better concurrency on flush operation
This commit is contained in:
parent
0d63fd68a8
commit
1911368feb
|
@ -26,8 +26,8 @@ import org.elasticsearch.ElasticSearchException;
|
||||||
import org.elasticsearch.common.Preconditions;
|
import org.elasticsearch.common.Preconditions;
|
||||||
import org.elasticsearch.common.Unicode;
|
import org.elasticsearch.common.Unicode;
|
||||||
import org.elasticsearch.common.bloom.BloomFilter;
|
import org.elasticsearch.common.bloom.BloomFilter;
|
||||||
|
import org.elasticsearch.common.collect.MapBuilder;
|
||||||
import org.elasticsearch.common.inject.Inject;
|
import org.elasticsearch.common.inject.Inject;
|
||||||
import org.elasticsearch.common.lucene.IndexWriters;
|
|
||||||
import org.elasticsearch.common.lucene.Lucene;
|
import org.elasticsearch.common.lucene.Lucene;
|
||||||
import org.elasticsearch.common.lucene.ReaderSearcherHolder;
|
import org.elasticsearch.common.lucene.ReaderSearcherHolder;
|
||||||
import org.elasticsearch.common.lucene.uid.UidField;
|
import org.elasticsearch.common.lucene.uid.UidField;
|
||||||
|
@ -62,6 +62,7 @@ import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.concurrent.locks.ReadWriteLock;
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
@ -122,6 +123,10 @@ public class RobinEngine extends AbstractIndexShardComponent implements Engine {
|
||||||
|
|
||||||
private volatile boolean possibleMergeNeeded = false;
|
private volatile boolean possibleMergeNeeded = false;
|
||||||
|
|
||||||
|
// we use flushNeeded here, since if there are no changes, then the commit won't write
|
||||||
|
// will not really happen, and then the commitUserData and the new translog will not be reflected
|
||||||
|
private volatile boolean flushNeeded = false;
|
||||||
|
|
||||||
private volatile int disableFlushCounter = 0;
|
private volatile int disableFlushCounter = 0;
|
||||||
|
|
||||||
// indexing searcher is initialized
|
// indexing searcher is initialized
|
||||||
|
@ -141,6 +146,8 @@ public class RobinEngine extends AbstractIndexShardComponent implements Engine {
|
||||||
private final Object failedEngineMutex = new Object();
|
private final Object failedEngineMutex = new Object();
|
||||||
private final CopyOnWriteArrayList<FailedEngineListener> failedEngineListeners = new CopyOnWriteArrayList<FailedEngineListener>();
|
private final CopyOnWriteArrayList<FailedEngineListener> failedEngineListeners = new CopyOnWriteArrayList<FailedEngineListener>();
|
||||||
|
|
||||||
|
private final AtomicLong translogIdGenerator = new AtomicLong();
|
||||||
|
|
||||||
@Inject public RobinEngine(ShardId shardId, @IndexSettings Settings indexSettings, ThreadPool threadPool,
|
@Inject public RobinEngine(ShardId shardId, @IndexSettings Settings indexSettings, ThreadPool threadPool,
|
||||||
IndexSettingsService indexSettingsService,
|
IndexSettingsService indexSettingsService,
|
||||||
Store store, SnapshotDeletionPolicy deletionPolicy, Translog translog,
|
Store store, SnapshotDeletionPolicy deletionPolicy, Translog translog,
|
||||||
|
@ -227,11 +234,23 @@ public class RobinEngine extends AbstractIndexShardComponent implements Engine {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
translog.newTranslog(newTransactionLogId());
|
if (IndexReader.indexExists(store.directory())) {
|
||||||
|
Map<String, String> commitUserData = IndexReader.getCommitUserData(store.directory());
|
||||||
|
if (commitUserData.containsKey(Translog.TRANSLOG_ID_KEY)) {
|
||||||
|
translogIdGenerator.set(Long.parseLong(commitUserData.get(Translog.TRANSLOG_ID_KEY)));
|
||||||
|
} else {
|
||||||
|
translogIdGenerator.set(System.currentTimeMillis());
|
||||||
|
indexWriter.commit(MapBuilder.<String, String>newMapBuilder().put(Translog.TRANSLOG_ID_KEY, Long.toString(translogIdGenerator.get())).map());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
translogIdGenerator.set(System.currentTimeMillis());
|
||||||
|
indexWriter.commit(MapBuilder.<String, String>newMapBuilder().put(Translog.TRANSLOG_ID_KEY, Long.toString(translogIdGenerator.get())).map());
|
||||||
|
}
|
||||||
|
translog.newTranslog(translogIdGenerator.get());
|
||||||
this.nrtResource = buildNrtResource(indexWriter);
|
this.nrtResource = buildNrtResource(indexWriter);
|
||||||
if (indexingSearcher.get() != null) {
|
if (indexingSearcher.get() != null) {
|
||||||
indexingSearcher.get().release();
|
|
||||||
indexingSearcher.set(null);
|
indexingSearcher.set(null);
|
||||||
|
indexingSearcher.get().release();
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
try {
|
try {
|
||||||
|
@ -266,6 +285,7 @@ public class RobinEngine extends AbstractIndexShardComponent implements Engine {
|
||||||
innerCreate(create, writer);
|
innerCreate(create, writer);
|
||||||
dirty = true;
|
dirty = true;
|
||||||
possibleMergeNeeded = true;
|
possibleMergeNeeded = true;
|
||||||
|
flushNeeded = true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new CreateFailedEngineException(shardId, create, e);
|
throw new CreateFailedEngineException(shardId, create, e);
|
||||||
} catch (OutOfMemoryError e) {
|
} catch (OutOfMemoryError e) {
|
||||||
|
@ -374,6 +394,7 @@ public class RobinEngine extends AbstractIndexShardComponent implements Engine {
|
||||||
innerIndex(index, writer);
|
innerIndex(index, writer);
|
||||||
dirty = true;
|
dirty = true;
|
||||||
possibleMergeNeeded = true;
|
possibleMergeNeeded = true;
|
||||||
|
flushNeeded = true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IndexFailedEngineException(shardId, index, e);
|
throw new IndexFailedEngineException(shardId, index, e);
|
||||||
} catch (OutOfMemoryError e) {
|
} catch (OutOfMemoryError e) {
|
||||||
|
@ -475,6 +496,7 @@ public class RobinEngine extends AbstractIndexShardComponent implements Engine {
|
||||||
innerDelete(delete, writer);
|
innerDelete(delete, writer);
|
||||||
dirty = true;
|
dirty = true;
|
||||||
possibleMergeNeeded = true;
|
possibleMergeNeeded = true;
|
||||||
|
flushNeeded = true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new DeleteFailedEngineException(shardId, delete, e);
|
throw new DeleteFailedEngineException(shardId, delete, e);
|
||||||
} catch (OutOfMemoryError e) {
|
} catch (OutOfMemoryError e) {
|
||||||
|
@ -572,6 +594,7 @@ public class RobinEngine extends AbstractIndexShardComponent implements Engine {
|
||||||
translog.add(new Translog.DeleteByQuery(delete));
|
translog.add(new Translog.DeleteByQuery(delete));
|
||||||
dirty = true;
|
dirty = true;
|
||||||
possibleMergeNeeded = true;
|
possibleMergeNeeded = true;
|
||||||
|
flushNeeded = true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new DeleteByQueryFailedEngineException(shardId, delete, e);
|
throw new DeleteByQueryFailedEngineException(shardId, delete, e);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -681,10 +704,17 @@ public class RobinEngine extends AbstractIndexShardComponent implements Engine {
|
||||||
// to be allocated to a different node
|
// to be allocated to a different node
|
||||||
indexWriter.close();
|
indexWriter.close();
|
||||||
indexWriter = createWriter();
|
indexWriter = createWriter();
|
||||||
|
|
||||||
|
if (flushNeeded) {
|
||||||
|
flushNeeded = false;
|
||||||
|
long translogId = translogIdGenerator.incrementAndGet();
|
||||||
|
indexWriter.commit(MapBuilder.<String, String>newMapBuilder().put(Translog.TRANSLOG_ID_KEY, Long.toString(translogId)).map());
|
||||||
|
translog.newTranslog(translogId);
|
||||||
|
}
|
||||||
|
|
||||||
AcquirableResource<ReaderSearcherHolder> current = nrtResource;
|
AcquirableResource<ReaderSearcherHolder> current = nrtResource;
|
||||||
nrtResource = buildNrtResource(indexWriter);
|
nrtResource = buildNrtResource(indexWriter);
|
||||||
current.markForClose();
|
current.markForClose();
|
||||||
translog.newTranslog(newTransactionLogId());
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new FlushFailedEngineException(shardId, e);
|
throw new FlushFailedEngineException(shardId, e);
|
||||||
} catch (OutOfMemoryError e) {
|
} catch (OutOfMemoryError e) {
|
||||||
|
@ -692,14 +722,18 @@ public class RobinEngine extends AbstractIndexShardComponent implements Engine {
|
||||||
throw new FlushFailedEngineException(shardId, e);
|
throw new FlushFailedEngineException(shardId, e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
if (flushNeeded) {
|
||||||
indexWriter.commit();
|
flushNeeded = false;
|
||||||
translog.newTranslog(newTransactionLogId());
|
try {
|
||||||
} catch (Exception e) {
|
long translogId = translogIdGenerator.incrementAndGet();
|
||||||
throw new FlushFailedEngineException(shardId, e);
|
indexWriter.commit(MapBuilder.<String, String>newMapBuilder().put(Translog.TRANSLOG_ID_KEY, Long.toString(translogId)).map());
|
||||||
} catch (OutOfMemoryError e) {
|
translog.newTranslog(translogId);
|
||||||
failEngine(e);
|
} catch (Exception e) {
|
||||||
throw new FlushFailedEngineException(shardId, e);
|
throw new FlushFailedEngineException(shardId, e);
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
failEngine(e);
|
||||||
|
throw new FlushFailedEngineException(shardId, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -1013,12 +1047,6 @@ public class RobinEngine extends AbstractIndexShardComponent implements Engine {
|
||||||
config.setMaxThreadStates(indexConcurrency);
|
config.setMaxThreadStates(indexConcurrency);
|
||||||
|
|
||||||
indexWriter = new IndexWriter(store.directory(), config);
|
indexWriter = new IndexWriter(store.directory(), config);
|
||||||
|
|
||||||
// we commit here on a fresh index since we want to have a commit point to support snapshotting
|
|
||||||
if (create) {
|
|
||||||
indexWriter.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
safeClose(indexWriter);
|
safeClose(indexWriter);
|
||||||
throw e;
|
throw e;
|
||||||
|
@ -1070,14 +1098,6 @@ public class RobinEngine extends AbstractIndexShardComponent implements Engine {
|
||||||
return newAcquirableResource(new ReaderSearcherHolder(indexSearcher));
|
return newAcquirableResource(new ReaderSearcherHolder(indexSearcher));
|
||||||
}
|
}
|
||||||
|
|
||||||
private long newTransactionLogId() throws IOException {
|
|
||||||
try {
|
|
||||||
return IndexWriters.rollbackSegmentInfos(indexWriter).getVersion();
|
|
||||||
} catch (Exception e) {
|
|
||||||
return IndexReader.getCurrentVersion(store.directory());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class RobinSearchResult implements Searcher {
|
private static class RobinSearchResult implements Searcher {
|
||||||
|
|
||||||
private final AcquirableResource<ReaderSearcherHolder> nrtHolder;
|
private final AcquirableResource<ReaderSearcherHolder> nrtHolder;
|
||||||
|
|
|
@ -43,6 +43,7 @@ import java.io.EOFException;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,9 +85,16 @@ public class LocalIndexShardGateway extends AbstractIndexShardComponent implemen
|
||||||
@Override public void recover(RecoveryStatus recoveryStatus) throws IndexShardGatewayRecoveryException {
|
@Override public void recover(RecoveryStatus recoveryStatus) throws IndexShardGatewayRecoveryException {
|
||||||
recoveryStatus.index().startTime(System.currentTimeMillis());
|
recoveryStatus.index().startTime(System.currentTimeMillis());
|
||||||
long version = -1;
|
long version = -1;
|
||||||
|
long translogId = -1;
|
||||||
try {
|
try {
|
||||||
if (IndexReader.indexExists(indexShard.store().directory())) {
|
if (IndexReader.indexExists(indexShard.store().directory())) {
|
||||||
version = IndexReader.getCurrentVersion(indexShard.store().directory());
|
version = IndexReader.getCurrentVersion(indexShard.store().directory());
|
||||||
|
Map<String, String> commitUserData = IndexReader.getCommitUserData(indexShard.store().directory());
|
||||||
|
if (commitUserData.containsKey(Translog.TRANSLOG_ID_KEY)) {
|
||||||
|
translogId = Long.parseLong(commitUserData.get(Translog.TRANSLOG_ID_KEY));
|
||||||
|
} else {
|
||||||
|
translogId = version;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IndexShardGatewayRecoveryException(shardId(), "Failed to fetch index version after copying it over", e);
|
throw new IndexShardGatewayRecoveryException(shardId(), "Failed to fetch index version after copying it over", e);
|
||||||
|
@ -108,7 +116,7 @@ public class LocalIndexShardGateway extends AbstractIndexShardComponent implemen
|
||||||
}
|
}
|
||||||
|
|
||||||
recoveryStatus.translog().startTime(System.currentTimeMillis());
|
recoveryStatus.translog().startTime(System.currentTimeMillis());
|
||||||
if (version == -1) {
|
if (translogId == -1) {
|
||||||
// no translog files, bail
|
// no translog files, bail
|
||||||
indexShard.start("post recovery from gateway, no translog");
|
indexShard.start("post recovery from gateway, no translog");
|
||||||
// no index, just start the shard and bail
|
// no index, just start the shard and bail
|
||||||
|
@ -118,9 +126,9 @@ public class LocalIndexShardGateway extends AbstractIndexShardComponent implemen
|
||||||
|
|
||||||
// move an existing translog, if exists, to "recovering" state, and start reading from it
|
// move an existing translog, if exists, to "recovering" state, and start reading from it
|
||||||
FsTranslog translog = (FsTranslog) indexShard.translog();
|
FsTranslog translog = (FsTranslog) indexShard.translog();
|
||||||
File recoveringTranslogFile = new File(translog.location(), "translog-" + version + ".recovering");
|
File recoveringTranslogFile = new File(translog.location(), "translog-" + translogId + ".recovering");
|
||||||
if (!recoveringTranslogFile.exists()) {
|
if (!recoveringTranslogFile.exists()) {
|
||||||
File translogFile = new File(translog.location(), "translog-" + version);
|
File translogFile = new File(translog.location(), "translog-" + translogId);
|
||||||
if (translogFile.exists()) {
|
if (translogFile.exists()) {
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
if (translogFile.renameTo(recoveringTranslogFile)) {
|
if (translogFile.renameTo(recoveringTranslogFile)) {
|
||||||
|
|
|
@ -40,6 +40,8 @@ import java.io.InputStream;
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
public interface Translog extends IndexShardComponent {
|
public interface Translog extends IndexShardComponent {
|
||||||
|
|
||||||
|
public static final String TRANSLOG_ID_KEY = "translog_id";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the id of the current transaction log.
|
* Returns the id of the current transaction log.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue