Flink 引擎介绍 | 青训营笔记

123 阅读6分钟

这是我参与「第四届青训营 」笔记创作活动的的第2天

一、Apache Flink 概述

核心是一个流式的数据流执行引擎,并且能够基于同一个Flink运行时,提供支持流处理和批处理两种类型应用。其针对数据流的分布式计算提供了数据分布,数据通信及容错机制等功能。基于流执行引擎,Flink提供了跟多高抽象层的API便于用户编写分布式任务,下面稍微介绍一下Flink的几种API:

  • SQL & Table API:Flink 支持两种关系型的 API,Table API 和 SQL。这两个 API 都是批处理和流处理统一的 API,这意味着在无边界的实时数据流和有边界的历史记录数据流上,关系型 API 会以相同的语义执行查询,并产生相同的结果。Table API 和 SQL借助了 Apache Calcite 来进行查询的解析,校验以及优化。它们可以与 DataStream 和DataSet API 无缝集成,并支持用户自定义的标量函数,聚合函数以及表值函数。

  • DataStream API:DataStream API为许多通用的流处理操作提供了处理原语。这些操作包括窗口、逐条记录的转换操作,在处理事件时进行外部数据库查询等。DataStream API 支持 Java 和Scala 语言,预先定义了例如 map()、reduce()、aggregate() 等函数。你可以通过扩展实现预定义接口或使用 Java、Scala 的 lambda 表达式实现自定义的函数。

  • DataSet API:DataSet API 是 Flink 用于批处理应用程序的核心 API。DataSet API 所提供的基础算子包括 map、reduce、(outer) join、co-group、iterate 等。所有算子都有相应的算法和数据结构支持,对内存中的序列化数据进行操作。如果数据大小超过预留内存,则过量数据将存储到磁盘。Flink 的 DataSet API 的数据处理算法借鉴了传统数据库算法的实现,例如混合散列连接(hybrid hash-join)和外部归并排序(external merge-sort)。

  • StateFul Stream Processing:最低级抽象只提供有状态流,通过Process Function嵌入到DataStream API中,它允许用户自由处理来自一个或者多个流的时间,并使用一致的容错状态,此外用户可以注册event time和processing time回调,允许程序实现复杂的计算。

二、 流批一体的 Apache Flink 架构

Flink 分层架构

  • SDK 层:
  • 执行引擎层(Runtime 层):执行引擎层提供了统一的 DAG,用来描述数据处理的 Pipeline,不管是流还是批,都会转化为 DAG 图,调度层再把 DAG 转化成分布式环境下的 Task,Task 之间通过 Shuffle 传输数据;

  • 状态存储层:负责存储算子的状态信息

Flink 整体架构

image.png

JobManager #

JobManager 具有许多与协调 Flink 应用程序的分布式执行有关的职责:它决定何时调度下一个 task(或一组 task)、对完成的 task 或执行失败做出反应、协调 checkpoint、并且协调从失败中恢复等等。这个进程由三个不同的组件组成:

  • ResourceManager

    ResourceManager 负责 Flink 集群中的资源提供、回收、分配 - 它管理 task slots,这是 Flink 集群中资源调度的单位(请参考TaskManagers)。Flink 为不同的环境和资源提供者(例如 YARN、Kubernetes 和 standalone 部署)实现了对应的 ResourceManager。在 standalone 设置中,ResourceManager 只能分配可用 TaskManager 的 slots,而不能自行启动新的 TaskManager。

  • Dispatcher

    Dispatcher 提供了一个 REST 接口,用来提交 Flink 应用程序执行,并为每个提交的作业启动一个新的 JobMaster。它还运行 Flink WebUI 用来提供作业执行信息。

  • JobMaster

    JobMaster 负责管理单个JobGraph的执行。Flink 集群中可以同时运行多个作业,每个作业都有自己的 JobMaster。

始终至少有一个 JobManager。高可用(HA)设置中可能有多个 JobManager,其中一个始终是 leader,其他的则是 standby(请参考 高可用(HA))。

TaskManagers #

TaskManager(也称为 worker)执行作业流的 task,并且缓存和交换数据流。

必须始终至少有一个 TaskManager。在 TaskManager 中资源调度的最小单位是 task slot。TaskManager 中 task slot 的数量表示并发处理 task 的数量。请注意一个 task slot 中可以执行多个算子(请参考Tasks 和算子链)。

Flink 作业示例

  • Flink 作业示例(Flink Learn: Hands-On Training
  • ExecutionGraph 生成:DataStream API Code --> JobGraph --> ExecutionGraph(Parallelized)
  • OperatorChain:

Flink 如何做到流批一体

为什么需要流批一体

  • 一些业务场景,除了实时的数据统计需求,为了确认运营或产品的效果,用户同时还需要和历史数据做比较,比如,抖音一些直播数据的统计;

  • 这种架构有一些痛点:

    • 人力成本比较高:批、流两套系统,相同逻辑需要开发两遍;
    • 数据链路冗余:本身计算内容是一致的,由于是两套链路,相同逻辑需要运行两遍,产生一定的资源浪费;
    • 数据口径不一致:两套系统、两套算子、两套 UDF,通常会产生不同程度的误差,这些误差会给业务方带来非常大的困扰。

    流和批的业务场景的特点如下 image.png

image.png 如上图所示在个体发生行为数据之时会有数据源包括(埋点日志、业务消息、业务数据库)等,实时数仓送通过Flink来进行处理流式数据导入kafka中。Flink基于kafka统计数据的特点,之后导入多种服务层。 而离线数仓则将数据导入hive数据表中导入服务层。

Flink 如何做到流批一体

  • 批式计算是流式计算的特例,Everything is Streams,有界数据集(批式数据)也是一种数据流、一种特殊的数据流;
  • 站在 Flink 的角度,Everything is Streams,无边界数据集是一种数据流,一个无边界的数据流可以按时间切段成一个个有边界的数据集,所以有界数据集(批式数据)也是一种数据流。因此,不管是有边界的数据集(批式数据)还是无边界数据集,Flink 都可以天然地支持,这是 Flink 支持流批一体的基础。并且 Flink 在流批一体上,从上面的 API 到底层的处理机制都是统一的,是真正意义上的流批一体。

Apache Flink 主要从以下几个模块来做流批一体:

  • SQL 层;
  • DataStream API 层统一,批和流都可以使用 DataStream API 来开发;
  • Scheduler 层架构统一,支持流批场景;
  • Failover Recovery 层 架构统一,支持流批场景;
  • Shuffle Service 层架构统一,流批场景选择不同的 Shuffle Service;

三、总结

通过本次课程讲述了Flink的发展历史,Flink的优势在什么地方?重点在对为什么要进行流批一体处理上进行了深刻研究,然后循序渐进的学习Flink如何做到流批一体,通过多个模块进行得到能实时计算、快速、低延迟的计算引擎。经过了解认识和两家Flink,对我们青训营之后的学习乃至未来实践有不可或缺的作用。