Flink API 解析 Flink Job 依赖的checkpoint 路径

引言

之前写一篇 Python 脚本解析 Flink _metadata 中依赖的 checkpoint 路径文章 Python解析 Flink Job 依赖的checkpoint 路径,代码比较暴力,直接按照 checkpoint 路径前缀判断,最近发现网上有通过 Flink API 解析 Flink Checkpoint 元数据代码的例子,参考了网上代码,并调试运行成功。

实现代码
java 复制代码
import org.apache.flink.core.fs.Path;
import org.apache.flink.runtime.checkpoint.Checkpoints;
import org.apache.flink.runtime.checkpoint.OperatorState;
import org.apache.flink.runtime.checkpoint.OperatorSubtaskState;
import org.apache.flink.runtime.checkpoint.metadata.CheckpointMetadata;
import org.apache.flink.runtime.state.*;
import org.apache.flink.runtime.state.filesystem.FileStateHandle;

import java.io.*;
import java.util.HashSet;
import java.util.Set;

/*
* @author: david.zhou
* @Flink Version: 1.14.4
* @Date: 2025/2/24 11:25
* @Description: Flink API 解析 Checkpoint 路径
* */

public class CheckpointMetadataParser {


    private static Set<String> ckPath = new HashSet<>();


    public static void main(String[] args) throws IOException {


        //  读取元数据文件
        File f=new File("/tmp/_metadata");
        FileInputStream fis=new FileInputStream(f);
        BufferedInputStream bis = new BufferedInputStream(fis);
        DataInputStream dis = new DataInputStream(bis);


        // 通过 Flink 的 Checkpoints 类解析元数据文件
        CheckpointMetadata savepoint = Checkpoints.loadCheckpointMetadata(dis,
                CheckpointMetadataParser.class.getClassLoader(), f.getAbsolutePath());
        // 打印当前的 CheckpointId
        System.out.println("CheckpointId:" + savepoint.getCheckpointId());

        // 遍历 OperatorState,这里的每个 OperatorState 对应一个 Flink 任务的 Operator 算子
        // 不要与 O
        // peratorState  和 KeyedState 混淆,不是一个层级的概念
        for(OperatorState operatorState :savepoint.getOperatorStates()) {
            //System.out.println(operatorState);
            // 当前算子的状态大小为 0 ,表示算子不带状态,直接退出
            if(operatorState.getStateSize() == 0){
                continue;
            }

            // 遍历当前算子的所有 subtask
            for(OperatorSubtaskState operatorSubtaskState: operatorState.getStates()) {
                // 解析 operatorSubtaskState 的 ManagedKeyedState
                parseManagedKeyedState(operatorSubtaskState);
                // 解析 operatorSubtaskState 的 ManagedOperatorState
                parseManagedOperatorState(operatorSubtaskState);
            }
        }

        for(String path: ckPath) {
            System.out.println("sstable 文件对应的 hdfs 位置:" + path);
        }
    }


    /**
     * 解析 operatorSubtaskState 的 ManagedKeyedState
     * @param operatorSubtaskState operatorSubtaskState
     */
    private static void parseManagedKeyedState(OperatorSubtaskState operatorSubtaskState) {
        // 遍历当前 subtask 的 KeyedState
        for(KeyedStateHandle keyedStateHandle:operatorSubtaskState.getManagedKeyedState()) {
            // 处理增量 Checkpoint
            if(keyedStateHandle instanceof IncrementalRemoteKeyedStateHandle) {
                IncrementalRemoteKeyedStateHandle incrementalStateHandle =
                        (IncrementalRemoteKeyedStateHandle) keyedStateHandle;

                // 获取 RocksDB 的 sharedState
                for (StateHandleID stateHandleID : incrementalStateHandle.getSharedStateHandleIDs()) {
                    StreamStateHandle stateHandle = incrementalStateHandle.getSharedState().get(stateHandleID);
                    //System.out.println("sstable 文件名:" + stateHandleID);
                    if (stateHandle instanceof FileStateHandle) {
                        Path filePath = ((FileStateHandle) stateHandle).getFilePath();
                        //System.out.println("filePath = " + filePath);
                        String ckSubPath = filePath.getPath().substring(0, filePath.getPath().indexOf("/shared"));
                        ckPath.add(ckSubPath);
                    }
                }
            }
        }
    }



    /**
     * 解析 operatorSubtaskState 的 ManagedOperatorState
     * @param operatorSubtaskState operatorSubtaskState
     */
    private static void parseManagedOperatorState(OperatorSubtaskState operatorSubtaskState) {
        // 遍历当前 subtask 的 OperatorState
        for(OperatorStateHandle operatorStateHandle:operatorSubtaskState.getManagedOperatorState()) {
            StreamStateHandle delegateStateHandle = operatorStateHandle.getDelegateStateHandle();
            if(delegateStateHandle instanceof FileStateHandle) {
                Path filePath = ((FileStateHandle) delegateStateHandle).getFilePath();
                //System.out.println("filePath: " + filePath.getPath());
            }
        }
    }


}
结果对比

对比了之前 Python 脚本demo,发现有结果不太一样,初步看 Python 中暴力解析部分元数据可能无效的。后续持续观察中,看看差异点。

相关推荐
TDengine (老段)3 小时前
TDengine 线程模型 — 网络、调度、执行
大数据·数据库·物联网·制造·时序数据库·tdengine·涛思数据
智购科技自动贩卖机6 小时前
自动售货机嵌入式状态机设计实战:从45个事件源到层次型状态机的工程重构
大数据·人工智能·stm32·物联网·重构·硬件架构
乐迪信息6 小时前
智慧港口船舶AI算法实现在线状态监测
大数据·人工智能·深度学习·算法·计算机视觉
Raas1006 小时前
MAI Gateway(魔芋企业级AI网关)对比分析:AI网关和API网关区别?企业级能力差距一览
大数据·人工智能·数据挖掘·mai gateway·企业级产品
Neighbor_OldY6 小时前
云上安全配置审计与误配置修复实战:从安全组、OSS、RAM到数据库的全栈排查复盘
大数据·运维·安全·云计算
工业甲酰苯胺7 小时前
AI低代码破局:制造业数智转型落地实战
大数据·人工智能·低代码·制造
头茬韭菜7 小时前
第 01 篇:「架构鸟瞰与进程启动链路」—— JobManager / TaskManager 从零长出来的完整调用链
架构·flink
大大大大晴天8 小时前
每天认识一个组件:流式存储Apache Fluss
大数据
熊野君8 小时前
第 4 章 技术产品经理核心能力模型
大数据·人工智能·产品经理
财复视界8 小时前
光智科技从“光学元件”到“稀散金属材料平台”的进化逻辑
大数据·人工智能·科技