微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Flink基本概念

目录

 Flink的特性

Flink技术栈

Flink任务调度原理

Flink执行图

Flink API

任务执行

时间操作

window操作

Flink API

Flink架构

Flink反压机制

Flink与Spark Streaming

Flink+Kafka实现exactly-once语义


 

 

 Flink的特性

  1. 高吞吐、低延迟、高性能
  2. 支持带事件时间的窗口(window)操作:time、count、session、data-driven
  3. 支持有状态计算的exactly once语义
  4. 支持具有反压功能的持续流模型
  5. 支持基于轻量级分布式快照(snapshot)实现的容错
  6. 同时支持batch on streaming处理和Streaming处理
  7. Flink在JVM内部实现了自己的内存管理
  8. 支持迭代计算
  9. 支持程序自动优化:避免特定情况下shuffle、排序等昂贵操作,中间结果有必要时缓存

Flink技术栈

 

 

  1. 同spark一样,Flink也有Flink Core(runtime层)来统一支持流处理和批处理
  2. Flink Core(runtime层):是一个分布式的流处理引擎,提供了支持Flink计算的全部核心实现
    1. 支持分布式流处理
    2. JobGraph到ExecutionGraph的映射、调度,为上层API层提供基础服务
  3. Flink API层:实现面向Stream的流处理和面向batch的批处理API
  4. 特定应用领域库:
    1. Flink ML:提供机器学习Pipelines API并实现多种机器学习算法
    2. 图计算库Gelly:提供了图计算相关API和多种图计算算法实现

Flink任务调度原理

  • Client 为提交 Job 的客户端,可以是运行在任何机器上(与 JobManager 环境连通即可)。提交 Job 后,Client 可以结束进程(Streaming的任务),也可以不结束并等待结果返回。
  • JobManager 主要负责调度 Job 并协调 Task 做 checkpoint,职责上很像 Storm 的 Nimbus。从 Client 处接收到 Job 和 JAR 包等资源后,会生成优化后的执行计划,并以 Task 的单元调度到各个 TaskManager 去执行。
  • TaskManager 在启动的时候就设置好了槽位数(Slot),每个 slot 能启动一个 Task,Task 为线程。从 JobManager 处接收需要部署的 Task,部署启动后,与自己的上游建立 Netty 连接,接收数据并处理。
  • 一个worker(TaskManager)都是一个JVM进程,它可能会在独立的线程上执行一个或多个subtask。为了控制一个worker能接收多少个task,worker通过task slot来进行控制(一个worker至少有一个task slot)。
  • 每个task slot表示TaskManager拥有资源的一个固定大小的子集。假如一个TaskManager有三个slot,那么它会将其管理的内存分成三份给各个slot。资源slot化意味着一个subtask将不需要跟来自其他job的subtask竞争被管理的内存,取而代之的是它将拥有一定数量的内存储备。需要注意的是,这里不会涉及到cpu的隔离,slot目前仅仅用来隔离task的受管理的内存。

 

  • Task Slot是静态的概念,是指TaskManager具有的并发执行能力,可以通过参数taskmanager.numberOfTaskSlots进行配置;而并行度parallelism是动态概念,即TaskManager运行程序时实际使用的并发能力,可以通过参数parallelism.default进行配置。
  • 也就是说,假设一共有3个TaskManager,每一个TaskManager中的分配3个TaskSlot,也就是每个TaskManager可以接收3个task,一共9个TaskSlot,如果我们设置parallelism.default=1,即运行程序认的并行度为1,9个TaskSlot只用了1个,有8个空闲,因此,设置合适的并行度才能提高效率。

Flink执行图

Flink 中的执行图可以分成四层:StreamGraph -> JobGraph -> ExecutionGraph -> 物理执行图。

  • StreamGraph:是根据用户通过 Stream API 编写的代码生成的最初的图。用来表示程序的拓扑结构。
  • JobGraph:StreamGraph经过优化后生成了 JobGraph,提交给 JobManager 的数据结构。主要的优化为,将多个符合条件的节点 chain 在一起作为一个节点,这样可以减少数据在节点之间流动所需要的序列化/反序列化/传输消耗。
  • ExecutionGraph:JobManager 根据 JobGraph 生成ExecutionGraph。ExecutionGraph是JobGraph的并行化版本,是调度层最核心的数据结构。
  • 物理执行图:JobManager 根据 ExecutionGraph 对 Job 进行调度后,在各个TaskManager 上部署 Task 后形成的“图”,并不是一个具体的数据结构。

Flink API

  • DataSet:对静态数据进行批处理操作、将静态数据抽象成分布式数据集,使用Flink各种操作符处理数据集,支持Java、Scala、Python
  • DataStream:对数据流进行流处理操作,将流式的数据抽象成分布式数据流,用Flink各种操作符处理数据流,支持Java、Scala
  • Table API:对结构化数据进行查询操作,将结构化数据抽象成关系表。并通过类sql的DSL对关系表进行各种查询操作,支持Java、Scala
  • DataStream 面向Stream的流处理。无界
  • DataSet面向Batch的批处理。有界+无界
  • Table API 面向Stream和Batch的处理。

任务执行

  • runtime层以JobGraph形式接受程序。JobGraph即为一个一般化的并行计算数据流图,它拥有任意数量的Task来接收和产生data stream。
  • DataStream API 和 DataSet API都会使用单独编译的处理方式生成JobGraph。DataSet API使用optimizer来决定针对程序的优化方法,而DataStream API则使用stream builder来完成该任务
  • 在执行JobGraph时,Flink提供了多种候选部署方案(如local,remote,YARN等)
  • Flink附随了一产生DataSet或DataStream API程序的类库和API:处理逻辑表查询Table,机器学习的FlinkML,图像处理的Gelly,复杂时间处理的CEP。

时间操作

 

  • 事件时间(Event Time):事件创建时间。它通常由事件中的时间戳描述,例如采集的日志数据中,每一条日志都会记录自己的生成时间,Flink通过时间戳分配器访问事件时间戳。
  • 采集时间(Ingestion Time):事件进入到Flink DataFlow的时间
  • 处理时间(Processing Time):某个Operator对事件进行处理的本地系统时间。认的时间属性就是Processing Time。

在Flink的流式处理中,绝大部分的业务都会使用eventTime,一般只在eventTime无法使用时,才会被迫使用ProcessingTime或者IngestionTime。

window操作

Window可以分成两类:

  • Countwindow:按照指定的数据条数生成一个Window,与时间无关。
  • TimeWindow:按照时间生成Window。

对于TimeWindow,可以根据窗口实现原理的不同分成三类:滚动窗口(Tumbling Window)、滑动窗口(Sliding Window)和会话窗口(Session Window)。

WindowAPI 都由滚动窗口和滑动窗口。

  • TimeWindow是将指定时间范围内的所有数据组成一个window,一次对一个window里面的所有数据进行计算。
  • Countwindow根据窗口中相同key元素的数量来触发执行,执行时只计算元素数量达到窗口大小的key对应的结果。

事件窗口EventTimeWindow API:

  • TumblingEventTimeWindows 滚动窗口
  • SlidingEventTimeWindows 滑动窗口
  • EventTimeSessionWindows 会话窗口(Session Window)。

基本操作:

  • window:创建自定义窗口
  • Trigger:触发器,决定一个窗口何时被计算或清除
  • evictor:驱逐者,在Trigger触发后且窗口被处理前,剔除窗口中不需要的元素(filter)
  • apply:自定义window function

Flink 中窗口机制和时间类型是完全解耦的,也就是说当需要改变时间类型时不需要更改窗口逻辑相关的代码

Flink API

 

 

越顶层越抽象,表达含义越简明,使用越方便。

越底层越具体,表达能力越丰富,使用越灵活。

 

Flink架构

 

  • 当系统本地启动时,一个JobManager和一个TaskManagere会启动在同一个JVM中。
  • 一个程序被提交后,系统创建一个Client来进行预处理,将程序转变成一个并行数据流形成,交给JobManager和TaskManager执行。
    • Job Managers:负责协调Flink系统调度Task,协调检查点,协调失败时恢复等。
    • Task Managers:执行并行程序的worker。
  • 每个worker(TaskManager)是一个JVM进程,里面运行一个或多个线程,每个worker能接收多少task,由task Slot来控制。
  • 一个TaskManager进行中有多个subtask线程,意味着task将共享TCP连接(基于多路复用)和心跳消息,共享数据集和数据结构,减少每个task的负担。

 

这里的slot只对内存隔离管理,cpu不进行隔离。

 

Flink反压机制

  • Storm: 通过监控process bolt中接收队列负载情况来处理反压,即当超过高水位值,就将反压信息写到Zookeeper,由zookeeper的watch通知worker进入反压状态,最后spout停止发送tuple。
  • Spark Streaming:设置属性“spark.streaming.backpressure.enabled”进行自动反压,即动态控制数据接收速率来适配集群数据处理能力。
  • Flink:不需要设置,自动处理反压,即每个组件都有对应的分布式阻塞队列,只有队列不满的情况,上游才发数据,较慢的接收者会自动降低发送速率,如果队列满了(有界队列),发送者会阻塞。

 

 

Flink与Spark Streaming

  • 数据模型:
    • spark 采用 RDD 模型,spark streaming 的 DStream 实际上也就是一组 组小批数据 RDD 的集合
    • flink 基本数据模型是数据流,以及事件(Event)序列
  • 运行时架构:
    • spark 是批计算,将 DAG 划分为不同的 stage,一个完成后才可以计算下一个
    • flink 是标准的流执行模式,一个事件在一个节点处理完后可以直接发往下一个节点进行处理

 

Flink+Kafka实现exactly-once语义

  • Flink通过checkpoint来保存数据是否处理完成的状态。
  • 由JobManager协调各个TaskManager进行checkpoint存储,checkpoint保存在 StateBackend中,认StateBackend是内存级的,也可以改为文件级的进行持久化保存。
  • 执行过程实际上是一个两段式提交,每个算子执行完成,会进行“预提交”,直到执行完sink操作,会发起“确认提交”,如果执行失败,预提交会放弃掉。
  • 如果宕机需要通过StateBackend进行恢复,只能恢复所有确认提交的操作。

 

 

 

 

 

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐