Ensure every repository has an incompatible-snapshots blob (#24403)
In #22267, we introduced the notion of incompatible snapshots in a repository, and they were stored in a root-level blob named `incompatible-snapshots`. If there were no incompatible snapshots in the repository, then there was no `incompatible-snapshots` blob. However, this causes a problem for some cloud-based repositories, because if the blob does not exist, the cloud-based repositories may attempt to keep retrying the read of a non-existent blob with expontential backoff until giving up. This causes performance issues (and potential timeouts) on snapshot operations because getting the `incompatible-snapshots` is part of getting the repository data (see RepositoryData#getRepositoryData()). This commit fixes the issue by creating an empty `incompatible-snapshots` blob in the repository if one does not exist.
This commit is contained in:
parent
8f1fe51f34
commit
9878aae144
|
@ -635,8 +635,17 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
|
||||||
repositoryData = repositoryData.incompatibleSnapshotsFromXContent(parser);
|
repositoryData = repositoryData.incompatibleSnapshotsFromXContent(parser);
|
||||||
}
|
}
|
||||||
} catch (NoSuchFileException e) {
|
} catch (NoSuchFileException e) {
|
||||||
logger.debug("[{}] Incompatible snapshots blob [{}] does not exist, the likely reason is that " +
|
if (isReadOnly()) {
|
||||||
"there are no incompatible snapshots in the repository", metadata.name(), INCOMPATIBLE_SNAPSHOTS_BLOB);
|
logger.debug("[{}] Incompatible snapshots blob [{}] does not exist, the likely " +
|
||||||
|
"reason is that there are no incompatible snapshots in the repository",
|
||||||
|
metadata.name(), INCOMPATIBLE_SNAPSHOTS_BLOB);
|
||||||
|
} else {
|
||||||
|
// write an empty incompatible-snapshots blob - we do this so that there
|
||||||
|
// is a blob present, which helps speed up some cloud-based repositories
|
||||||
|
// (e.g. S3), which retry if a blob is missing with exponential backoff,
|
||||||
|
// delaying the read of repository data and sometimes causing a timeout
|
||||||
|
writeIncompatibleSnapshots(RepositoryData.EMPTY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return repositoryData;
|
return repositoryData;
|
||||||
} catch (NoSuchFileException ex) {
|
} catch (NoSuchFileException ex) {
|
||||||
|
@ -802,8 +811,6 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void snapshotShard(IndexShard shard, SnapshotId snapshotId, IndexId indexId, IndexCommit snapshotIndexCommit, IndexShardSnapshotStatus snapshotStatus) {
|
public void snapshotShard(IndexShard shard, SnapshotId snapshotId, IndexId indexId, IndexCommit snapshotIndexCommit, IndexShardSnapshotStatus snapshotStatus) {
|
||||||
SnapshotContext snapshotContext = new SnapshotContext(shard, snapshotId, indexId, snapshotStatus);
|
SnapshotContext snapshotContext = new SnapshotContext(shard, snapshotId, indexId, snapshotStatus);
|
||||||
|
|
|
@ -189,6 +189,18 @@ public class BlobStoreRepositoryTests extends ESSingleNodeTestCase {
|
||||||
assertEquals(repositoryData.getIncompatibleSnapshotIds(), readData.getIncompatibleSnapshotIds());
|
assertEquals(repositoryData.getIncompatibleSnapshotIds(), readData.getIncompatibleSnapshotIds());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testIncompatibleSnapshotsBlobExists() throws Exception {
|
||||||
|
final BlobStoreRepository repository = setupRepo();
|
||||||
|
RepositoryData emptyData = RepositoryData.EMPTY;
|
||||||
|
repository.writeIndexGen(emptyData, emptyData.getGenId());
|
||||||
|
RepositoryData repoData = repository.getRepositoryData();
|
||||||
|
assertEquals(emptyData, repoData);
|
||||||
|
assertTrue(repository.blobContainer().blobExists("incompatible-snapshots"));
|
||||||
|
repoData = addRandomSnapshotsToRepoData(repository.getRepositoryData(), true);
|
||||||
|
repository.writeIndexGen(repoData, repoData.getGenId());
|
||||||
|
assertEquals(0, repository.getRepositoryData().getIncompatibleSnapshotIds().size());
|
||||||
|
}
|
||||||
|
|
||||||
private BlobStoreRepository setupRepo() {
|
private BlobStoreRepository setupRepo() {
|
||||||
final Client client = client();
|
final Client client = client();
|
||||||
final Path location = ESIntegTestCase.randomRepoPath(node().settings());
|
final Path location = ESIntegTestCase.randomRepoPath(node().settings());
|
||||||
|
|
|
@ -429,11 +429,13 @@ public class DedicatedClusterSnapshotRestoreIT extends AbstractSnapshotIntegTest
|
||||||
|
|
||||||
logger.info("--> making sure that snapshot no longer exists");
|
logger.info("--> making sure that snapshot no longer exists");
|
||||||
assertThrows(client().admin().cluster().prepareGetSnapshots("test-repo").setSnapshots("test-snap").execute(), SnapshotMissingException.class);
|
assertThrows(client().admin().cluster().prepareGetSnapshots("test-repo").setSnapshots("test-snap").execute(), SnapshotMissingException.class);
|
||||||
// Subtract three files that will remain in the repository:
|
// Subtract four files that will remain in the repository:
|
||||||
// (1) index-1
|
// (1) index-1
|
||||||
// (2) index-0 (because we keep the previous version) and
|
// (2) index-0 (because we keep the previous version) and
|
||||||
// (3) index-latest
|
// (3) index-latest
|
||||||
assertThat("not all files were deleted during snapshot cancellation", numberOfFilesBeforeSnapshot, equalTo(numberOfFiles(repo) - 3));
|
// (4) incompatible-snapshots
|
||||||
|
assertThat("not all files were deleted during snapshot cancellation",
|
||||||
|
numberOfFilesBeforeSnapshot, equalTo(numberOfFiles(repo) - 4));
|
||||||
logger.info("--> done");
|
logger.info("--> done");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -989,8 +989,8 @@ public class SharedClusterSnapshotRestoreIT extends AbstractSnapshotIntegTestCas
|
||||||
logger.info("--> delete the last snapshot");
|
logger.info("--> delete the last snapshot");
|
||||||
client.admin().cluster().prepareDeleteSnapshot("test-repo", lastSnapshot).get();
|
client.admin().cluster().prepareDeleteSnapshot("test-repo", lastSnapshot).get();
|
||||||
logger.info("--> make sure that number of files is back to what it was when the first snapshot was made, " +
|
logger.info("--> make sure that number of files is back to what it was when the first snapshot was made, " +
|
||||||
"plus one because one backup index-N file should remain");
|
"plus two because one backup index-N file should remain and incompatible-snapshots");
|
||||||
assertThat(numberOfFiles(repo), equalTo(numberOfFiles[0] + 1));
|
assertThat(numberOfFiles(repo), equalTo(numberOfFiles[0] + 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDeleteSnapshotWithMissingIndexAndShardMetadata() throws Exception {
|
public void testDeleteSnapshotWithMissingIndexAndShardMetadata() throws Exception {
|
||||||
|
|
Loading…
Reference in New Issue