我的编程空间,编程开发者的网络收藏夹
学习永远不晚

ApacheFlink中如何深度解析FaultTolerance

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

ApacheFlink中如何深度解析FaultTolerance

ApacheFlink中如何深度解析FaultTolerance,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

摘要:实际问题 在流计算场景中,数据会源源不断的流入Apache Flink系统,每条数据进入Apache Flink系统都会触发计算。那么在计算过程中如果网络、机器等原因导致Task运行失败了,Apache Flink会如何处理呢?我们介绍了 Apache Flink 会利用State记录计算的状态,在Failover时候Task会根据State进行恢复。                

在流计算场景中,数据会源源不断的流入Apache Flink系统,每条数据进入Apache Flink系统都会触发计算。那么在计算过程中如果网络、机器等原因导致Task运行失败了,Apache Flink会如何处理呢?在 《Apache Flink 漫谈系列 - State》一篇中我们介绍了 Apache Flink 会利用State记录计算的状态,在Failover时候Task会根据State进行恢复。但State的内容是如何记录的?Apache Flink 是如何保证 Exactly-Once 语义的呢?这就涉及到了Apache Flink的 容错(Fault Tolerance) 机制,本篇将会为大家进行相关内容的介绍。

容错(Fault Tolerance) 是指容忍故障,在故障发生时能够自动检测出来,并使系统能够自动恢复正常运行。当出现某些指定的网络故障、硬件故障、软件错误时,系统仍能执行规定的一组程序,或者说程序不会因系统中的故障而中止,并且执行结果也不包含系统故障所引起的差错。

我们知道MySql的binlog是一个Append Only的日志文件,Mysql的主备复制是高可用的主要方式,binlog是主备复制的核心手段(当然mysql高可用细节很复杂也有多种不同的优化点,如 纯异步复制优化为半同步和同步复制以保证异步复制binlog导致的master和slave的同步时候网络坏掉,导致主备不一致问题等)。Mysql主备复制,是Mysql容错机制的一部分,在容错机制之中也包括事物控制,在传统数据库中事物可以设置不同的事物级别,以保证不同的数据质量,级别由低到高 如下:

  • Read uncommitted - 读未提交,就是一个事务可以读取另一个未提交事务的数据。那么这种事物控制成本最低,但是会导致另一个事物读到脏数据,那么如何解决读到脏数据的问题呢?利用Read committed 级别...

  • Read committed - 读提交,就是一个事务要等另一个事务提交后才能读取数据。这种级别可以解决读脏数据的问题,那么这种级别有什么问题呢?这个级别还有一个 不能重复读的问题,即:开启一个读事物T1,先读取字段F1值是V1,这时候另一个事物T2可以UPDATA这个字段值V2,导致T1再次读取字段值时候获得V2了,同一个事物中的两次读取不一致了。那么如何解决不可重复读的问题呢?利用 Repeatable read 级别...

  • Repeatable read - 重复读,就是在开始读取数据(事务开启)时,不再允许修改操作。重复读模式要有事物顺序的等待,需要一定的成本达到高质量的数据信息,那么重复读还会有什么问题吗?是的,重复读级别还有一个问题就是 幻读,幻读产生的原因是INSERT,那么幻读怎么解决呢?利用Serializable级别...

  • Serializable  - 序列化 是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。

主备复制,事物控制都是传统数据库容错的机制。

流计算Fault Tolerance的一个很大的挑战是低延迟,很多Apache Flink任务都是7 x 24小时不间断,端到端的秒级延迟,要想在遇上网络闪断,机器坏掉等非预期的问题时候快速恢复正常,并且不影响计算结果正确性是一件极其困难的事情。同时除了流计算的低延时要求,还有计算模式上面的挑战,在Apache Flink中支持Exactly-Once和At-Least-Once两种计算模式,如何做到在Failover时候不重复计算,进而精准的做到Exactly-Once也是流计算Fault Tolerance要重点解决的问题。

Apache Flink的Fault Tolerance机制核心是持续创建分布式流数据及其状态的快照。这些快照在系统遇到故障时,作为一个回退点。Apache Flink中创建快照的机制叫做Checkpointing,Checkpointing的理论基础 Stephan 在 Lightweight Asynchronous Snapshots for Distributed Dataflows 进行了细节描述,该机制源于由K. MANI CHANDY和LESLIE LAMPORT 发表的 Determining-Global-States-of-a-Distributed-System Paper,该Paper描述了在分布式系统如何解决全局状态一致性问题。

在Apache Flink中以Checkpointing的机制进行容错,Checkpointing会产生类似binlog一样的、可以用来恢复任务状态的数据文件。Apache Flink中也有类似于数据库事物控制一样的数据计算语义控制,比如:At-Least-Once和Exactly-Once。

上面我们说Checkpointing是Apache Flink中Fault Tolerance的核心机制,我们以Checkpointing的方式创建包含timer,connector,window,user-defined state 等stateful Operator的快照。在Determining-Global-States-of-a-Distributed-System的全局状态一致性算法中重点描述了全局状态的对齐问题,在Lightweight Asynchronous Snapshots for Distributed Dataflows中核心描述了对齐的方式,在Apache Flink中采用以在流信息中插入barrier的方式完成DAG中异步快照。 如下图(from Lightweight Asynchronous Snapshots for Distributed Dataflows)描述了Asynchronous barrier snapshots for acyclic graphs,也是Apache Flink中采用的方式。

ApacheFlink中如何深度解析FaultTolerance

上图描述的是一个增量计算word count的Job逻辑,核心逻辑是如下几点:

  • barrier 由source节点发出;

  • barrier会将流上event切分到不同的checkpoint中;

  • 汇聚到当前节点的多流的barrier要对齐;

  • barrier对齐之后会进行Checkpointing,生成snapshot;

  • 完成snapshot之后向下游发出barrier,继续直到Sink节点;

这样在整个流计算中以barrier方式进行Checkpointing,随着时间的推移,整个流的计算过程中按时间顺序不断的进行Checkpointing,如下图:

ApacheFlink中如何深度解析FaultTolerance

生成的snapshot会存储到StateBackend中,相关State的介绍可以查阅 《Apache Flink 漫谈系列 - State》。这样在进行Failover时候,从最后一次成功的checkpoint进行恢复。

上面我们了解到整个流上面我们会随这时间推移不断的做Checkpointing,不断的产生snapshot存储到Statebackend中,那么多久进行一次Checkpointing?对产生的snapshot如何持久化的呢?带着这些疑问,我们看看Apache Flink对于Checkpointing如何控制的?有哪些可配置的参数:(这些参数都在 CheckpointCoordinator 中进行定义)

  • checkpointMode - 检查点模式,分为 AT_LEAST_ONCE 和 EXACTLY_ONCE 两种模式;

  • checkpointInterval - 检查点时间间隔,单位是毫秒。

  • checkpointTimeout - 检查点超时时间,单位毫秒。

在Apache Flink中还有一些其他配置,比如:是否将存储到外部存储的checkpoints数据删除,如果不删除,即使job被cancel掉,checkpoint信息也不会删除,当恢复job时候可以利用checkpoint进行状态恢复。我们有两种配置方式,如下:

  • ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION - 当job被cancel时候,外部存储的checkpoints不会删除。

  • ExternalizedCheckpointCleanup.DELETE_ON_CANCELLATION - 当job被cancel时候,外部存储的checkpoints会被删除。

通过上面内容我们了解了Apache Flink中Exactly-Once和At-Least-Once只是在进行checkpointing时候的配置模式,两种模式下进行checkpointing的原理是一致的,那么在实现上有什么本质区别呢?

语义

  • At-Least-Once - 语义是流上所有数据至少被处理过一次(不要丢数据)

  • Exactly-Once - 语义是流上所有数据必须被处理且只能处理一次(不丢数据,且不能重复)

从语义上面Exactly-Once 比 At-Least-Once对数据处理的要求更严格,更精准,那么更高的要求就意味着更高的代价,这里的代价就是 延迟。

实现

那在实现上面Apache Flink中At-Least-Once 和 Exactly-Once有什么区别呢?区别体现在多路输入的时候(比如 Join),当所有输入的barrier没有完全到来的时候,早到来的event在Exactly-Once模式下会进行缓存(不进行处理),而在At-Least-Once模式下即使所有输入的barrier没有完全到来,早到来的event也会进行处理。也就是说对于At-Least-Once模式下,对于下游节点而言,本来数据属于checkpoint N 的数据在checkpoint N-1 里面也可能处理过了。

我以Exactly-Once为例说明Exactly-Once模式相对于At-Least-Once模式为啥会有更高的延时?如下图:

ApacheFlink中如何深度解析FaultTolerance

上图示意了某个节点进行Checkpointing的过程:

  • 当Operator接收到某个上游发下来的第barrier时候开始进行barrier的对齐阶段;

  • 在进行对齐期间早到的input的数据会被缓存到buffer中;

  • 当Operator接收到上游所有barrier的时候,当前Operator会进行Checkpointing,生成snapshot并持久化;

  • 当完Checkpointing时候将barrier广播给下游Operator;

多路输入的barrier没有对齐的时候,barrier先到的输入数据会缓存在buffer中,不进行处理,这样对于下游而言buffer的数据越多就有更大的延迟。这个延时带来的好处就是相邻Checkpointing所记录的数据(计算结果或event)没有重复。相对At-Least-Once模式数据不会被buffer,减少延时的利好是以容忍数据重复计算为代价的。

在Apache Flink的代码实现上用CheckpointBarrierHandler类处理barrier,其核心接口是:

public interface CheckpointBarrierHandler {
    ...
   
    BufferOrEvent getNextNonBlocked() throws Exception;
    ...
}

其中BufferOrEvent,可能是正常的data event,也可能是特殊的event,比如barrier event。对应At-Least-Once和Exactly-Once有两种不同的实现,具体如下: 

  • Exactly-Once模式 - BarrierBuffer

    BarrierBuffer用于提供Exactly-Once一致性保证,其行为是:它将以barrier阻塞输入直到所有的输入都接收到基于某个检查点的barrier,也就是上面所说的对齐。为了避免背压输入流,BarrierBuffer将从被阻塞的channel中持续地接收buffer并在内部存储它们,直到阻塞被解除。

BarrierBuffer 实现了CheckpointBarrierHandler的getNextNonBlocked, 该方法用于获取待处理的下一条记录。该方法是阻塞调用,直到获取到下一个记录。其中这里的记录包括两种,一种是来自于上游未被标记为blocked的输入,比如上图中的 event(a),;另一种是,从已blocked输入中缓冲区队列中被释放的记录,比如上图中的event(1,2,3,4)。

  • At-Least-Once模式 - BarrierTracker
    BarrierTracker会对各个输入接收到的检查点的barrier进行跟踪。一旦它观察到某个检查点的所有barrier都已经到达,它将会通知监听器检查点已完成,以触发相应地回调处理。不像BarrierBuffer的处理逻辑,BarrierTracker不阻塞已经发送了barrier的输入,也就说明不采用对齐机制,因此本检查点的数据会及时被处理,并且因此下一个检查点的数据可能会在该检查点还没有完成时就已经到来。这样在恢复时只能提供At-Least-Once的语义保证。

BarrierTracker也实现了CheckpointBarrierHandler的getNextNonBlocked, 该方法用于获取待处理的下一条记录。与BarrierBuffer相比它实现很简单,只是阻塞的获取要处理的event。

如上两个CheckpointBarrierHandler实现的核心区别是BarrierBuffer会维护多路输入是否要blocked,缓存被blocked的输入的record。所谓有得必有失,有失必有得,舍得舍得在这里也略有体现哈 :)。

在 《Apache Flink 漫谈系列 - State》中我们有过对Apache Flink存储到State中的内容做过介绍,比如在connector会利用OperatorState记录读取位置的offset,那么一个完整的Apache Flink任务的执行图是一个DAG,上面我们描述了DAG中一个节点的过程,那么整体来看Checkpointing的过程是怎样的呢?在产生checkpoint并分布式持久到HDFS的过程是怎样的呢?

整体Checkpointing流程

ApacheFlink中如何深度解析FaultTolerance

上图我们看到一个完整的Apache Flink Job进行Checkpointing的过程,JM触发Soruce发射barriers,当某个Operator接收到上游发下来的barrier,开始进行barrier的处理,整体根据DAG自上而下的逐个节点进行Checkpointing,并持久化到Statebackend,一直到DAG的sink节点。

Incremental Checkpointing

对于一个流计算的任务,数据会源源不断的流入,比如要进行双流join(Apache Flink 漫谈系列 - Join 篇会详细介绍),由于两边的流event的到来有先后顺序问题,我们必须将left和right的数据都会在state中进行存储,Left event流入会在Right的State中进行join数据,Right event流入会在Left的State中进行join数据,如下图左右两边的数据都会持久化到State中:
ApacheFlink中如何深度解析FaultTolerance

由于流上数据源源不断,随着时间的增加,每次checkpoint产生的snapshot的文件(RocksDB的sst文件)会变的非常庞大,增加网络IO,拉长checkpoint时间,最终导致无法完成checkpoint,进而导致Apache Flink失去Failover的能力。为了解决checkpoint不断变大的问题,Apache Flink内部实现了Incremental Checkpointing,这种增量进行checkpoint的机制,会大大减少checkpoint时间,并且如果业务数据稳定的情况下每次checkpoint的时间是相对稳定的,根据不同的业务需求设定checkpoint的interval,稳定快速的进行Checkpointing,保障Apache Flink任务在遇到故障时候可以顺利的进行Failover。Incremental Checkpointing的优化对于Apache Flink成百上千的任务节点带来的利好不言而喻。

根据上面的介绍我们知道Apache Flink内部支持Exactly-Once语义,要想达到端到端(Soruce到Sink)的Exactly-Once,需要Apache Flink外部Soruce和Sink的支持,具体如下:

  • 外部Source的容错要求
    Apache Flink 要做到 End-to-End 的 Exactly-Once 需要外部Source的支持,比如上面我们说过 Apache Flink的Checkpointing机制会在Source节点记录读取的Position,那就需要外部Source提供读取数据的Position和支持根据Position进行数据读取。

  • 外部Sink的容错要求
    Apache Flink 要做到 End-to-End 的 Exactly-Once相对比较困难,以Kafka作为Sink为例,当Sink Operator节点宕机时候,根据Apache Flink 内部Exactly-Once模式的容错保证, 系统会回滚到上次成功的Checkpoint继续写入,但是上次成功checkpoint之后当前checkpoint未完成之前已经把一部分新数据写入到kafka了. Apache Flink自上次成功的checkpoint继续写入kafka,就造成了kafka再次接收到一份同样的来自Sink Operator的数据,进而破坏了End-to-End 的 Exactly-Once 语义(重复写入就变成了At-Least-Once了),如果要解决这一问题,Apache Flink 利用Two Phase Commit(两阶段提交)的方式来进行处理。本质上是Sink Operator 需要感知整体Checkpoint的完成,并在整体Checkpoint完成时候将计算结果写入Kafka。

看完上述内容,你们掌握ApacheFlink中如何深度解析FaultTolerance的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注编程网行业资讯频道,感谢各位的阅读!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

ApacheFlink中如何深度解析FaultTolerance

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

ApacheFlink中如何深度解析FaultTolerance

ApacheFlink中如何深度解析FaultTolerance,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。摘要:实际问题 在流计算场景中,数据会源源不断的流入Apache
2023-06-19

如何深度解析JVM

如何深度解析JVM,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。首先这里澄清两个概念:JVM实例和JVM执行引擎实例,JVM实例对应了一个独立运行的Java程序,而JVM执行引
2023-06-17

如何深度解析Kafka

如何深度解析Kafka,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。背景介绍Kafka简介Kafka是一种分布式的,基于发布/订阅的消息系统。主要设计目标如下:
2023-06-17

如何深度分析jvm中dump文件

这篇文章将为大家详细讲解有关如何深度分析jvm中dump文件,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。JVM dumpjava内存dump是jvm运行时内存的一份快照,利用它可以分析是否
2023-06-16

如何深度剖析Python语言特点

这期内容当中小编将会给大家带来有关如何深度剖析Python语言特点,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。这里并不涉及python的特殊规则和细节,目标是通过示例使你快速了解Python语言的特点。
2023-06-17

Python中如何深度学习CNN

本篇文章给大家分享的是有关Python中如何深度学习CNN,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。1.CNN概述CNN的整体思想,就是对图片进行下采样,让一个函数只学一个
2023-06-25

如何进行Java中对HashMap的深度分析与比较

如何进行Java中对HashMap的深度分析与比较,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。在Java的世界里,无论类还是各种数据,其结构的处理是整个程序的逻辑以及性能
2023-06-03

如何深度剖析C++资源管理细节

如何深度剖析C++资源管理细节,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。我们从系统结构的角度上讲,C/C++ 支持 3 种内存管理方式,基于栈的C++资源管
2023-06-17

深度解析Java中的国际化底层类ResourceBundle

做项目应该都会实现国际化,那么大家知道Java底层是如何实现国际化的吗?这篇文章就来和大家深度解析一下Java中的国际化底层类ResourceBundle,希望对大家有所帮助
2023-03-10

如何解决mysql深度分页问题

目录mysql深度分页问题1.基本分页:耗时0.019秒2.深度分页:耗时10.236秒3.深度ID分页:耗时0.052秒4.两步走深度分页:耗时0.049秒+0.017秒5.一步走深度分页:耗时0.05秒6.集成BeanSearcher框
2023-01-09

教你如何深度解析Windows7的设备驱动管理原理

1、Windows 7系统的设备驱动文件解读 在Windows7系统中包含了一个覆盖范围很广的身边驱动程序库。在该操作系统的基本安装中,这些驱动程序都会保www.cppcns.com存在驱动程序存储区中,它们位于%SystemRoot%\S
2023-05-25

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录