Flink checkpoint state相关概念
参考源码flink-1.11
Checkpoint完整的元数据
CompletedCheckpoint
,用来描述所有任务都完成确认后的checkpoint, 封装了一次 Checkpoint 完整的元数据信息.
public class CompletedCheckpoint implements Serializable {
// job id
private final JobID job;
// checkpoint id
private final long checkpointID;
// checkpoint触发的时间戳
private final long timestamp;
// checkpoint完成耗时
private final long duration;
// 本次 Checkpoint 中每个算子的 ID 及算子对应 State 信息
private final Map<OperatorID, OperatorState> operatorStates;
// checkpoint 的配置,主要描述:1. 类型(checkpoint或者savepoint)
// 2. 什么时候进行垃圾回收
private final CheckpointProperties props;
//checkpoint coordinator生成的状态封装而成
private final Collection<MasterState> masterHookStates;
// Checkpoint 存储路径
private final CompletedCheckpointStorageLocation storageLocation;
// 元数据句柄
private final StreamStateHandle metadataHandle;
// Checkpoint 目录地址
private final String externalPointer;
// 回调:主要用来更新isDiscard标识
@Nullable
private transient volatile CompletedCheckpointStats.DiscardCallback discardCallback;
}
算子级别的元数据 OperatorState
包含operator所有subtask的manager/raw operator状态和keyed-group状态句柄,因此代表operator的完整状态。
public class OperatorState implements CompositeStateHandle {
// operator id
private final OperatorID operatorID;
// checkpoint 时算子的并行度
private final int parallelism;
// checkpoint 时算子的 maxParallelism,也是key-group的个数
private final int maxParallelism;
// 当前 Operator 算子内,每个 subtask 持有的 State 信息,
// 这里 map 对应的 key 为 subtaskId,value 为 subtask 对应的 State,
// OperatorState 表示一个 算子级别的,OperatorSubtaskState 是 subtask 级别的。
// 如果一个算子有 10 个并行度,那么 OperatorState 有 10 个 OperatorSubtaskState
private final Map<Integer, OperatorSubtaskState> operatorSubtaskStates;
// operator coordinator的状态句柄,数据结构是byte数组,不存在时为空.
@Nullable
private ByteStreamStateHandle coordinatorState;
}
subtask级别的元数据 OperatorSubtaskState
operator中每个subtask的state,一个operator state 包含一个或多个subtask state,具体个数由operator对应的并发决定。
public class OperatorSubtaskState implements CompositeStateHandle {
// OperatorState 元数据维护在 OperatorStateHandle 中
// managed来自OperatorStateBackend快照,raw来自OperatorStateCheckpointOutputStream快照
private final StateObjectCollection<OperatorStateHandle> managedOperatorState;
private final StateObjectCollection<OperatorStateHandle> rawOperatorState;
// KeyedState 元数据存储维护在 KeyedStateHandle 中
// managedKeyedState来自KeyedStateBackend快照,raw来自KeyedStateCheckpointOutputStream快照
private final StateObjectCollection<KeyedStateHandle> managedKeyedState;
private final StateObjectCollection<KeyedStateHandle> rawKeyedState;
private final long stateSize;
// 以下两者和任务间的网络交互相关
// inputChannel的状态句柄
@Nonnull
private final StateObjectCollection<InputChannelStateHandle> inputChannelState;
// ResultSubpartition状态句柄
@Nonnull
private final StateObjectCollection<ResultSubpartitionStateHandle> resultSubpartitionState;
}
OperatorStateHandle 句柄
OperatorStateHandle
是一个接口,它只有一种实现OperatorStreamStateHandle
public class OperatorStreamStateHandle implements OperatorStateHandle {
// map 中 key 是 StateName,value 是 StateMetaInfo
// StateMetaInfo 中封装的是当前 State 在状态文件所处的 offset 和 Mode
private final Map<String, StateMetaInfo> stateNameToPartitionOffsets;
// OperatorState 状态文件句柄,可以读出状态数据,根据 StreamStateHandle,
// 即当前 subtask 可以从这个文件中读取状态数据。
private final StreamStateHandle delegateStateHandle;
}
// OperatorState 分布模式的枚举
enum Mode {
// 对应 getListState API,表示每个 subtask 只获取一部分状态数据,即:所有 subtask 的状态加起来是一份全量的。
SPLIT_DISTRIBUTE,
// 对应 getUnionListState API,表示每个 subtask 获取一份全量的状态数据
UNION,
// 对应 BroadcastState
BROADCAST
}
class StateMetaInfo implements Serializable {
// 当前 State 在状态文件所处的 offset 和 Mode
private final long[] offsets;
// OperatorState 的分布模式
private final Mode distributionMode;
}
KeyedStateHandle 句柄
KeyedStateHandle是checkpoint状态的句柄的基础,从故障中恢复时,该句柄将传递给所有与key-group范围重叠的任务。
这是一个接口,实现的非测试类中常用的是KeyGroupsStateHandle
和IncrementalRemoteKeyedStateHandle
。IncrementalLocalKeyedStateHandle
和 DirectoryKeyedStateHandle
是对 RocksDB Increment 模式的优化。RocksDB 在 Increment 模式开启 local-recovery
,可以在本地目录存放一份 State,当从 Checkpoint 处恢复时,不用去 dfs 去拉,而是直接从本地目录恢复 State。
KeyGroupsStateHandle 句柄
partition stream operator状态的句柄,主要有一系列的key-group快照组成。
public class KeyGroupsStateHandle implements StreamStateHandle, KeyedStateHandle {
// KeyedState 状态文件句柄,可以读出状态数据
private final StreamStateHandle stateHandle;
// KeyGroupRangeOffsets 封装了当前负责的 KeyGroupRange
// 及 KeyGroupRange 中每个 KeyGroup 对应的 State 在 stateHandle 的 offset 位置
private final KeyGroupRangeOffsets groupRangeOffsets;
}
public class KeyGroupRangeOffsets implements Iterable<Tuple2<Integer, Long>> , Serializable {
// 当前 Operator 当前 subtask 负责的 KeyGroupRange
private final KeyGroupRange keyGroupRange;
// 数组保存了每个 KeyGroup 对应的 offset,
// 所以:数组的长度 == keyGroupRange 中 KeyGroup 的数量
private final long[] offsets;
}
IncrementalRemoteKeyedStateHandle 句柄
增量快照的句柄,IncrementalRemoteKeyedStateHandle
应用于 RocksDB 增量 Checkpoint 模式, Checkpoint 实际存储的是 RocksDB 数据库的 sst 文件和 RocksDB 数据库的元数据文件。
主要包含:
- 创建的共享状态,其中包括自上次完成检查点以来生成的共享文件。如果检查点成功完成,则后续的检查点可以引用这些文件。
- 引用的共享状态,其中包括在先前检查点中实现的共享文件。在我们将其注册到{@link SharedStateRegistry}之前,所有引用的共享状态句柄都只是占位符,因此我们不会发送两次状态句柄,因为我们知道它们已经存在于检查点协调器上。
- 私有状态,包括所有其他文件,通常是可变文件,不能被其他检查点共享。
- 后端元状态,包括现有状态的信息。
public class IncrementalRemoteKeyedStateHandle implements IncrementalKeyedStateHandle {
// 标识状态后端,RocksDB 数据库的唯一 ID
private final UUID backendIdentifier;
// 这个 RocksDB 数据库负责的 KeyGroupRange
private final KeyGroupRange keyGroupRange;
private final long checkpointId;
// 共享state
private final Map<StateHandleID, StreamStateHandle> sharedState;
// 本次checkpoint独有的state
private final Map<StateHandleID, StreamStateHandle> privateState;
// 本次 Checkpoint 元数据的 StateHandle
private final StreamStateHandle metaStateHandle;
// 该注册表管理在(增量)检查点之间共享的状态,并负责删除在任何有效检查点中不再使用的共享状态。
private transient SharedStateRegistry sharedStateRegistry;
}
// StateHandleID 允许在状态句柄之间进行逻辑比较的唯一ID
// 逻辑上相等的两个状态句柄应始终返回相同的ID(什么是逻辑上相等的方式取决于实现方式)。例如,对于基于文件的状态,这可以基于完整文件路径的字符串表示形式。
public class StateHandleID extends StringBasedID {
// eg:keyString 为 sst 文件名
public StateHandleID(String keyString) {
super(keyString);
}
}