Exactly Once语义在Flink中的实现

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
简介: Exactly Once语义在Flink中的实现

💨数据流和动态表

传统的SQL:🚩处理的 是有界的🚩执行查询可以访问完整的数据🚩批处理查询产生固定大小结果后终止流处理:🚩流是一个无限元组序列🚩执行查询无法访问所有数据🚩查询不断更新结果,永不终止

👇数据流和动态表转换如下

图片.png

不同数据处理保证的语义

✔At-most-once:出现故障的时候,啥也不做。数据处理不保证任何语义,处理时延迟低。

✔At-least-once:保证每条数据均至少被处理一次,一条数据可能存在重复消费。

✔Exactly Once:最严格的处理语义,从输出结果来看,每条数据均被消费且仅消费一次,仿佛故障丛飞发生。

💨Exactly Once和Checkpoint

从上面三个语义中我们看到Exactly Once语义是标准最高的。

比如说,我们可以把一个记录处理操作再划分为下面3个子操作: 🚩接收数据的操作。从数据源接收数据的操作。 🚩转换处理数据的操作。在这里面数据会被事先定义好的各种操作语义所处理。 🚩输出数据操作。将处理好后的结果数据输出到外部系统文件系统,或数据集等等。


其实在流处理过程中,失败现象就可能发生在上面3个步骤中的任何一步。如果要拿最高标准“Exactly Once”标准来看,我们要达到的理想效果应该是:
🚩数据只被处理过一次,这里面可以包括曾经处理失败,然后再读取原始数据进行处理。
🚩对于一个原始数据,我们保证最后结果数据输出是一致的,我们并不是说输出操作只是一次执行的。

🎈Checkpoint是Flink的一致性检查点。

Flink检查点的核心作用是确保状态正确,即使遇到程序中断,也要正确。记住这一基本点之后,我们用一个例子来看检查点是如何运行的。Flink为用户提供了用来定义状态的工具。

🚩Checkpoint是Flink 故障恢复机制的核心,就是应用状态的一致性检查点

🚩有状态流应用的一致检查点,其实就是所有任务的状态,在某个时间点的一份拷贝(一份快照);这个时间点,应该是所有任务都恰好处理完一个相同的输入数据的时候(如5这个数据虽然进了奇数流但是偶数流也应该做快照,因为属于同一个相同数据,只是没有被他处理)

🚩在JobManager中也有个Chechpoint的指针,指向了仓库的状态快照的一个拓扑图,为以后的数据故障恢复做准备

💨Chandy-Lamport分布式快照算法

✔分布式快照:特定时间点记录下来的分布式系统的全局状态(global state)。

✔分布式快照主要用途:故障恢复(即检查点)、死锁检测、垃圾收集等。

✔将分布式系统抽象为一张有向图:顶点称为进程(process),边称为channel。

Chandy-Lamport算法基于如下前提:在每对进程pi、pj之间都存在channel cij和cji,cij是output,cji是input。channel的网络可靠,缓存无限大,并且先进先出,即channel上的消息会不重不漏地按序到达。算法要达到如下的终极目标: 🚩最终产生的快照必须保证一致性; 🚩快照过程不能影响系统正常运行,更不能stop the world。  Chandy-Lamport 算法具体的工作流程主要包括下面三个部分: 🚩Initiating a snapshot: 也就是开始创建 snapshot,可以由系统中的任意一个进程发起🚩Propagating a snapshot: 系统中其他进程开始逐个创建 snapshot 的过程 🚩Terminating a snapshot: 算法结束条件

💨Flink端到端的Exactly-once语义

要真正实现流数据处理的Exactly-Once语义,一共要保证三个地方

🚩外部应用数据输入到source要保证Exactly-Once语义。🚩flink内部的数据处理要保证Exactly-Once语义。🚩sink将数据输入到外部应用要保证Exactly-Once语义。

🎈那么flink对这三个阶段是如何保证的呢?这里以kafka-flink-kafka为例简单概述:

🚩内部 —— 利用checkpoint机制,把状态存盘,发生故障的时候可以恢复,保证内部的状态一致性🚩source —— kafka consumer作为source,可以将偏移量保存下来,如果后续任务出现了故障,恢复的时候可以由连接器重置偏移量,重新消费数据,保证一致性🚩sink —— kafka producer作为sink,采用两阶段提交 sink,需要实现一个 TwoPhaseCommitSinkFunction

💨两阶段提交协议

在多个结点参与执行的分布式系统中,为了协调每个节点都能同时执行或者回滚某个事务性的操作,引入了一个中心节点来统一处理所有节点的执行逻辑,这个中心节点叫做协作者,被中心节点调度的其他业务节点叫做参与者。

阶段提交协议分为:预提交阶段和提交阶段

👇预提交阶段

🚩协作者向所有参与者发送一个commit消息🚩每个参与的协作者收到消息后,执行事务,但是不真正提交🚩若事务成功执行完成,发送一个成功的消息;执行失败,则发送一个失败的消息

👇提交阶段

🍳若协作者成功接收到所有参与者的vote yes的消息:

🚩协作者向所有参与者发送一个commit消息;🚩每个收到 commit消息的参与者释放执行事务所需的资源,并结束这次事务的执行;🚩完成步骤2后,参与者发送一个 ack消息给协作者;🚩协作者收到所有参与者的ack消息后,标识该事务执行完成。

🍳若协作者有收到参与者vote no的消息(或者发生等待超时) :

🚩协作者向所有参与者发送一个 rollback消息;🚩每个收到rollback 消息的参与者回滚事务的执行操作,并释放事务所占资源;🚩完成步骤2后,参与者发送个ack消息给协作者;🚩协作者收到所有参 与者的ack消息后,标识该事务成功完成回滚。

💨两阶段提交总结

🚩事务开启:在sink task向下游写数据之前,均会开启一 个事务,后续所有写数据的操作均在这个事务中执行,事务未提交前, 事务写入的数据下游不可读;

🚩预提交阶段: JobManager 开始下发Checkpoint Barrier,当各个处理逻辑接收到barrier 后停止处理后续数据,对当前状态制 作快照,此时sink也不在当前事务下继续处理数据(处理后续的数据需要新打开下一个事务)。状态制作成功则向JM成功 的消息,失败则发送失败的消息;

🚩提交阶段: 若JM收到所有预提交成功的消息,则向所有处理逻辑(包括sink)发送可以提交此次事务的消息,sink 接收到此 消息后,则完成此次事务的提交,此时下游可以读到这次事务写入的数据;若JM有收到预提交失败的消息,则通知所有处理 逻辑回滚这次事务的操作,此时sink则丢弃这次事务提交的数据下。


  • Flink Checkpoint机制的存在,是为了解决Flink任务在运行的过程中,由于各种问题导致任务异常中断后,能正常恢复。
  • Checkpoint能保证每条数据都对各个有状态的算子更新一次,sink 输出算子仍然可能下发重复的数据;
  • 严格意义的端到端的 Exactly-once语义需要特殊的sink 算子实现。


相关实践学习
基于Hologres轻松玩转一站式实时仓库
本场景介绍如何利用阿里云MaxCompute、实时计算Flink和交互式分析服务Hologres开发离线、实时数据融合分析的数据大屏应用。
Linux入门到精通
本套课程是从入门开始的Linux学习课程,适合初学者阅读。由浅入深案例丰富,通俗易懂。主要涉及基础的系统操作以及工作中常用的各种服务软件的应用、部署和优化。即使是零基础的学员,只要能够坚持把所有章节都学完,也一定会受益匪浅。
目录
相关文章
|
1月前
|
数据处理 Apache 流计算
Flink Watermark和时间语义
Flink Watermark和时间语义
35 2
|
1月前
|
Apache 流计算
【Flink】Flink的三种时间语义
【4月更文挑战第19天】【Flink】Flink的三种时间语义
|
8月前
|
程序员 API 数据安全/隐私保护
Flink--8、时间语义、水位线(事件和窗口、水位线和窗口的工作原理、生产水位线、水位线的传递、迟到数据的处理)
Flink--8、时间语义、水位线(事件和窗口、水位线和窗口的工作原理、生产水位线、水位线的传递、迟到数据的处理)
|
22天前
|
数据处理 Apache 流计算
Flink Watermark和时间语义
Flink Watermark和时间语义
|
1月前
|
Java 数据处理 分布式数据库
Flink中的Exactly-Once语义是什么?请解释其作用和实现原理。
Flink中的Exactly-Once语义是什么?请解释其作用和实现原理。
44 0
|
1月前
|
存储 算法 Java
读Flink源码谈设计:Exactly Once
将Flink应用至生产已有一段时间,刚上生产的时候有幸排查过因数据倾斜引起的Checkpoint超时问题——当时简单的了解了相关机制,最近正好在读Flink源码,不如趁这个机会搞清楚。 在这里,我们首先要搞清楚两种Exactly-Once的区别: - Exactly Once:在计算引擎内部,数据不丢失不重复。本质是通过Flink开启检查点进行Barrier对齐,即可做到。 - End to End Exactly Once:这意味着从数据读取、引擎处理到写入外部存储的整个过程中,数据都是不丢失不重复的。这要求数据源可重放,写入端支持事务的恢复和回滚或幂等。
540 0
|
1月前
|
消息中间件 Kafka 程序员
Flink(九)【时间语义与水位线】
Flink(九)【时间语义与水位线】
|
存储 消息中间件 关系型数据库
三、【计算】Exactly Once 语义在Flink中的实现(下) | 青训营笔记
三、【计算】Exactly Once 语义在Flink中的实现(下) | 青训营笔记
三、【计算】Exactly Once 语义在Flink中的实现(下) | 青训营笔记
|
SQL 数据处理 调度
Exactly Once 语义在 Flink 中的实现|青训营笔记
本篇文章主要讲述了Flink是如何实现在分布式环境下,对于task的处理做到exactly-once的语义的(结合二阶段提交协议)
143 0
Exactly Once 语义在 Flink 中的实现|青训营笔记
|
1天前
|
消息中间件 Java 关系型数据库
实时计算 Flink版操作报错合集之从 PostgreSQL 读取数据并写入 Kafka 时,遇到 "initial slot snapshot too large" 的错误,该怎么办
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
119 0