flink checkpoint 恢复_Flink解析 | Apache Flink结合Kafka构建端到端的ExactlyOnce处理

1ef379503fcd6eed8a8b7486ab5cbb69.png

周凯波(宝牛)

阿里巴巴技术专家,四川大学硕士,2010年毕业后加入阿里搜索事业部,从事搜索离线平台的研发工作,参与将搜索后台数据处理架构从MapReduce到Flink的重构。目前在阿里计算平台事业部,专注于基于Flink的一站式计算平台的建设。

文章目录: 

1. Apache Flink 应用程序中的 Exactly-Once 语义

2. Flink 应用程序端到端的 Exactly-Once 语义

3. 示例 Flink 应用程序启动预提交阶段

4. 在 Flink 中实现两阶段提交 Operator

5. 总结

Apache Flink 自2017年12月发布的1.4.0版本开始,为流计算引入了一个重要的里程碑特性:TwoPhaseCommitSinkFunction:

https://issues.apache.org/jira/browse/FLINK-7210

它提取了两阶段提交协议的通用逻辑,使得通过 Flink 来构建端到端的 Exactly-Once 程序成为可能。同时支持一些数据源(source)和输出端(sink),包括 Apache Kafka  0.11及更高版本。它提供了一个抽象层,用户只需要实现少数方法就能实现端到端的 Exactly-Once 语义。

有关 TwoPhaseCommitSinkFunction 的使用详见文档: TwoPhaseCommitSinkFunction。或者可以直接阅读 Kafka 0.11 sink 的文档: kafka。

https://ci.apache.org/projects/flink/flink-docs-release-1.4/api/java/org/apache/flink/streaming/api/functions/sink/TwoPhaseCommitSinkFunction.html

https://ci.apache.org/projects/flink/flink-docs-release-1.4/dev/connectors/kafka.html

接下来会详细分析这个新功能以及Flink的实现逻辑,分为如下几点:

  • 描述 Flink checkpoint 机制是如何保证 Flink 程序结果的 Exactly-Once 的;

  • 显示 Flink 如何通过两阶段提交协议与数据源和数据输出端交互,以提供端到端的 Exactly-Once 保证;

  • 通过一个简单的示例,了解如何使用 TwoPhaseCommitSinkFunction 实现 Exactly-Once 的文件输出。

Flink 应用程序中的 Exactly-Once 语义

当我们说『Exactly-Once』时,指的是每个输入的事件只影响最终结果一次。即使机器或软件出现故障,既没有重复数据,也不会丢数据。

Flink 很久之前就提供了 Exactly-Once 语义。在过去几年中,我们对 Flink 的 checkpoint 机制有过深入的描述,这是 Flink 有能力提供 Exactly-Once 语义的核心。Flink 文档还提供了该功能的全面概述:

https://ci.apache.org/projects/flink/flink-docs-release-1.4/ops/state/checkpoints.html

在继续之前,先看下对 checkpoint 机制的简要介绍,这对理解后面的主题至关重要。

一次 checkpoint 是以下内容的一致性快照:

  • 应用程序的当前状态

  • 输入流的位置

Flink 可以配置一个固定的时间点,定期产生 checkpoint,将 checkpoint 的数据写入持久存储系统,例如 S3 或 HDFS 。将 checkpoint 数据写入持久存储是异步发生的,这意味着 Flink 应用程序在 checkpoint 过程中可以继续处理数据。

如果发生机器或软件故障,重新启动后,Flink 应用程序将从最新的 checkpoint 点恢复处理; Flink 会恢复应用程序状态,将输入流回滚到上次 checkpoint 保存的位置,然后重新开始运行。这意味着 Flink 可以像从未发生过故障一样计算结果。

在 Flink 1.4.0 之前,Exactly-Once 语义仅限于 Flink 应用程序内部,并没有扩展到 Flink 数据处理完后发送的大多数外部系统。Flink 应用程序与各种数据输出端进行交互,开发人员需要有能力自己维护组件的上下文来保证 Exactly-Once 语义。

为了提供端到端的 Exactly-Once 语义 - 也就是说,除了 Flink 应用程序内部, Flink 写入的外部系统也需要能满足 Exactly-Once 语义 - 这些外部系统必须提供提交或回滚的方法,然后通过 Flink 的 checkpoint 机制来协调。

分布式系统中,协调提交和回滚的常用方法是两阶段提交协议。在下一节中,我们将讨论 Flink 的 TwoPhaseCommitSinkFunction 是如何利用两阶段提交协议来提供端到端的 Exactly-Once 语义。

Flink 应用程序端到端的 Exactly-Once 语义

我们将介绍两阶段提交协议,以及它如何在一个读写 Kafka 的 Flink 程序中实现端到端的 Exactly-Once 语义。Kafka 是一个流行的消息中间件,经常与 Flink 一起使用。Kafka 在最近的 0.11 版本中添加了对事务的支持。这意味着现在通过 Flink 读写 Kafka,并提供端到端的 Exactly-Once 语义有了必要的支持:

https://ci.apache.org/projects/flink/flink-docs-release-1.4/dev/connectors/kafka.html#kafka-011

Flink 对端到端的 Exactly-Once 语义的支持不仅局限于 Kafka ,您可以将它与任何一个提供了必要的协调机制的源/输出端一起使用。例如 Pravega,来自 DELL/EMC 的开源流媒体存储系统,通过 Flink 的 TwoPhaseCommitSinkFunction 也能支持端到端的 Exactly-Once 语义。

30bedfc07fe8ba8728d9d7a9e50b5619.png

exactly-once-two-phase-commit-1

在今天讨论的这个示例程序中,我们有:

  • 从 Kafka 读取的数据源(Flink 内置的 KafkaConsumer)

  • 窗口聚合

  • 将数据写回 Kafka 的数据输出端(Flink 内置的 KafkaProducer)

要使数据输出端提供 Exactly-Once 保证,它必须将所有数据通过一个事务提交给 Kafka。提交捆绑了两个 checkpoint 之间的所有要写入的数据。这可确保在发生故障时能回滚写入的数据。但是在分布式系统中,通常会有多个并发运行的写入任务的,简单的提交或回滚是不够的,因为所有组件必须在提交或回滚时“一致”才能确保一致的结果。Flink 使用两阶段提交协议及预提交阶段来解决这个问题。

在 checkpoint 开始的时候,即两阶段提交协议的“预提交”阶段。当 checkpoint 开始时,Flink 的 JobManager 会将 checkpoint barrier(将数据流中的记录分为进入当前 checkpoint 与进入下一个 checkpoint)注入数据流。

brarrier 在 operator 之间传递。对于每一个 operator,它触发 operator 的状态快照写入到 state backend。

0956da0f9624098a93c07e5c7595cb13.png

exactly-once-two-phase-commit-2

数据源保存消费 Kafka 的偏移量(offset),之后将 checkpoint barrier 传递给下一个 operator。

这种方式仅适用于 operator 具有『内部』状态。所谓内部状态,是指 Flink statebackend 保存和管理的 -例如,第二个 operator 中 window 聚合算出来的 sum 值。当一个进程有它的内部状态的时候,除了在 checkpoint 之前需要将数据变更写入到 state backend ,不需要在预提交阶段执行任何其他操作。Flink 负责在 checkpoint 成功的情况下正确提交这些写入,或者在出现故障时中止这些写入。

709a78e9644124c531f7435e76d25326.png

exactly-once-two-phase-commit-3

示例 Flink 应用程序启动预提交阶段

但是,当进程具有『外部』状态时,需要作些额外的处理。外部状态通常以写入外部系统(如 Kafka)的形式出现。在这种情况下,为了提供 Exactly-Once 保证,外部系统必须支持事务,这样才能和两阶段提交协议集成。

在本文示例中的数据需要写入 Kafka,因此数据输出端(Data Sink)有外部状态。在这种情况下,在预提交阶段,除了将其状态写入 state backend 之外,数据输出端还必须预先提交其外部事务。

4d538758b999a693181ae99cb1bd162e.png

exactly-once-two-phase-commit-4

当 checkpoint barrier 在所有 operator 都传递了一遍,并且触发的 checkpoint 回调成功完成时,预提交阶段就结束了。所有触发的状态快照都被视为该 checkpoint 的一部分。checkpoint 是整个应用程序状态的快照,包括预先提交的外部状态。如果发生故障,我们可以回滚到上次成功完成快照的时间点。

下一步是通知所有 operator,checkpoint 已经成功了。这是两阶段提交协议的提交阶段,JobManager 为应用程序中的每个 operator 发出 checkpoint 已完成的回调。

数据源和 window operator 没有外部状态,因此在提交阶段,这些 operator 不必执行任何操作。但是,数据输出端(Data Sink)拥有外部状态,此时应该提交外部事务。

d33a6ea189d4875a118df4a07f032a68.png

exactly-once-two-phase-commit-5

我们对上述知识点总结下:

  • 一旦所有 operator 完成预提交,就提交一个 commit。

  • 如果至少有一个预提交失败,则所有其他提交都将中止,我们将回滚到上一个成功完成的 checkpoint 。

  • 在预提交成功之后,提交的 commit 需要保证最终成功 - operator 和外部系统都需要保障这点。如果 commit 失败(例如,由于间歇性网络问题),整个 Flink 应用程序将失败,应用程序将根据用户的重启策略重新启动,还会尝试再提交。这个过程至关重要,因为如果 commit 最终没有成功,将会导致数据丢失。

因此,我们可以确定所有 operator 都同意 checkpoint 的最终结果:所有 operator 都同意数据已提交,或提交被中止并回滚

在 Flink 中实现两阶段提交 Operator

完整的实现两阶段提交协议可能有点复杂,这就是为什么 Flink 将它的通用逻辑提取到抽象类 TwoPhaseCommitSinkFunction 中的原因。

接下来基于输出到文件的简单示例,说明如何使用 TwoPhaseCommitSinkFunction 。用户只需要实现四个函数,就能为数据输出端实现 Exactly-Once 语义:

  • beginTransaction - 在事务开始前,我们在目标文件系统的临时目录中创建一个临时文件。随后,我们可以在处理数据时将数据写入此文件。

  • preCommit - 在预提交阶段,我们刷新文件到存储,关闭文件,不再重新写入。我们还将为属于下一个 checkpoint 的任何后续文件写入启动一个新的事务。

  • commit - 在提交阶段,我们将预提交阶段的文件原子地移动到真正的目标目录。需要注意的是,这会增加输出数据可见性的延迟。

  • abort - 在中止阶段,我们删除临时文件。

我们知道,如果发生任何故障,Flink 会将应用程序的状态恢复到最新的一次 checkpoint 点。一种极端的情况是,预提交成功了,但在这次 commit 的通知到达 operator 之前发生了故障。在这种情况下,Flink 会将 operator 的状态恢复到已经预提交,但尚未真正提交的状态。

我们需要在预提交阶段保存足够多的信息到 checkpoint 状态中,以便在重启后能正确的中止或提交事务。在这个例子中,这些信息是临时文件和目标目录的路径。

TwoPhaseCommitSinkFunction 已经把这种情况考虑在内了,并且在从 checkpoint 点恢复状态时,会优先发出一个 commit 。我们需要以幂等方式实现提交,一般来说,这并不难。在这个示例中,我们可以识别出这样的情况:临时文件不在临时目录中,但已经移动到目标目录了。

在 TwoPhaseCommitSinkFunction 中,还有一些其他边界情况也会考虑在内,请参考 Flink 文档了解更多信息:

https://ci.apache.org/projects/flink/flink-docs-release-1.4/api/java/org/apache/flink/streaming/api/functions/sink/TwoPhaseCommitSinkFunction.html

总结

总结下本文涉及的一些要点:

  • Flink 的 checkpoint 机制是支持两阶段提交协议并提供端到端的 Exactly-Once 语义的基础。

  • 这个方案的优点是: Flink 不像其他一些系统那样,通过网络传输存储数据 - 不需要像大多数批处理程序那样将计算的每个阶段写入磁盘。

  • Flink 的 TwoPhaseCommitSinkFunction 提取了两阶段提交协议的通用逻辑,基于此将 Flink 和支持事务的外部系统结合,构建端到端的 Exactly-Once 成为可能。

  • 从 Flink 1.4.0 开始,Pravega 和 Kafka 0.11 producer 都提供了 Exactly-Once 语义;Kafka 在0.11版本首次引入了事务,为在 Flink 程序中使用 Kafka producer 提供 Exactly-Once 语义提供了可能性。

  • Kafaka 0.11 producer 的事务是在 TwoPhaseCommitSinkFunction 基础上实现的,和 at-least-once producer 相比只增加了非常低的开销。

这是个令人兴奋的功能,期待 Flink TwoPhaseCommitSinkFunction 在未来支持更多的数据接收端。

via:

https://www.ververica.com/blog/end-to-end-exactly-once-processing-apache-flink-apache-kafka

作者:Piotr Nowojski

翻译:周凯波

1ce66bd17a330c4100666c9e096c8893.png

0bdab4bc2470dce729e35010fddc817c.gif

大家工作学习遇到HBase技术问题,把问题发布到HBase技术社区论坛http://hbase.group,欢迎大家论坛上面提问留言讨论。想了解更多HBase技术关注HBase技术社区公众号(微信号:hbasegroup),非常欢迎大家积极投稿。

d654fdb0f32f7163ddbeb478a06a937c.png

本群为HBase+Spark技术交流讨论,整合最优质的专家资源和技术资料会定期开展线下技术沙龙,专家技术直播,专家答疑活动

点击链接钉钉入群:https://dwz.cn/Fvqv066s或扫码进群

9448c80a821eccebdcb9adda8f5cf45d.png

本群为Cassandra技术交流讨论,整合最优质的专家资源和技术资料会定期开展线下技术沙龙,专家技术直播,专家答疑活动

Cassandra 社区钉钉大群:https://c.tb.cn/F3.ZRTY0o

2cbd195e5a9f8048a75e33bd0b1c6763.png

Cassandra 技术社区微信公众号:

bc40d10bb5b70655a6f4056f90f8260e.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/555124.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java通过ftl模板导出word最详细教程

首先用office建一个word文档 参数写自己查询出来的字段,我在这里房里图片是方便找到位置替换为64位编码 模板创建好之后,另存为Word 2003 XML文档(*.xml) 存储为别的可能会报错,我只用这一种 存储为xml之后千万不要用word打开,最…

封装html ui 控件,聊聊前端 UI 组件:组件设计

本文首发于欧雷流。由于我会时不时对文章进行补充、修正和润色,为了保证所看到的是最新版本,请阅读原文。在本系列文章《聊聊前端 UI 组件:组件体系》中初步说明了 UI 组件的架构设计,本文将在此基础上进一步展开说说那篇文章中一…

live555推流rtsp_Hi3518 RTSP推流

1、openssl编译下载地址:http://distfiles.macports.org/openssl/解压后进入源码根路径执行./config no-asm no-async --prefix/home/chenyc/project/hi3518e/Hi3518E_SDK_V1.0.3.0/armlib/openssl --cross-compile-prefixarm-hisiv300-linux-#打开生成的makefile 删除-m64 在…

怎么两边同时取ln_男生“两边铲光”发型out了?试试这4款吧,剪完清爽又帅气...

发型对于男生来说是特别重要的!女生可以通过化妆来让自己变得更完美,而男生想要改变自己的形象,是不敢轻易化妆的,只有通过改变自己的发型,才能更好地展现自己的魅力。现下男生最流行的发型,莫过于“两边铲…

ionic 修改组件默认样式_开源Magpie:组件库详解

开源项目专题系列(八)1.开源项目名称:magpie_fly2.github地址:https://github.com/wuba/magpie_fly3.简介:magpie_fly 是58集体出品组件库,统一管理日常开发中的基础组件及高阶组件,并提供了相对友好的方式介绍组件的具…

口袋之旅html5超强账号,口袋之旅特攻排行榜 强大的绝对能力

历史上是在金银版分了精灵的特攻物攻,在宝石版分了技能的特攻物攻,让很多精灵和技能得以重生。口袋之旅采用的是第二世代的精灵加第三世代的技能分类,于是特攻手也成为了一个需要挑选的部分,本文继续为你缩小挑选范围。特攻种族值…

使用ftl生成word

背景:根据word模板下载word。word里面需要填充数据,格式是固定的。首先在word中给数据起个变量名称 需要更换的数据改成${变量名!},必须是英文的,加感叹号是为了防止null,如果数据是null,文档下载下来后会直…

什么叫做项目孵化_蓝莓孵化营12进5争夺战,项目人绽放自我不留遗憾

国内首档互联网职业竞技励志节目《蓝莓孵化营》,今晚22点在浙江卫视播出第十一期。本期节目中,第三事业群的12组项目人将为最终的5张终极考核入场券展开争夺。这一次,他们比拼的是以“2020”为主题的短视频,每一组项目人都拼尽了自…

一开机就提示脱机工作_「华为手机维修自学教程」华为手机的开机触发电路 华为维修技巧...

谈谈华为的开机触发电路华为这段时间的新闻不少,大家应该都有说了解。华为的强大意味着华为手机的维修市场越来越大。从事维修的朋友们你们准备好了吗?今天给大家说一说,华为手机的开机触发电路。修苹果手机的朋友大家都知道,电源…

SpringBoot 整合mybatis-plus 高级功能及用法详解

springboot 整合mybatis-plus 高级功能及用法详解 学习并使用mybatis-plus的一些高级功能的用法例如&#xff1a; AR模式、 乐观锁 、逻辑删除 、自动填充、数据保护等功能 为了方便演示&#xff0c;咱们还是新建一个全新的项目 引入mp依赖 <dependency><groupId>…

8除以2表示什么意思_八字中劫财,比肩分别表示什么意思

◆◆比劫与其他十神的生克关系◆◆食伤&#xff1a;比劫生食伤财星&#xff1a;比劫克财星官星&#xff1a;官星克比劫印星&#xff1a;印星生比劫◆◆比劫帮身◆◆八字术语&#xff0c;比肩劫财均可助日干之力&#xff0c;如甲见甲(比)、乙(劫)、寅(禄)、卯(刃)之类&#xff0…

MyBatis-plus 自动填充MetaObjectHandler不生效问题

背景 在项目中经常遇到一些数据需要自动填充&#xff0c;填充方法都是同一种规则&#xff0c;例如创建时间等。 1 自动填充方法配置 1.1 实体类添加注解 1.2 在handler包下实现元对象处理器接口 import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import o…

博途变量类型_PLC数据类型(UDT)

UDT类型是一种由多个不同数据类型元素组成的数据结构&#xff0c;元素可以是基本数据类型&#xff0c;也可以是STRUCT、数组等复杂数据类型以及其它UDT等。UDT类型嵌套UDT类型的深度限制为 8 级。UDT类型可以在DB、OB/FC/FB接口区处使用。从TIA 博途 V13SP1 开始&#xff0c;S7…

Mybatis-Plus条件参数查询手册

【引言】 使用mybatis-plus框架的基础上&#xff0c;直接使用其中的条件参数进行查询还是很方便的。但每次使用到像大于、不等于这样一些不常用条件时&#xff0c;都需要现查&#xff0c;所以记录在这篇博客里&#xff0c;当作一个自己的查询手册。 【手册】 查询方式说明se…

java 最快平衡几个值_Java 集合框架面试问题集锦

Java集合框架(例如基本的数据结构)里包含了最常见的Java常见面试问题。很好地理解集合框架&#xff0c;可以帮助你理解和利用Java的一些高级特性。下面是面试Java核心技术的一些很实用的问题。Q&#xff1a;最常见的数据结构有哪些&#xff0c;在哪些场景下应用它们&#xff1f…

mybatis-plus 如何判断参数是否为空并作为查询条件

判断参数是否为空并作为查询条件 Overridepublic Page<DemandEntity> selectByDepartmentDisplay(DemandEntity demandEntity) {EntityWrapper<DemandEntity> wrapper new EntityWrapper<DemandEntity>();wrapper.eq(!StringUtils.isNullOrEmpty(demandEnt…

linux 总数 进程_Linux运用一些常用命令,优秀的PHPer都需掌握

作为一名优秀的phper&#xff0c;Linux是必备的一项技能&#xff0c;工作3-5年的基本能明白我讲的道理&#xff01;今天搜集整理了一些Linux服务器运维常用命令,希望对大家有帮助&#xff1a;1.删除0字节文件find -type f -size 0 -exec rm -rf {} 2.查看进程按内存从大到小排列…

c语言高低位拷贝_C语言指针详解

1为什么使用指针 假如我们定义了 char a’A’ &#xff0c;当需要使用 ‘A’ 时&#xff0c;除了直接调用变量 a &#xff0c;还可以定义 char *p&a &#xff0c;调用 a 的地址&#xff0c;即指向 a 的指针 p &#xff0c;变量 a&#xff08; char 类型&#xff09;只占了一…

MybatisPlus中@TableField注解的使用详解

MybatisPlus中TableField注解的使用详解 实现 官方文档说明&#xff1a; com.baomidou.mybatisplus.annotations.TableField TableField注解新增属性 update 预处理 set 字段自定义注入 (讲解&#xff1a;比如我们使用mybatisplus自带的insert()方法向数据库插入数据时&…

dataframe记录数_大数据系列之Spark SQL、DataFrame和RDD数据统计与可视化

Spark大数据分析中涉及到RDD、Data Frame和SparkSQL的操作&#xff0c;本文简要介绍三种方式在数据统计中的算子使用。1、在IPython Notebook运行Python Spark程序IPython Notebook具备交互式界面&#xff0c;可以在Web界面输入Python命令后立刻看到结果&#xff0c;还可将数据…