Search before asking
Description
When the Kafka or Fluss Durable ActionState backend is enabled, restoring a job from a checkpoint can leave duplicated recovery state permanently retained in each subtask's in-memory cache.
During recovery:
- Recovery markers are stored in
UnionListState, so every restored subtask receives all markers.
KafkaActionStateStore.rebuildState() merges the markers and scans every referenced Kafka partition.
FlussActionStateStore.rebuildState() similarly merges the markers and scans every referenced Fluss bucket.
- As a result, every subtask's
actionStates map contains the complete recovery tail, including states for keys owned by other subtasks.
For example, with parallelism 2:
After restore:
subtask 0 cache: {A, B}
subtask 1 cache: {A, B}
Key ownership:
subtask 0 owns A
subtask 1 owns B
When a subsequent checkpoint completes, snapshotLastCompletedSequenceNumbers() scans the current subtask's keyed state only. Therefore, notifyCheckpointComplete() invokes:
subtask 0: pruneState(A, ...)
subtask 1: pruneState(B, ...)
The resulting caches are:
subtask 0 cache: {B}
subtask 1 cache: {A}
The entries belonging to other subtasks are never passed to pruneState() and remain reachable until the current operator attempt is closed or fails again.
How to reproduce
-
Enable the Kafka or Fluss Durable ActionState backend.
-
Set operator parallelism to 2.
-
Choose keys A and B such that they are assigned to different subtasks.
-
Complete checkpoint C0.
-
After C0, write ActionState records for both A and B.
-
Trigger failover before the next checkpoint completes.
-
Restore from C0.
-
Inspect the actionStates map in both subtasks.
Both maps contain A and B:
subtask 0: {A, B}
subtask 1: {A, B}
-
Allow the replayed actions for A and B to complete.
-
Complete checkpoint C1.
-
Inspect both caches again.
The current implementation leaves:
subtask 0: {B}
subtask 1: {A}
Version and environment
Apache Flink Agents 0.2+
Are you willing to submit a PR?
Search before asking
Description
When the Kafka or Fluss Durable ActionState backend is enabled, restoring a job from a checkpoint can leave duplicated recovery state permanently retained in each subtask's in-memory cache.
During recovery:
UnionListState, so every restored subtask receives all markers.KafkaActionStateStore.rebuildState()merges the markers and scans every referenced Kafka partition.FlussActionStateStore.rebuildState()similarly merges the markers and scans every referenced Fluss bucket.actionStatesmap contains the complete recovery tail, including states for keys owned by other subtasks.For example, with parallelism 2:
When a subsequent checkpoint completes, snapshotLastCompletedSequenceNumbers() scans the current subtask's keyed state only. Therefore, notifyCheckpointComplete() invokes:
The resulting caches are:
The entries belonging to other subtasks are never passed to pruneState() and remain reachable until the current operator attempt is closed or fails again.
How to reproduce
Enable the Kafka or Fluss Durable ActionState backend.
Set operator parallelism to 2.
Choose keys A and B such that they are assigned to different subtasks.
Complete checkpoint C0.
After C0, write ActionState records for both A and B.
Trigger failover before the next checkpoint completes.
Restore from C0.
Inspect the
actionStatesmap in both subtasks.Both maps contain A and B:
Allow the replayed actions for A and B to complete.
Complete checkpoint C1.
Inspect both caches again.
The current implementation leaves:
Version and environment
Apache Flink Agents 0.2+
Are you willing to submit a PR?