Skip to content

[server] fix KV snapshot restoring fallback - #3790

Open
zuston wants to merge 2 commits into
apache:mainfrom
zuston:snapshotFallback
Open

[server] fix KV snapshot restoring fallback#3790
zuston wants to merge 2 commits into
apache:mainfrom
zuston:snapshotFallback

Conversation

@zuston

@zuston zuston commented Jul 28, 2026

Copy link
Copy Markdown
Member

Purpose

Fix KV tablet recovery when the latest remote snapshot is broken or missing. The recovery process now correctly detects missing snapshot files reported by different filesystem implementations, removes the broken snapshot metadata, and safely falls back to the previous available snapshot.

Close #3740

Brief change log

  • Detect missing snapshot data through the exception cause chain, including Hadoop's File does not exist error message.
  • Distinguish newly created and restored snapshot handles so discarding a restored broken snapshot does not delete shared files referenced by older snapshots.
  • Add regression coverage for broken snapshot cleanup and the latest snapshot → previous snapshot fallback flow.

Tests

API and Format

Documentation

@zuston

zuston commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

PTAL @fresh-borzoni @wuchong

@fresh-borzoni fresh-borzoni left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zuston Thank you, a good catch 👍 LGTM overall, couple of comments

* Returns whether the throwable or any of its causes indicates that snapshot data no longer
* exists in remote storage.
*/
public static boolean isSnapshotDataNotExists(Throwable throwable) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This deletes the znode and the files, so a wrong true here is unrecoverable. A standby during failover also says File does not exist while the file is fine, should we confirm with fileSystem.exists() before treating the snapshot as broken?

And should we match on FileNotFoundException / NoSuchFileException too? Otherwise S3, OSS and GCS each need another string added here later.

}

if (!isRegistered) {
if (ownsSharedFiles) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

discard() no longer touches the shared files, which is right, but it's not obvious from here who does.
What happens to the ones this snapshot alone referenced once its znode is gone?

}

public void registerKvFileHandles(SharedKvFileRegistry registry, long snapshotID) {
checkState(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason to drop the checkState completely? A double registration goes silent now.

// Simulate snapshot corruption by deleting only one private file while its metadata and
// shared files remain intact.
assertThat(snapshot2.getKvSnapshotHandle().getPrivateFileHandles()).isNotEmpty();
snapshot2.getKvSnapshotHandle().getPrivateFileHandles().get(0).getKvFileHandle().discard();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deleting a local file gives No such file or directory, so the Hadoop message from the issue isn't exercised on the replica path at all.
Could we add a small unit test on isSnapshotDataNotExists with a nested File does not exist chain?

List<Long> attemptedSnapshotIds = new ArrayList<>();
testKvSnapshotContext =
new TestSnapshotContext(snapshotKvTabletDir.getPath(), kvSnapshotStore);
new TestSnapshotContext(snapshotKvTabletDir.getPath(), kvSnapshotStore) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The round-trip is the important bit as production always hands out a snapshot deserialized from ZK, and the base context handing out the live object is what hid this.
Shall we move it into TestSnapshotContext instead of an anonymous subclass?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PK table bucket can't rebuild from the missing snapshot in the remote storage

2 participants