flink checkpoint 恢复_干货:Flink+Kafka 0.11端到端精确一次处理语义实现

2017年12月Apache Flink社区发布了1.4版本。该版本正式引入了一个里程碑式的功能:两阶段提交Sink,即TwoPhaseCommitSinkFunction。该SinkFunction提取并封装了两阶段提交协议中的公共逻辑,自此Flink搭配特定source和sink(特别是0.11版本Kafka)搭建精确一次处理语义( exactly-once semantics)应用成为了可能。作为一个抽象类TwoPhaseCommitSinkFunction提供了一个抽象层供用户自行实现特定方法来支持 exactly-once semantics。

用户可以阅读Java文档来学习如何使用TwoPhaseCommitSinkFunction,或者参考Flink官网文档来了解FlinkKafkaProducer011是如何支持 exactly-once semantics的,因为后者正是基于TwoPhaseCommitSinkFunction实现的。

本文将深入讨论一下Flink 1.4这个新特性以及其背后的设计思想。在本文中我们将:

1. 描述Flink应用中的checkpoint如何帮助确保exactly-once semantics

2. 展示Flink如何通过两阶段提交协议与source和sink交互以实现端到端的  exactly-once semantics交付保障

3. 给出一个使用TwoPhaseCommitSinkFunction实现 exactly-once semantics的文件Sink实例

11438d3ea501f05ae1e42c748bf773c5d.pngFlink应用的仅一次处理

当谈及仅一次处理时,我们真正想表达的是每条输入消息只会影响最终结果一次!【译者:影响应用状态一次,而非被处理一次】即使出现机器故障或软件崩溃,Flink也要保证不会有数据被重复处理或压根就没有被处理从而影响状态。长久以来Flink一直宣称支持 exactly-once semantics是指在一个Flink应用内部。在过去的几年间,Flink开发出了checkpointing机制,而它则是提供这种应用内仅一次处理的基石。

在继续之前我们简要总结一下checkpointing算法,这对于我们了解本文内容至关重要。简单来说,一个Flink checkpoint是一个一致性快照,它包含:

1. 应用的当前状态

2. 消费的输入流位置

Flink会定期地产生checkpoint并且把这些checkpoint写入到一个持久化存储上,比如S3或HDFS。这个写入过程是异步的,这就意味着Flink即使在checkpointing过程中也是不断处理输入数据的。

如果出现机器或软件故障,Flink应用重启后会从最新成功完成的checkpoint中恢复——重置应用状态并回滚状态到checkpoint中输入流的正确位置,之后再开始执行数据处理,就好像该故障或崩溃从未发生过一般。

在Flink 1.4版本之前,仅一次处理只限于Flink应用内。Flink处理完数据后需要将结果发送到外部系统,这个过程中Flink并不保证仅一次处理。但是Flink应用通常都需要接入很多下游子系统,而开发人员很希望能在多个系统上维持仅一次处理语义,即维持端到端的仅一次处理语义。

为了提供端到端的仅一次处理语义,仅一次处理语义必须也要应用于Flink写入数据的外部系统——故这些外部系统必须提供一种手段允许提交或回滚这些写入操作,同时还要保证与Flink checkpoint能够协调使用。

在分布式系统中协调提交和回滚的一个常见方法就是使用两阶段提交协议。下一章节中我们将讨论下Flink的TwoPhaseCommitSinkFunction是如何利用两阶段提交协议来实现exactly-once semantics的。

21438d3ea501f05ae1e42c748bf773c5d.pngFlink实现仅一次语义的应用

下面将给出一个实例来帮助了解两阶段提交协议以及Flink如何使用它来实现仅一次处理语义。该实例从Kafka中读取数据,经处理之后再写回到Kafka。Kafka是非常受欢迎的消息队列,而Kafka 0.11.0.0版本正式发布了对于事务的支持——这是与Kafka交互的Flink应用要实现端到端仅一次语义的必要条件。

当然,Flink支持这种仅一次处理语义并不只是限于与Kafka的结合,可以使用任何source/sink,只要它们提供了必要的协调机制。举个例子,Pravega是Dell/EMC的一个开源流式存储系统,Flink搭配它也可以实现端到端的exactly-once semantics。

ac3986df61062f605e780307b7871446.png

本例中的Flink应用包含以下组件,如上图所示:

1. 一个source,从Kafka中读取数据(即KafkaConsumer)

2. 一个时间窗口化的聚会操作

3. 一个sink,将结果写回到Kafka(即KafkaProducer)

若要sink支持 exactly-once semantics,它必须以事务的方式写数据到Kafka,这样当提交事务时两次checkpoint间的所有写入操作当作为一个事务被提交。这确保了出现故障或崩溃时这些写入操作能够被回滚。

当然了,在一个分布式且含有多个并发执行sink的应用中,仅仅执行单次提交或回滚是不够的,因为所有组件都必须对这些提交或回滚达成共识,这样才能保证得到一个一致性的结果。Flink使用两阶段提交协议以及预提交(pre-commit)阶段来解决这个问题。

Flink checkpointing开始时便进入到pre-commit阶段。具体来说,一旦checkpoint开始,Flink的JobManager向输入流中写入一个checkpoint barrier将流中所有消息分割成属于本次checkpoint的消息以及属于下次checkpoint的。barrier也会在操作算子间流转。对于每个operator来说,该barrier会触发operator状态后端为该operator状态打快照。

1e156da3cb188ad66e5cfee1a9fb0580.png

众所周知,flink kafka source保存Kafka消费offset,一旦完成位移保存,它会将checkpoint barrier传给下一个operator。

这个方法对于opeartor只有内部状态的场景是可行的。所谓的内部状态就是完全由Flink状态保存并管理的——本例中的第二个opeartor:时间窗口上保存的求和数据就是这样的例子。当只有内部状态时,pre-commit阶段无需执行额外的操作,仅仅是写入一些已定义的状态变量即可。当chckpoint成功时Flink负责提交这些写入,否则就终止取消掉它们。

382998d6672405acc8d52c6aba77efa6.png

当时,一旦operator包含外部状态,事情就不一样了。我们不能像处理内部状态一样处理这些外部状态。因为外部状态通常都涉及到与外部系统的交互。如果是这样的话,外部系统必须要支持可与两阶段提交协议捆绑使用的事务才能确保实现整体的exactly-once semantics。

显然本例中的data sink是有外部状态的,因为它需要写入数据到Kafka。此时的pre-commit阶段下data sink在保存状态到状态存储的同时还必须预提交它的外部事务,如下图所示:

 998d2ff8137fb5759302ff832ce648ae.png 

当checkpoint barrier在所有operator都传递了一遍且对应的快照也都成功完成之后,pre-commit阶段才算完成。该过程中所有创建的快照都被视为是checkpoint的一部分。其实,checkpoint就是整个应用的全局状态,当然也包含pre-commit阶段提交的外部状态。当出现崩溃时,我们可以回滚状态到最新已成功完成快照时的时间点。

下一步就是通知所有的operator,告诉它们checkpoint已成功完成。这便是两阶段提交协议的第二个阶段:commit阶段。该阶段中JobManager会为应用中每个operator发起checkpoint已完成的回调逻辑。

本例中的data source和窗口操作无外部状态,因此在该阶段,这两个opeartor无需执行任何逻辑,但是data sink是有外部状态的,因此此时我们必须提交外部事务,如下图所示:

fe99ba1b9dc321465c4c9a75b700ffde.png

汇总以上所有信息,总结一下:

1. 一旦所有operator完成各自的pre-commit,它们会发起一个commit操作

2. 倘若有一个pre-commit失败,所有其他的pre-commit必须被终止,并且Flink会回滚到最近成功完成decheckpoint

3. 一旦pre-commit完成,必须要确保commit也要成功——operator和外部系统都需要对此进行保证。倘若commit失败(比如网络故障等),Flink应用就会崩溃,然后根据用户重启策略执行重启逻辑,之后再次重试commit。这个过程至关重要,因为倘若commit无法顺利执行,就可能出现数据丢失的情况

因此,所有opeartor必须对checkpoint最终结果达成共识:即所有operator都必须认定数据提交要么成功执行,要么被终止然后回滚。

31438d3ea501f05ae1e42c748bf773c5d.pngFlink中实现两阶段提交

这种operator的管理有些复杂,这也是为什么Flink提取了公共逻辑并封装进TwoPhaseCommitSinkFunction抽象类的原因。

下面讨论一下如何扩展TwoPhaseCommitSinkFunction类来实现一个简单的基于文件的sink。若要实现支持exactly-once semantics的文件sink,我们需要实现以下4个方法:

1. beginTransaction:开启一个事务,在临时目录下创建一个临时文件,之后,写入数据到该文件中

2. preCommit:在pre-commit阶段,flush缓存数据块到磁盘,然后关闭该文件,确保再不写入新数据到该文件。同时开启一个新事务执行属于下一个checkpoint的写入操作3. commit:在commit阶段,我们以原子性的方式将上一阶段的文件写入真正的文件目录下。注意:这会增加输出数据可见性的延时。通俗说就是用户想要看到最终数据需要等会,不是实时的。4. abort:一旦终止事务,我们离自己删除临时文件

当出现崩溃时,Flink会恢复最新已完成快照中应用状态。需要注意的是在某些极偶然的场景下,pre-commit阶段已成功完成而commit尚未开始(也就是operator尚未来得及被告知要开启commit),此时倘若发生崩溃Flink会将opeartor状态恢复到已完成pre-commit但尚未commit的状态。

在一个checkpoint状态中,对于已完成pre-commit的事务状态,我们必须保存足够多的信息,这样才能确保在重启后要么重新发起commit亦或是终止掉事务。本例中这部分信息就是临时文件所在的路径以及目标目录。

TwoPhaseCommitSinkFunction考虑了这种场景,因此当应用从checkpoint恢复之后TwoPhaseCommitSinkFunction总是会发起一个抢占式的commit。这种commit必须是幂等性的,虽然大部分情况下这都不是问题。本例中对应的这种场景就是:临时文件不在临时目录下,而是已经被移动到目标目录下。

41438d3ea501f05ae1e42c748bf773c5d.png总结

本文的一些关键要点:

  1. Flinkcheckpointing机制是实现两阶段提交协议以及提供仅一次语义的基石

  2. 与其他系统持久化传输中的数据不同,Flink不需要将计算的每个阶段写入到磁盘中

  3. Flink新的TwoPhaseCommitSinkFunction封装两阶段提交协议的公共逻辑使之搭配支持事务的外部系统来共同构建仅一次语义应用成为可能

  4. 自1.4版本起,Flink + Pravega和Kafka 0.11 producer开始支持仅一次语义

  5. Flink Kafka 0.11 producer基于TwoPhaseCommitSinkFunction实现,比起至少一次语义的producer而言开销并未显著增加

推荐阅读:

Flink 1.10 细粒度资源管理解析

Flink State 最佳实践

不可不知的spark shuffle

bd8e661a224613c8056bce444fb6e2fb.png

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

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

相关文章

8255数码管显示0到9_汇编语言--键盘扫描及显示实验(含代码解释)

实验题目将8255单元与键盘及数码管显示单元连接,编写实验程序,扫描键盘输入,并将扫描结果送数码管显示。键盘采用4X4键盘,每个数码管显示值可为0-F共16个数。实验具体内容如下:将键盘进行编号,记作0~F,当按下其中一一个按键时&…

printf函数输出多个printf 、前置加加或者后置加加

目录 (1)前置加加和后置加加的区别 (2)printf输出前置加加 (3)printf输出后置加加 (4)printf输出printf (1)前置加加和后置加加的区别 首先我们先来了解…

python怎么执行csv文件_无法读取/打开/或对CSV文件python 3.4windows执行任何操作

我无法打开程序生成的任何CSV文件(我没有程序的完整详细信息),它的文件名为266925.130314-88850999.word文件是csv,它在excel 2013中打开,所有编辑器都很好,我尝试用原始文件名打开,我尝试通过将扩展名从.word更改为.c…

strlen函数strcpy函数strcat函数的实现

一、strlen函数 作用&#xff1a;计算字符串第一次碰到\0的长度&#xff0c;不包含\0。 #include<stdio.h> #include<assert.h>int Strlen(const char * str)//const的作用是不改变str字符数组 {assert(str ! NULL);if(str NULL){return NULL;}int length 0;//…

mysql 生明变量_mysql中变量的使用

4.4.1 局部变量局部变量是用户可自定义的变量&#xff0c;它的作用范围仅在程序内部。在程序中通常用来储存从表中查询到的数据&#xff0c;或当作程序执行过程中暂存变量使用。局部变量必须以“”开头&#xff0c;而且必须先用DECLARE命令说明后才可使用。其说明形式如下&…

斐波那契数列 青蛙跳台阶 变态跳台阶

目录 一、斐波那契数列 二、青蛙跳台阶问题 三、变态跳台阶 一、斐波那契数列 题目&#xff1a;写一个函数&#xff0c;输入n&#xff0c;求斐波那契数列的第n项。 思路&#xff1a;用递归的方法&#xff0c;f(n) f(n-1) f(n-2)。代码比较简单。 #include<iostream&g…

python history函数_python的history_n 和history函数 获取的成交量和持仓量出现翻倍

使用的最新的掘金者3。用python sdk调用 history_n 和history函数获取日k线&#xff0c;出现有的活约交易日的成交量和持仓量翻倍了,有的日期又是正确的。比如动力煤 ZC2001 对应代码CZCE.ZC001&#xff0c;获取 2019-05-20 这天的日线数据出现翻倍交易量是 2464.000000持仓量 …

math python 向上取整_计算机等级考试二级Python语言模拟试卷单选解答详解第1期...

模拟试卷单选题20题有粉丝私信希望增加一些针对国家二级Python考级的小练习和答题详解。所以就有了模拟试卷的题目讲解。第1题&#xff1a;下面的程序运行结果是&#xff08; &#xff09;解答&#xff1a;这是一个变量作用域的问题&#xff0c;变量分为全局变量和局部变量。a1…

将字符转换成数字(atoi),将数字转换成字符(itoa)

目录 一、将字符转换为数字。 二、将数字转换成字符。 一、将字符转换为数字。 &#xff08;首先字符必须是"0" —"9"&#xff0c;然后转换成十进制的数字&#xff09; 比如将"1234" 转换成 1234 #include<stdio.h> #include<st…

visio2013复制到word有多余白边_学习工坊(一)|实用技巧之Word篇

Word那些你不知道的实用小技巧让你工作更快捷大家无论学习还是工作总离不开Word软件吧今天推给大家几个实用的Word小技巧从此快人一步开启Word新世界1、Word的分屏在编辑Word文字的时候有时候需要对照前后文但是一直上下翻找是否会感觉很麻烦这里悄悄告诉大家Word可以分屏哦我们…

san分布式共享文件系统_SAN网络存储共享软件全攻略剖析

在高性能专用存储网络需求的驱使下&#xff0c;SAN存储区域网络系统大量应用于高性能计算网络系统、大型网站系统、非线性编辑系统等网络系统中&#xff0c;存储设备与计算机主机系统之间一对一的关系&#xff0c;被可供多个系统共享同一个存储设备网络的关系所取代。为确保多大…

怎么看调用的接口_SpringCloud服务间调用

本篇简介在上一篇我们介绍了SpringCloud中的注册中心组件Eureka。Eureka的作用是做服务注册与发现的&#xff0c;目的是让不同的服务与服务之间都可以通过注册中心进行间接关联&#xff0c;并且可以通过注册中心有效的管理不同服务与服务的运行状态。但在微服务的架构中&#x…

bimmercode刷隐藏教程_PS教程:快速提取人物像素,制作人物海报主体,简单易学...

这一篇主要是教大家快速提取人物像素&#xff0c;制作人物海报主体。主要是用快速复制移动快捷键(alt方向键)、单列框选工具、变形工具进行操作&#xff0c;简单快速。人物素材通过抠图得到&#xff0c;抠图方法用的是快速选择工具选择并遮住&#xff0c;这里就不说具体了&…

cass生成曲线要素文件_《CASS道路断面法施工技术》

技术分享&#xff0c;研究很久&#xff0c;分享一套CASS处理道路断面的施工方法技术&#xff0c;不懂的欢迎留言。CASS应用于道路类工程计算/ 1 /绘制道路中线道路中线一般由直线、圆曲线、缓和曲线段组成的复合线。CASS软件我们使用菜单中“公路曲线设计”生成。1、录入要素文…

dnf机械机器人补丁_干货 | 详解工业机器人控制系统架构

机械臂和移动机器人两种工业机器人的特点你知道吗&#xff1f;下面我们对比一下二者的控制系统方案。以上分类是根据应用对象&#xff0c;此外&#xff0c;市面上更多的是通用型运动控制器&#xff0c;即控制非标设备的。1 控制器底层方案1.1 机械臂类机械臂类的控制器发展较…

项目的ar指什么_AR眼镜显示测评标准解读——概述

AR眼镜检测哪些AR眼镜作为近眼显示设备的一种&#xff0c;运用其显示系统实现了虚拟信息与真实世界相叠加的效果&#xff1b;AR眼镜显示性能指标影响着AR产品实际的体验效果。因此&#xff0c;如何客观评价AR眼镜显示技术指标尤为重要。AR眼镜的性能特征和技术参数主要包括光学…

我的JAVA

一、了解Java Java是一门重编译语言&#xff0c;它本身就包含了许多类库、特性&#xff0c;再加上它所衍生出来的相关产品&#xff0c;是一个很庞大的语言体系&#xff0c;拥有无数分支&#xff0c;核心是JDK和JRE。 JDK&#xff0c;英文全称是Java Development Kit&#xff0c…

11下滑半个屏幕_努比亚发布手表手机:柔性屏幕,体积感人

2月26日凌晨&#xff0c;努比亚在MWC2019展会上召开新品发布会&#xff0c;全新的柔性屏“腕机”努比亚α正式与我们见面。努比亚α采用一块960*192分辨率的4英寸柔性屏&#xff0c;视野比手表类产品更广阔。同时为了让弯折的过程中不易出现起皱等问题&#xff0c;努比亚还使用…

Java-02

JAVA工作方式 源程序(myProgram.java) – > 编译(javac myProgram.java) -> JAVA字节码(myProgram.class) ->运行(java myProgram) 指令&#xff1a; 编译时&#xff1a;javac(compiler) 文件名运行时&#xff1a;java 文件名 JAVA的程序结构 源文件>类>方法&…

关于数组的下标越界

数组是用来存储数据的。数组是定长的连续的内存片段。因为数组的定长性&#xff0c;我们可以对数组进行多种操作。本篇记录的就是因为数组的定长性引起的下标越界问题。 首先&#xff0c;我们定义一个数组。 int a new int [5];这表示我们定义了一个Int 型&#xff0c;长度为5的…