源码解析flink的GenericWriteAheadSink为什么做不到精确一次输出

背景

GenericWriteAheadSink是可以用于几乎是精准一次输出的场景,为什么说是几乎精准一次呢?我们从源码的角度分析一下

GenericWriteAheadSink做不到精准一次输出的原因

首先我们看一下flink检查点完成后通知GenericWriteAheadSink开始进行分段的记录输出并提交事务的代码

java 复制代码
pubblic void notifyCheckpointComplete(long checkpointId) throws Exception {
        super.notifyCheckpointComplete(checkpointId);

        synchronized (pendingCheckpoints) {
            Iterator<PendingCheckpoint> pendingCheckpointIt = pendingCheckpoints.iterator();
            while (pendingCheckpointIt.hasNext()) {

                PendingCheckpoint pendingCheckpoint = pendingCheckpointIt.next();

                long pastCheckpointId = pendingCheckpoint.checkpointId;
                int subtaskId = pendingCheckpoint.subtaskId;
                long timestamp = pendingCheckpoint.timestamp;
                StreamStateHandle streamHandle = pendingCheckpoint.stateHandle;

                if (pastCheckpointId <= checkpointId) {
                    try {
                        if (!committer.isCheckpointCommitted(subtaskId, pastCheckpointId)) {
                            try (FSDataInputStream in = streamHandle.openInputStream()) {
                            //开始把分段记录列表的记录进行输出
                                boolean success =
                                        sendValues(
                                                new ReusingMutableToRegularIteratorWrapper<>(
                                                        new InputViewIterator<>(
                                                                new DataInputViewStreamWrapper(in),
                                                                serializer),
                                                        serializer),
                                                pastCheckpointId,
                                                timestamp);
                                if (success) {
                                   //把分段记录列表输出成功后提交事务
                                    committer.commitCheckpoint(subtaskId, pastCheckpointId);
                                    streamHandle.discardState();
                                    pendingCheckpointIt.remove();
                                }
                            }
                        } else {
                            streamHandle.discardState();
                            pendingCheckpointIt.remove();
                        }
                    } catch (Exception e) {
                        // we have to break here to prevent a new (later) checkpoint
                        // from being committed before this one
                        LOG.error("Could not commit checkpoint.", e);
                        break;
                    }
                }
            }
        }
    }

从上面的源码可以看出,sendValue方法和提交事务commitCheckpoint方法并不能保证原子性,这就意味着如果sendValue执行了一部分或者全部,而提交事务方法commitCheckpoint失败,那么此时这个检查点对应的事务相当于就没有完成,在下一个检查点的通知消息中,会把历史检查点的事务重新sendValue然后进行commit一次,这就意味着相同的记录会执行两次sendValue操作,这就是GenericWriteAheadSink不能保证精准一次的原因

相关推荐
QiLinkOS5 分钟前
企业知识产权战略的“X光”透视报告:从“外包代工”到“法律军火库”的终极分野
大数据·人工智能·dna双螺旋归因模型·技术专利避坑指南·qilink·技术专利风险情报·技术专利洞察
Java面试题总结9 分钟前
GatewayWorker 从零到一完整指南
java
脉动数据行情21 分钟前
Java OkHttp 完整封装 GC COMEX 美黄金实时盘口定时拉取工具类
java·okhttp·comex 黄金·外盘贵金属
敖行客 Allthinker26 分钟前
IM 融合专题:后端架构师的核心修炼
java·开发语言·数据库
HAPPY酷36 分钟前
【ROS2】16G 内存笔记本跑 ROS2 仿真?VMware 虚拟机“保姆级”配置指南 (R9 7940HX + RTX 4060)
java·linux·ide·windows·pycharm
折哥的程序人生 · 物流技术专研9 小时前
第4篇:Lambda 简化策略模式(Java 8+)
java·设计模式·策略模式·函数式编程·lambda·代码简化·扩充系列
researcher-Jiang10 小时前
高性能计算之OpenMP——超算习堂学习1
android·java·学习
IT新视界10 小时前
大数据开发工具-Transwarp Data Studio
大数据
donoot10 小时前
Linux系统下图书馆级电子书全自动标准化分类整理完整实施方案
大数据·linux·运维·电子书管理
Elastic 中国社区官方博客11 小时前
如何比较两个 Elasticsearch 索引并找出缺失的文档
大数据·运维·数据库·elasticsearch·搜索引擎