Skip to content

Commit b62de02

Browse files
committed
[FLINK-29802][state] Changelog supports native savepoint
1 parent 6be297d commit b62de02

2 files changed

Lines changed: 78 additions & 0 deletions

File tree

flink-state-backends/flink-statebackend-changelog/src/main/java/org/apache/flink/state/changelog/AbstractChangelogStateBackend.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package org.apache.flink.state.changelog;
2020

2121
import org.apache.flink.annotation.Internal;
22+
import org.apache.flink.core.execution.SavepointFormatType;
2223
import org.apache.flink.metrics.MetricGroup;
2324
import org.apache.flink.runtime.execution.Environment;
2425
import org.apache.flink.runtime.state.AbstractKeyedStateBackend;
@@ -108,6 +109,11 @@ public StateBackend getDelegatedStateBackend() {
108109
return delegatedStateBackend;
109110
}
110111

112+
@Override
113+
public boolean supportsSavepointFormat(SavepointFormatType formatType) {
114+
return delegatedStateBackend.supportsSavepointFormat(formatType);
115+
}
116+
111117
protected abstract <K> CheckpointableKeyedStateBackend<K> restore(
112118
Environment env,
113119
String operatorIdentifier,

flink-state-backends/flink-statebackend-changelog/src/main/java/org/apache/flink/state/changelog/ChangelogKeyedStateBackend.java

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.apache.flink.metrics.MetricGroup;
3131
import org.apache.flink.runtime.checkpoint.CheckpointOptions;
3232
import org.apache.flink.runtime.checkpoint.CheckpointType;
33+
import org.apache.flink.runtime.checkpoint.SnapshotType;
3334
import org.apache.flink.runtime.state.AbstractKeyedStateBackend;
3435
import org.apache.flink.runtime.state.CheckpointStateOutputStream;
3536
import org.apache.flink.runtime.state.CheckpointStorageLocationReference;
@@ -67,6 +68,7 @@
6768
import org.apache.flink.state.changelog.restore.ChangelogRestoreTarget;
6869
import org.apache.flink.state.changelog.restore.FunctionDelegationHelper;
6970
import org.apache.flink.state.common.PeriodicMaterializationManager.MaterializationTarget;
71+
import org.apache.flink.util.concurrent.FutureUtils;
7072

7173
import org.apache.flink.shaded.guava31.com.google.common.io.Closer;
7274

@@ -89,6 +91,7 @@
8991
import java.util.TreeMap;
9092
import java.util.concurrent.CompletableFuture;
9193
import java.util.concurrent.ExecutionException;
94+
import java.util.concurrent.FutureTask;
9295
import java.util.concurrent.RunnableFuture;
9396
import java.util.concurrent.TimeUnit;
9497
import java.util.concurrent.TimeoutException;
@@ -379,6 +382,11 @@ public RunnableFuture<SnapshotResult<KeyedStateHandle>> snapshot(
379382
@Nonnull CheckpointStreamFactory streamFactory,
380383
@Nonnull CheckpointOptions checkpointOptions)
381384
throws Exception {
385+
386+
if (checkpointOptions.getCheckpointType().isSavepoint()) {
387+
return nativeSavepoint(checkpointId, timestamp, streamFactory, checkpointOptions);
388+
}
389+
382390
// The range to upload may overlap with the previous one(s). To reuse them, we could store
383391
// the previous results either here in the backend or in the writer. However,
384392
// materialization may truncate only a part of the previous result and the backend would
@@ -416,6 +424,57 @@ public RunnableFuture<SnapshotResult<KeyedStateHandle>> snapshot(
416424
.thenApply(this::castSnapshotResult));
417425
}
418426

427+
private RunnableFuture<SnapshotResult<KeyedStateHandle>> nativeSavepoint(
428+
long checkpointId,
429+
long timestamp,
430+
@Nonnull CheckpointStreamFactory streamFactory,
431+
@Nonnull CheckpointOptions checkpointOptions)
432+
throws Exception {
433+
434+
SnapshotType.SharingFilesStrategy sharingFilesStrategy =
435+
checkpointOptions.getCheckpointType().getSharingFilesStrategy();
436+
if (sharingFilesStrategy != SnapshotType.SharingFilesStrategy.NO_SHARING) {
437+
throw new UnsupportedOperationException(
438+
"ChangelogKeyedStateBackend doesn't support native savepoint with SharingFilesStrategy: "
439+
+ sharingFilesStrategy);
440+
}
441+
442+
long materializationID = materializedId++;
443+
// For NO_SHARING native savepoint, trigger delegated one
444+
RunnableFuture<SnapshotResult<KeyedStateHandle>> delegatedSnapshotResult =
445+
keyedStateBackend.snapshot(
446+
materializationID, timestamp, streamFactory, checkpointOptions);
447+
448+
materializationIdByCheckpointId.put(checkpointId, materializationID);
449+
return new FutureTask<SnapshotResult<KeyedStateHandle>>(
450+
() -> {
451+
SnapshotResult<KeyedStateHandle> result =
452+
FutureUtils.runIfNotDoneAndGet(delegatedSnapshotResult);
453+
return castSnapshotResult(
454+
buildSnapshotResult(
455+
checkpointId,
456+
SnapshotResult.empty(),
457+
new ChangelogSnapshotState(
458+
getMaterializedResult(result), materializationID)));
459+
}) {
460+
@Override
461+
public boolean cancel(boolean mayInterruptIfRunning) {
462+
return delegatedSnapshotResult.cancel(mayInterruptIfRunning)
463+
&& super.cancel(mayInterruptIfRunning);
464+
}
465+
466+
@Override
467+
public boolean isCancelled() {
468+
return delegatedSnapshotResult.isCancelled() && super.isCancelled();
469+
}
470+
471+
@Override
472+
public boolean isDone() {
473+
return delegatedSnapshotResult.isDone() && super.isDone();
474+
}
475+
};
476+
}
477+
419478
@SuppressWarnings("unchecked")
420479
private SnapshotResult<KeyedStateHandle> castSnapshotResult(SnapshotResult<?> snapshotResult) {
421480
return (SnapshotResult<KeyedStateHandle>) snapshotResult;
@@ -1013,6 +1072,19 @@ private class ChangelogSnapshotState {
10131072
/** ID of this materialization corresponding to the nested backend checkpoint ID. */
10141073
private final long materializationID;
10151074

1075+
/**
1076+
* Construct a ChangelogSnapshotState with empty non-materialized part, which could be used
1077+
* when triggering manual materialization.
1078+
*/
1079+
public ChangelogSnapshotState(
1080+
List<KeyedStateHandle> materializedSnapshot, long materializationID) {
1081+
this(
1082+
materializedSnapshot,
1083+
Collections.emptyList(),
1084+
SequenceNumber.of(Long.MAX_VALUE),
1085+
materializationID);
1086+
}
1087+
10161088
public ChangelogSnapshotState(
10171089
List<KeyedStateHandle> materializedSnapshot,
10181090
List<ChangelogStateHandle> restoredNonMaterialized,

0 commit comments

Comments
 (0)