Flink知识概要

Flink是一个用于处理无界和有界数据的分布式计算引擎,支持批流一体和精确一次 Exactly-Once 语义。其特性包括:状态管理、水位线WaterMark处理乱序事件、容错Checkpoint机制以及丰富的算子和窗口操作。Flink通过周期性或间断性生成的Watermark来处理迟到数据,同时提供Keyed State和Operator State两种状态类型。在部署中,Flink可以使用不同的State Backend来管理状态和checkpoint。面试中,Flink的热点问题涉及数据倾斜、延迟优化、SQL实现、高可用以及CEP模式等。
摘要由CSDN通过智能技术生成

Flink

一、基本特性

1、Flink简介

Flink 是分布式实时和离线计算引擎,用于在无界数据流和有界数据流上进行有状态的计算, 能在常见集群环境中运行,并能以内存速度和任意规模进行计算。

应用场景包括:实时数据计算、实时数据仓库和 ETL、事件驱动型场景,如告警、监控;此外,随着 Flink 对机器学习的支持越来越完善,还可以被用作机器学习和人工智能

2、Flink特性

  • 1.批流一体:Flink从另一个视角看待流处理和批处理,将二者统一起来,流处理看待时输入数据流是无界的;批处理被作为一种特殊的流处理,只是它的输入数据流被定义为有界的。
  • 2.Exactly-Once:Flink 通过实现两阶段提交状态保存来实现端到端的精确一致性语义
  • 3.状态管理:Flink在做计算的过程中经常需要存储中间状态,来避免数据丢失和状态恢复。
  • 4.时间处理:Flink支持事件时间EventTime、注入时间IngestionTime、处理时间ProcessingTime三种时间,同时也支持watermark来处理滞后数据。
  • 5.支持窗口:支持时间驱动的 timeWindow、数据驱动的countWindow,同时支持滚动窗口tumbling windows、滑动窗口sliding windows、会话窗口session windows。滚动窗口中的数据不会叠加;
  • 6.利用内存性能:任务的状态始终保留在内存中,如果状态大小超过可用内存,则会保存在能高效访问的磁盘数据结构中,非常低的处理延迟,

性能上: ProcessingTime性能最好, IngestTime次之, EventTime最差
延迟上:EventTime延迟最低,IngestTime次之, ProcessingTime延迟最高
确定性: EventTime确定性最高,IngestTime次之, ProcessingTime最低

3、精确一次Exactly-Once

https://developer.51cto.com/article/643945.html

精确一次消费的概念,出现在消息系统中,通常关注点只和消息的消费有关,但是实际情况远不止如此

端到端的精确一次消费包括了,从消息源发出消息,处理程序接到消息并处理消息,到最后保存结果,整个流程,数据的精确一次处理。

在 Flink 中,端到端精准一次处理的位置有三个:

  • 1)Source 端:数据从消息系统进入到 Flink 时,需要保证消息精准一次消费,发生故障时需要支持重设数据的读取位置,如Kafka可以通过offset来实现 ,可以自主维护消息的offset,实现精确一次消费
  • 2)Flink 内部端:flink利用 Checkpoint 机制,把状态存盘,发生故障的时候可以恢复,保证内部的状态一致性。
  • 3)Sink 端:将处理完的数据sink到下一阶段时,需要保证数据能够准确无误发送到下一阶段。Flink 1.4 版本引入了两阶段提交 Sink,
    在这里插入图片描述
    在这里插入图片描述

两阶段提交:

  • 1)开始事务:创建一个临时文件夹,来写把数据写入到这个文件夹里面;
  • 2)预提交:将内存中缓存的数据写入临时文件并关闭;
  • 3)正式提交:将之前写完的临时文件放入目标目录下。这代表着最终的数据会有一些延迟;
  • 4)丢弃:丢弃临时文件;

若失败发生在预提交成功后,正式提交前。可以根据状态来提交预提交的数据,也可删

Flink+Kafka 如何实现端到端的 exactly-once 语义

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

4、状态State

状态State是指,流计算过程中计算节点的中间计算结果或元数据属性,比如 在aggregation过程中要在state中记录中间聚合结果。流计算在增量计算Failover失败重启都需要state的支撑。

Flink状态主要分为两种类型:

  • 1)键控状态Keyed State:状态跟特定的key绑定,API中的keyBy字段,每一个key都有一个属于自己的State,key与key之间的State是不可见的,KeyedState 只能使用在KeyStream上的操作和函数。支持的数据结构有5种ValueState、ListState、MapState、AggregatingState、ReducingState

  • 在这里插入图片描述

  • 2)算子状态Operator State:状态跟一个特定算子的实例绑定,整个算子只对应一个State对象(相同的并行算子都能访问到状态)。只支持ListState

  • 在这里插入图片描述

可以将Keyed State视为是已经被分片或分区的Operator State,每个key都有且仅有一个状态分区(state-partition)。

状态后端State backend
主要负责本地的状态管理,以及将检查点(checkpoint)状态写入远程存储

  • 1)MemoryStateBackend: 状态信息是存储在 TaskManager 堆内存中的,checkpoint 的时候将状态保存到 JobManager 的堆内存中。
    缺点:只能保存数据量小的状态,状态数据有可能会丢失;优点:开发测试很方便
  • 2)FsStateBackend:状态信息存储在 TaskManager 堆内存中的,checkpoint 的时候将状态保存到指定的文件中 (HDFS 等文件系统)。
    缺点: 状态大小受TaskManager内存限制(默认支持5M) ;优点: 状态访问速度很快、 状态信息不会丢失;用于: 生产,也可存储状态数据量大的情况
  • 3)RocksDBStateBackend:状态信息存储在 RocksDB 数据库 (key-value 的数据存储服务), 最终保存在本地文件中 checkpoint 的时候将状态保存到指定的文件中 (HDFS 等文件系统)
    缺点: 状态访问速度有所下降 优点: 可以存储超大量的状态信息 状态信息不会丢失 用于: 生产,可以存储超大量的状态信息

5、水位线WaterMark

WaterMark水位线,可以理解为 一个延迟触发机制,,Flink窗口计算时,通过结合EventTime与WaterMark,来处理迟到的事件,一般等于currentMaxEventTime - delay,是一个具体时间戳,认为事件 eventTime小于WaterMark的所有数据都已经到达,

如果有窗口的停止时间等于Watermark,也就是Watermark大于某个window的end_time,并这个window左闭右开有数据,那么这个窗口被触发执行。

只有一个waterMark时,一个线程触发当前窗口的waterMark时间,为最大的waterMark时间;
当有多个waterMark时,也就是多并行度多个线程时,触发当前窗口的waterMark时间,取线程间最小的线程内最大waterMark时间

每个事件都有一个CurrentWatermark,相当于每个事件的计算触发时间,由ProcessTime 或者EventTime 改变为 当前watermark时间

Watermark计算方式一般为;

 currentMaxEventTime = Math.max(currentMaxEventTime, currentElementEventTime);
new Watermark(currentMaxEventTime - maxOutOfOrderness);

正常事件:EventTime大于currentMaxEventTime,窗口的currentMaxEventTime等于EventTime,不受影响;晚到事件,EventTime小于currentMaxEventTime,窗口的currentMaxEventTime等于上一个大的EventTime,

watermark窗口触发条件:

1.watermark 时间 >= window_end_time
2.[window_start_time, window_end_time) 区间中有数据存在,注意是左闭右开的区间,而且是以 event time 来计算的

主要是作用于有窗口重叠的,Flink的窗口不同于spark的窗口,每隔5秒统计一次,不管窗口里面有没有数,到窗口结尾就触发统计,flink的窗口需要一个大于窗口时间的事件来触发,增加waterMark,增加容错,窗口统计会晚设置的延迟几秒

6、容错checkpoint

容错:

  • MySQL的思想很容易理解,就像棋谱一样,把每一步都记录下来,binlog。后人读棋谱,可以随时切换到任意一张棋谱,然后跟着每一步的操作重现当时的情景。
  • HDFS的思想也比较好理解,怕丢数据,就存成N份。只要写进去最少副本数,就自动会把所有旧副本都覆盖了,最大程度的保存好数据。而且他们都属于离线数据库,随时可以存一个快照。
  • 但Flink不一样,MySQL和HDFS都是离线存储,Flink是在线的,是一个数据流呀,不能停,Flink通过Checkpoint机制将某个时刻应用状态State进行快照Snapshot保存到磁盘。

Flink 实现容错,主要通过 状态Checkpoint机制 。State 用来存储计算过程中的中间状态。Checkpoint 将某个时刻应用状态State进行快照Snapshot保存到磁盘

Flink中的Checkpoint,底层使用了Chandy-Lamport分布式快照算法,可以保证数据的在分布式环境下的一致性。主要核心是barrier栅栏,相当于标识符,表示对应用中各个OperatorState进行快照时,到哪个位置。

checkpoint流程

  • 在checkpoint过程中,JobManager会按照代码配置的规则,定期触发checkpoint,在所有的source的子任务中注入Barrier栅栏

  • TaskManager在收到所有上游广播的Barrier栅栏(理解为执行Checkpoint的信号) 后,这 个barri栅栏随着数据流向一直流动,当流入到一个算子的时候,算子会等待所有流的 Barrier 都到达之后,才会开始本地的快照,这种机制被称为 Barrier 对齐。 flink 1.11后可以非Barrier 对齐,触发checkpoint。

  • 在对齐的过程中,算子只会继续处理的来自未出现 Barrier Channel 的数据,而其余 Channel 的数据会被写入输入队列,直至在队列满后被阻塞。当所有 Barrier 到达后,算子进行本地快照,输出 Barrier 到下游并恢复正常处理。

  • 当整个DAG图的子任务的checkpoint都做完之后,会汇报给JobManager,JobManager则认为这个checkpoint已经完成。

  • 流的 barrier ,是 Flink 的 Checkpoint 中的一个核心概念。 多个 barrier 被插入到数据流中,然后作为数据流的一部分随着数据流动(有点类似于 Watermark),这些 barrier 不会跨越流中的数据。
  • 每个barrier 会把数据流分成两部分:一部分数据进入当前的快照 ,另一部分数据进入下一个快照。
  • 每 个barrier 携带着快照的 id,barrier 不会暂停数据的流动, 所以非常轻量级。
  • 在流中, 同一时间可以有来源于多个不同快照的多个 barrier, 这个意味着可 以并发的出现不同的快照.

Flink的checkpoint机制,可以与(stream和state)的持久化存储交互的前提: 持久化的source,它需要支持在一定时间内重放事件。这种sources的典型例子是持久化的消息队列(如 Kafka,RabbitMQ等)或文件系统(比如HDFS等
https://developer.aliyun.com/article/926456
在这里插入图片描述

https://blog.csdn.net/qq_24095055/article/details/124564178
Flink Checkpoint 基于 Chandy-Lamport 算法的分布式快照

Chandy-Lamport 算法,将分布式系统抽象成 DAG,节点表示进程,边表示两个进程间通信的管道。分布式快照的目的,是记录下整个系统的状态,即可分为节点的状态(进程的状态),和边的状态(传输中的数据)。因为系统状态是由输入的消息序列,驱动变化的,我们可以将输入的消息序列分为多个较短的子序列,图的每个节点或边先后处理完某个子序列后,都会进入同一个稳定的全局统状态。利用这个特性,系统的进程和信道在子序列的边界点分别进行本地快照,即使各部分的快照时间点不同最终也可以组合成一个有意义的全局快照

Flink 通过在 DAG 数据源,定时向数据流注入名为 Barrier 的特殊元素,将连续的数据流切分为多个有限序列,对应多个 Checkpoint 周期。每当接收到 Barrier,算子进行本地的 Checkpoint 快照,并在完成后异步上传本地快照,同时将 Barrier 以广播方式发送至下游。当某个 Checkpoint 的所有 Barrier 到达 DAG 末端且所有算子完成快照,则标志着全局快照的成功。

比起其他分布式快照,该算法的优势在于辅以 Copy-On-Write 技术的情况下不需要 “Stop The World”影响应用吞吐量,同时基本不用持久化处理中的数据,只用保存进程的状态信息,大大减小了快照的大小。

当作业出现反压时,阻塞式的 Barrier 对齐反而会加剧作业的反压,甚至导致作业的不稳定。

  • 首先, Chandy-Lamport 分布式快照的结束依赖于 Marker 的流动,而反压则会限制 Marker 的流动,导致快照的完成时间变长甚至超时。
  • 其次,Barrier 对齐本身可能成为一个反压的源头,影响上游算子的效率,而这在某些情况下是不必要的。

flink是基于Chandy-Lamport算法来实现全局快照的,其核心就是在数据中间穿插barrier;当一个task上游同一批次所有的barrier到齐时,就可以触发快照状态的保存了,问题就是出在这里,等待对齐。在flink1.11版本引入了非对齐的checkpoint,来解决这种阻塞问题,

  • 如果当第一个barrier来的时候,我不能触发checkpoint, 是因为还有部分数据没有处理到。

  • 直接把这部分还没处理的数据(在buffer里面的数据),连同状态数据一起保存到checkpoint里面;

  • 在从checkpoint恢复的时候,就先把这部分buffer数据, 先恢复到当前task的buffer里面,继续计算就可以了,其实弱化了每个checkpoint批次的概念;

  • 这样一来当收到第一个barrier的时候,就可以直接触发checkpoint了

对齐与非对齐,两者的差异主要可以总结为两点:

  • 快照的触发,是在接收到第一个 Barrier 时还是在接收到最后一个 Barrier 时。
  • 是否需要阻塞已经接收到 Barrier 的 Channel 的计算。

7、Flink内存管理

Flink本身基本是以Java语言完成的,理论上说,直接使用JVM的虚拟机的内存管理就应该更简单方便,但Flink还是单独抽象出了自己的内存管理。

https://blog.51cto.com/u_15294985/5134340

因为Flink是为大数据而产生的,而大数据使用会消耗大量的内存,而JVM的内存管理管理设计是兼顾平衡的,不可能单独为了大数据而修改,这对于Flink来说,非常的不灵活,而且频繁GC会导致长时间的机器暂停应用,这对于大数据的应用场景来说也是无法忍受的。

JVM在大数据环境下存在的问题:

  • 1)Java 对象存储密度低。在HotSpot JVM中,每个对象占用的内存空间必须是8的倍数,那么一个只包含 boolean 属性的对象就要占用了16个字节内存:对象头占了8个,boolean 属性占了1个,对齐填充占了7个。而实际上我们只想让它占用1个bit。
  • 2)在处理大量数据会生成大量对象,尤其是几十甚至上百G的内存应用时
  • 3)Java GC可能会被反复触发,其中Full GC或Major GC的开销是非常大的,GC 会达到秒级甚至分钟级。
  • 4)OOM 问题影响稳定性。OutOfMemoryError是分布式计算框架经常会遇到的问题,当JVM中所有对象大小超过分配给JVM的内存大小时,就会发生OutOfMemoryError错误,导致JVM崩溃,分布式框架的健壮性和性能都会受到影响。

在这里插入图片描述
Flink的内存管理,是在JVM的基础之上封装的内存管理;除了JVM之上封装的内存管理,还会有个一个很大的堆外内存(可以理解为使用操作系统内存),用来执行一些IO操作。

taskmanager进程内存 = Flink内存 +JVM特有内存
Flink内存 = 框架堆内和堆外内存 + Task堆内和堆外内存 + 网络缓冲内存+管理内存

  • 1) JVM 特定内存:JVM 本身使用的内存,包含 JVM 的元空间和 over-head
    • JVM 的元空间,默认 256mb
    • JVM over-head 执行开销:JVM 执行时自身所需要的内容,包括线程堆栈、IO、编译缓存等所使用的内存。.fraction默认 0.1;min,默认 192mb;max,默认 1gb
  • 2) 框架内存:Flink 框架,即 TaskManager 本身所占用的内存,不计入 Slot 的资源中
    • 堆内内存:size默认 128MB
    • 堆外内存:size默认 128MB
  • 3) Task 内存:Task 执行用户代码时所使用的内存
    • 堆内内存:size默认 none,由 Flink 内存扣除掉其他部分的内存得到。
    • 堆外内存:size默认 0,表示不使用堆外内存
  • 4) 网络内存
  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值