Apache Flink 是一个分布式大数据处理引擎,可对有界数据流和无界数据流进行有状态或无状态的计算,能够部署在各种集群环境,对各种规模大小的数据进行快速计。
简介
Flink诞生于欧洲的一个大数据研究项目StratoSphere。该项目是柏林工业大学的一个研究性项目。早期,Flink是做Batch计算的,但是在2014年,StratoSphere里面的核心成员孵化出Flink,同年将Flink捐赠Apache,并在后来成为Apache的顶级大数据项目,同时Flink计算的主流方向被定位为Streaming,即用流式计算来做所有大数据的计算,这就是Flink技术诞生的背景。
2015开始阿里开始介入Flink 负责对资源调度和流式sql的优化,成立了阿里内部版本Blink在最近更新的1.10版本中,Blink合并入Flink。
特性
- 支持高吞吐、低延迟、高性能的流处理
- 支持带有事件时间的窗口(Window)操作
- 支持有状态计算的Exactly-once语义
- 支持高度灵活的窗口(Window)操作,支持基于time、count、session,以及data-driven的窗口操作
- 支持具有Backpressure功能的持续流模型
- 支持基于轻量级分布式快照(Snapshot)实现的容错,可以保证数据有状态的计算,记录数据的状态,如果数据处理失败了,可以再恢复到原来的状态
- 一个运行时同时支持Batch on Streaming处理和Streaming处理
- Flink在JVM内部实现了自己的内存管理
- 支持迭代计算
- 支持程序自动优化:避免特定情况下Shuffle、排序等昂贵操作
- 可伸缩,可以支持上千个节点
概念
Streams
流,分为有界数据流与无界数据流
- 无界流 有定义流的开始,但没有定义流的结束。它们会无休止地产生数据。无界流的数据必须持续处理,即数据被摄取后需要立刻处理。我们不能等到所有数据都到达再处理,因为输入是无限的,在任何时候输入都不会完成。处理无界数据通常要求以特定顺序摄取事件,例如事件发生的顺序,以便能够推断结果的完整性。
- 有界流 有定义流的开始,也有定义流的结束。有界流可以在摄取所有数据后再进行计算。有界流所有数据可以被排序,所以并不需要有序摄取。有界流处理通常被称为批处理。
State
状态是计算过程中的数据信息,在容错恢复和 Checkpoint 中有重要的作用,流计算在本质上是 Incremental Processing,因此需要不断查询保持状态;另外,为了确保 Exactly- once 语义,需要数据能够写入到状态中;而持久化存储,能够保证在整个分布式系统运行失败或者挂掉的情况下做到 Exactly- once,这是状态的另外一个价值。
Time
分为 Event time、Ingestion time、Processing time,Flink 的无限数据流是一个持续的过程,时间是我们判断业务状态是否滞后,数据处理是否及时的重要依据。
架构
基本组件栈
Flink基础组件栈Flink的架构遵循着分层的架构设计理念,在降低系统耦合度的同时,也为上层用户构建Flink应用提供了丰富且友好的接口。
Flink分为架构分为三层,由上往下依次是API&Libraries层、Runtime核心层以及物理部署层。
-
API&Libraries层
作为分布式数据处理框架,Flink同时提供了支撑计算和批计算的接口,同时在此基础上抽象出不同的应用类型的组件库,如基于流处理的CEP(复杂事件处理库)、SQL&Table库和基于批处理的FlinkML(机器学习库)等、Gelly(图处理库)等。API层包括构建流计算应用的DataStream API和批计算应用的DataSet API,两者都提供给用户丰富的数据处理高级API,例如Map、FlatMap操作等,同时也提供比较低级的Process Function API,用户可以直接操作状态和时间等底层数据。
-
Runtime核心层
该层主要负责对上层不同接口提供基础服务,也是Flink分布式计算框架的核心实现层,支持分布式Stream作业的执行、JobGraph到ExecutionGraph的映射转换、任务调度等。将DataSteam和DataSet转成统一的可执行的Task Operator,达到在流式引擎下同时处理批量计算和流式计算的目的。
-
物理部署层
层主要涉及Flink的部署模式,目前Flink支持多种部署模式:本地、集群(Standalone、YARN)、云(GCE/EC2)、Kubenetes。Flink能够通过该层能够支持不同平台的部署,用户可以根据需要选择使用对应的部署模式。
基本架构图
1.pngFlink系统主要由两个组件组成,分别为JobManager和TaskManager,Flink架构也遵循Master-Slave架构设计原则,JobManager为Master节点,TaskManager为Worker(Slave)节点。所有组件之间的通信都是借助于Akka Framework,包括任务的状态以及Checkpoint触发等信息。
-
Client客户端
客户端负责将任务提交到集群,与JobManager构建Akka连接,然后将任务提交到JobManager,通过和JobManager之间进行交互获取任务执行状态。客户端提交任务可以采用CLI方式或者通过使用Flink WebUI提交,也可以在应用程序中指定JobManager的RPC网络端口构建ExecutionEnvironment提交Flink应用。
-
JobManager
JobManager负责整个Flink集群任务的调度以及资源的管理,从客户端中获取提交的应用,然后根据集群中TaskManager上TaskSlot的使用情况,为提交的应用分配相应的TaskSlots资源并命令TaskManager启动从客户端中获取的应用。JobManager相当于整个集群的Master节点,且整个集群中有且仅有一个活跃的JobManager,负责整个集群的任务管理和资源管理。JobManager和TaskManager之间通过Actor System进行通信,获取任务执行的情况并通过Actor System将应用的任务执行情况发送给客户端。同时在任务执行过程中,Flink JobManager会触发Checkpoints操作,每个TaskManager节点收到Checkpoint触发指令后,完成Checkpoint操作,所有的Checkpoint协调过程都是在Flink JobManager中完成。当任务完成后,Flink会将任务执行的信息反馈给客户端,并且释放掉TaskManager中的资源以供下一次提交任务使用。
-
TaskManager
TaskManager相当于整个集群的Slave节点,负责具体的任务执行和对应任务在每个节点上的资源申请与管理。客户端通过将编写好的Flink应用编译打包,提交到JobManager,然后JobManager会根据已经注册在JobManager中TaskManager的资源情况,将任务分配给有资源的TaskManager节点,然后启动并运行任务。TaskManager从JobManager接收需要部署的任务,然后使用Slot资源启动Task,建立数据接入的网络连接,接收数据并开始数据处理。同时TaskManager之间的数据交互都是通过数据流的方式进行的。
每个TaskManager最少持有 1 个 Slot,Slot 是 Flink 执行 Job 时的最小资源分配单位,在 Slot 中运行着具体的 Task 任务。
项目依赖
Flink系统代码分为多个子项目。目的是减少实现Flink程序的项目所需的依赖项数量,并促进更轻松地测试较小的子模块。 下图显示了各个项目及其依赖性。
1.png除了上图中列出的项目,Flink当前还包含以下子项目:
- flink-dist:分发项目。它定义了如何将编译后的代码,脚本和其他资源组合到准备使用的最终文件夹结构中。
- flink-quickstart:用于快速入门和教程的脚本,maven原型和示例程序。
- flink-contrib:一系列早期版本的项目以及用户提供的有用工具。后者的代码主要由外部贡献者维护。与其余代码相比,被flink-contrib接受的代码要求更低。
编程模型
2.pngFlink 提供几种不同层次的抽象来开发 流/批(streaming/batch)程序
-
最低级的抽象仅提供状态流(stateful streaming),它通过 Process Function (处理函数)内嵌在 DataStream API 中。它容许用户自由地处理来自一个或多个流的事件,并且使用一致的容错状态。此外,用户也可以给事件时间和处理时间注册回调,使得程序可以实现复杂的计算。
-
实践中,多数的应用程序不需要使用上述的低级的抽象,仅需要使用核心接口(Core API)来编码,比如 DataStream API (数据流接口,有界/无界流) 和 DataSet API (数据集接口,有界数据集)。这些流畅的接口为数据处理提供了通用构建流程,诸如用户指定的转换(transformation)、连接(join)、聚合(aggregation)、窗口(window)、状态(state)等不同形式。这些接口处理的数据类型在不同的编程语言中以类(class)的形式呈现。
低层次的处理函数(Process Function)与数据流接口(DataStream API)的交互,使得某些特定的操作可以抽象为更低的层次成为可能。数据集接口(DataSet API)在有界的数据集上提供额外的原始操作,例如循环和迭代(loops/iterations)。
-
表接口(Table API)使以表为中心的声明性 DSL,可以动态地改变表(当展示流的时候)。Table API遵循(扩展)关系型模型:表附加了一个模式(schema)(类似于关系型数据库中的表),此API提供了可比较的操作,例如select,project,join,group-by,aggregate等。Table API程序以声明方式定义应该执行的逻辑操作,而不是准确地指定操作代码。 尽管Table API可以通过各种类型的用户定义函数进行扩展,但它的表现力不如Core API,但使用起来更简洁(编写的代码更少)。 此外,Table API程序还会通过优化程序,在执行之前应用优化规则。
可以在表和DataStream/ DataSet之间无缝转换,允许在程序中混合Table API以及DataStream和DataSet API。
-
Flink提供的最高级抽象是SQL。 这种抽象在语义和表达方面类似于Table API,但是将程序表示为SQL查询表达式。 SQL抽象与Table API紧密交互,SQL查询可以在Table API中定义的表上执行。
应用场景
数据管道
数据管道应用Data Pipeline 的核心场景类似于数据搬运并在搬运的过程中进行部分数据清洗或者处理,而整个业务架构图的左边是 Periodic ETL,它提供了流式 ETL 或者实时 ETL,能够订阅消息队列的消息并进行处理,清洗完成后实时写入到下游的 Database 或 File system 中。
实时数仓
当下游要构建实时数仓时,上游则可能需要实时的 Stream ETL。这个过程会进行实时清洗或扩展数据,清洗完成后写入到下游的实时数仓的整个链路中,可保证数据查询的时效性,形成实时数据采集、实时数据处理以及下游的实时 Query。
搜索引擎推荐
搜索引擎这块以淘宝为例,当卖家上线新商品时,后台会实时产生消息流,该消息流经过 Flink 系统时会进行数据的处理、扩展。然后将处理及扩展后的数据生成实时索引,写入到搜索引擎中。这样当淘宝卖家上线新商品时,能在秒级或者分钟级实现搜索引擎的搜索。
数据分析
数据分析应用如图,左边是 Batch Analytics,右边是 Streaming Analytics。Batch Analysis 就是传统意义上使用类似于 Map Reduce、Hive、Spark Batch 等,对作业进行分析、处理、生成离线报表,Streaming Analytics 使用流式分析引擎如 Storm,Flink 实时处理分析数据,应用较多的场景如实时大屏、实时报表。
数据驱动
数据驱动应用从某种程度上来说,所有的实时的数据处理或者是流式数据处理都是属于数据驱动,流计算本质上是 数据驱动 计算。应用较多的如风控系统,当风控系统需要处理各种各样复杂的规则时,数据驱动就会把处理的规则和逻辑写入到 Datastream 的 API 或者是 ProcessFunction 的 API 中,然后将逻辑抽象到整个 Flink 引擎中,当外面的数据流或者是事件进入就会触发相应的规则,这就是数据驱动的原理。在触发某些规则后,数据驱动会进行处理或者是进行预警,这些预警会发到下游产生业务通知,这是数据驱动的应用场景数据驱动在应用上更多应用于复杂事件的处理。
网友评论