Flink笔记

Flink 笔记

what + why + where + who + how.

1,是什么?
2,为什么要用它?
3,使用场景有哪些?
4,谁在用?
5,怎样用?

一、介绍(What)

1.1 定义

Apache Flink 是一个框架和分布式处理引擎,用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行,并能以内存速度和任意规模进行计算。

1.2 处理数据

数据处理包括处理无界和有界数据。
任何类型的数据都可以形成一种事件流。信用卡交易、传感器测量、机器日志、网站或移动应用程序上的用户交互记录,所有这些数据都形成一种流。而数据可以被作为 无界 或者 有界 流来处理。

无界流:有定义流的开始,但没有定义流的结束。它们会无休止地产生数据。无界流的数据必须持续处理,即数据被摄取后需要立刻处理。我们不能等到所有数据都到达再处理,因为输入是无限的,在任何时候输入都不会完成。处理无界数据通常要求以特定顺序摄取事件,例如事件发生的顺序,以便能够推断结果的完整性。
有界流:有定义流的开始,也有定义流的结束。有界流可以在摄取所有数据后再进行计算。有界流所有数据可以被排序,所以并不需要有序摄取。有界流处理通常被称为批处理。
Flink笔记

1.3 Flink组件层次
Flink笔记
API&Libraries层
作为分布式数据处理框架,Flink同时提供了支撑流计算和批计算的接口,同时在此基础之上抽象出不同的应用类型的组件库,如基于流处理的CEP(复杂事件处理库)、SQL&Table库和基于批处理的FlinkML(机器学习库)等、Gelly(图处理库)等。API层包括构建流计算应用的DataStream API和批计算应用的DataSet API,两者都提供给用户丰富的数据处理高级API,例如Map、FlatMap操作等,同时也提供比较低级的Process Function API,用户可以直接操作状态和时间等底层数据。

Runtime核心层
该层主要负责对上层不同接口提供基础服务,也是Flink分布式计算框架的核心实现层,支持分布式Stream作业的执行、JobGraph到ExecutionGraph的映射转换、任务调度等。

物理部署层
该层主要涉及Flink的部署模式,目前Flink支持多种部署模式:本地、集群(Standalone/YARN)、云(GCE/EC2)、Kubenetes。Flink能够通过该层能够支持不同平台的部署,用户可以根据需要选择使用对应的部署模式。

1.4 Flink 架构
Flink笔记
(1)Client客户端
客户端负责将任务提交到集群,与JobManager构建Akka(framework)连接,然后将任务提交到JobManager,通过和JobManager之间进行交互获取任务执行状态。客户端提交任务可以采用CLI方式或者通过使用Flink WebUI提交,也可以在应用程序中指定JobManager的RPC网络端口构建ExecutionEnvironment提交Flink应用。

(2)JobManager
JobManager负责整个Flink集群任务的调度以及资源的管理,从客户端中获取提交的应用,然后根据集群中TaskManager上TaskSlot的使用情况,为提交的应用分配相应的TaskSlots资源并命令TaskManger启动从客户端中获取的应用。JobManager相当于整个集群的Master节点,且整个集群中有且仅有一个活跃的JobManager,负责整个集群的任务管理和资源管理。JobManager和TaskManager之间通过Actor System进行通信,获取任务执行的情况并通过Actor System将应用的任务执行情况发送给客户端。同时在任务执行过程中,Flink JobManager会触发Checkpoints操作,每个TaskManager节点收到Checkpoint触发指令后,完成Checkpoint操作,所有的Checkpoint协调过程都是在Flink JobManager中完成。当任务完成后,Flink会将任务执行的信息反馈给客户端,并且释放掉TaskManager中的资源以供下一次提交任务使用。

(3)TaskManager
TaskManager相当于整个集群的Slave节点,负责具体的任务执行和对应任务在每个节点上的资源申请与管理。客户端通过将编写好的Flink应用编译打包,提交到JobManager,然后JobManager会根据已经注册在JobManager中TaskManager的资源情况,将任务分配给有资源的TaskManager节点,然后启动并运行任务。TaskManager从JobManager接收需要部署的任务,然后使用Slot资源启动Task,建立数据接入的网络连接,接收数据并开始数据处理。同时TaskManager之间的数据交互都是通过数据流的方式进行的。

Flink的任务运行其实是采用多线程的方式,在多个任务和Task之间通过TaskSlot方式共享系统资源,每个TaskManager中通过管理多个TaskSlot资源池进行对资源进行有效管理。

1.5 任务提交与运行组件
Flink笔记Flink笔记
二、为什么要用它?(Why)

优势

1、同时支持高吞吐、低延迟、高性能、高可用
2、支持事件时间概念(窗口计算)-保持了事件原本产生时的时序性,尽可能的避免网络或硬件系统的影响
3、支持有状态计算(版本1.4)
4、支持高度灵活的窗口操作
5、增量检查点机制(Checkpoints),基于轻量级分布式快照实现的容错,
6、基于JVM实现独立的内存管理,内存计算
7、使用Savepoints能够更方便地升级、迁移、暂停、恢复应用服务,该技术可以让用户更好的管理和实时流式计算

三、使用场景有哪些?(where)

场景
事件驱动型应用
数据分析应用
数据管道应用

3.1 事件驱动型应用

什么是事件驱动型应用?
事件驱动型应用是一类具有状态的应用,它从一个或多个事件流提取数据,并根据到来的事件触发计算、状态更新或其他外部动作。事件驱动型应用是在计算存储分离的传统应用基础上进化而来。在传统架构中,应用需要读写远程事务型数据库。相反,事件驱动型应用是基于状态化流处理来完成。在该设计中,数据和计算不会分离,应用只需访问本地(内存或磁盘)即可获取数据。系统容错性的实现依赖于定期向远程持久化存储写入 checkpoint。
下图描述了传统应用和事件驱动型应用架构的区别。
Flink笔记
事件驱动型应用的优势?
事件驱动型应用无须查询远程数据库,本地数据访问使得它具有更高的吞吐和更低的延迟。而由于定期向远程持久化存储的 checkpoint 工作可以异步、增量式完成,因此对于正常事件处理的影响甚微。事件驱动型应用的优势不仅限于本地数据访问。传统分层架构下,通常多个应用会共享同一个数据库,因而任何对数据库自身的更改(例如:由应用更新或服务扩容导致数据布局发生改变)都需要谨慎协调。反观事件驱动型应用,由于只需考虑自身数据,因此在更改数据表示或服务扩容时所需的协调工作将大大减少。

Flink 如何支持事件驱动型应用?
事件驱动型应用会受制于底层流处理系统对时间和状态的把控能力,Flink 诸多优秀特质都是围绕这些方面来设计的。它提供了一系列丰富的状态操作原语,允许以精确一次的一致性语义合并海量规模(TB 级别)的状态数据。此外,Flink 还支持事件时间和自由度极高的定制化窗口逻辑,而且它内置的 ProcessFunction 支持细粒度时间控制,方便实现一些高级业务逻辑。同时,Flink 还拥有一个复杂事件处理(CEP)类库,可以用来检测数据流中的模式。
Flink 中针对事件驱动应用的明星特性当属 savepoint。Savepoint 是一个一致性的状态映像,它可以用来初始化任意状态兼容的应用。在完成一次 savepoint 后,即可放心对应用升级或扩容,还可以启动多个版本的应用来完成 A/B 测试。

典型的事件驱动型应用实例
1)反欺诈
2)异常检测
3)基于规则的报警
4)业务流程监控
5)(社交网络)Web 应用

3.2 数据分析应用

什么是数据分析应用?
数据分析任务需要从原始数据中提取有价值的信息和指标。传统的分析方式通常是利用批查询,或将事件记录下来并基于此有限数据集构建应用来完成。为了得到最新数据的分析结果,必须先将它们加入分析数据集并重新执行查询或运行应用,随后将结果写入存储系统或生成报告。借助一些先进的流处理引擎,还可以实时地进行数据分析。和传统模式下读取有限数据集不同,流式查询或应用会接入实时事件流,并随着事件消费持续产生和更新结果。这些结果数据可能会写入外部数据库系统或以内部状态的形式维护。仪表展示应用可以相应地从外部数据库读取数据或直接查询应用的内部状态。
如下图所示,Apache Flink 同时支持流式及批量分析应用。
Flink笔记
流式分析应用的优势?
和批量分析相比,由于流式分析省掉了周期性的数据导入和查询过程,因此从事件中获取指标的延迟更低。不仅如此,批量查询必须处理那些由定期导入和输入有界性导致的人工数据边界,而流式查询则无须考虑该问题。另一方面,流式分析会简化应用抽象。批量查询的流水线通常由多个独立部件组成,需要周期性地调度提取数据和执行查询。如此复杂的流水线操作起来并不容易,一旦某个组件出错将会影响流水线的后续步骤。而流式分析应用整体运行在 Flink 之类的高端流处理系统之上,涵盖了从数据接入到连续结果计算的所有步骤,因此可以依赖底层引擎提供的故障恢复机制。

Flink 如何支持数据分析类应用?
Flink 为持续流式分析和批量分析都提供了良好的支持。具体而言,它内置了一个符合 ANSI 标准的 SQL 接口,将批、流查询的语义统一起来。无论是在记录事件的静态数据集上还是实时事件流上,相同 SQL 查询都会得到一致的结果。同时 Flink 还支持丰富的用户自定义函数,允许在 SQL 中执行定制化代码。如果还需进一步定制逻辑,可以利用 Flink DataStream API 和 DataSet API 进行更低层次的控制。此外,Flink 的 Gelly 库为基于批量数据集的大规模高性能图分析提供了算法和构建模块支持。

典型的数据分析应用实例
电信网络质量监控
移动应用中的产品更新及实验评估分析
消费者技术中的实时数据即席分析
大规模图分析
数据管道应用

3.3 数据管道应用
什么是数据管道?
提取-转换-加载(ETL)是一种在存储系统之间进行数据转换和迁移的常用方法。ETL 作业通常会周期性地触发,将数据从事务型数据库拷贝到分析型数据库或数据仓库。
数据管道和 ETL 作业的用途相似,都可以转换、丰富数据,并将其从某个存储系统移动到另一个。但数据管道是以持续流模式运行,而非周期性触发。因此它支持从一个不断生成数据的源头读取记录,并将它们以低延迟移动到终点。例如:数据管道可以用来监控文件系统目录中的新文件,并将其数据写入事件日志;另一个应用可能会将事件流物化到数据库或增量构建和优化查询索引。
下图描述了周期性 ETL 作业和持续数据管道的差异。
Flink笔记
数据管道的优势?
和周期性 ETL 作业相比,持续数据管道可以明显降低将数据移动到目的端的延迟。此外,由于它能够持续消费和发送数据,因此用途更广,支持用例更多。

Flink 如何支持数据管道应用?
很多常见的数据转换和增强操作可以利用 Flink 的 SQL 接口(或 Table API)及用户自定义函数解决。如果数据管道有更高级的需求,可以选择更通用的 DataStream API 来实现。Flink 为多种数据存储系统(如:Kafka、Kinesis、Elasticsearch、JDBC数据库系统等)内置了连接器。同时它还提供了文件系统的连续型数据源及数据汇,可用来监控目录变化和以时间分区的方式写入文件。

典型的数据管道应用实例
电子商务中的实时查询索引构建
电子商务中的持续 ETL

四、Flink用户(Who)

1、亚马逊
2、阿里巴巴
3、腾讯
4、华为
5、滴滴
6、小米

五、怎么用(How)

5.1 First Step 找官网

官网 :https://ci.apache.org/projects/flink/flink-docs-release-1.11/zh/

5.2 数据处理过程
Flink笔记
流处理应用的基本组件

可以由流处理框架构建和执行的应用程序类型是由框架对 流、状态、时间的支持程度来决定的。


显而易见,(数据)流是流处理的基本要素。然而,流也拥有着多种特征。这些特征决定了流如何以及何时被处理。Flink 是一个能够处理任何类型数据流的强大处理框架。
有界 和 无界 的数据流:流可以是无界的;也可以是有界的,例如固定大小的数据集。Flink 在无界的数据流处理上拥有诸多功能强大的特性,同时也针对有界的数据流开发了专用的高效算子。
实时 和 历史记录 的数据流:所有的数据都是以流的方式产生,但用户通常会使用两种截然不同的方法处理数据。或是在数据生成时进行实时的处理;亦或是先将数据流持久化到存储系统中——例如文件系统或对象存储,然后再进行批处理。Flink 的应用能够同时支持处理实时以及历史记录数据流。

状态
只有在每一个单独的事件上进行转换操作的应用才不需要状态,换言之,每一个具有一定复杂度的流处理应用都是有状态的。任何运行基本业务逻辑的流处理应用都需要在一定时间内存储所接收的事件或中间结果,以供后续的某个时间点(例如收到下一个事件或者经过一段特定时间)进行访问并进行后续处理。
应用状态是 Flink 中的一等公民,Flink 提供了许多状态管理相关的特性支持,其中包括:
多种状态基础类型:Flink 为多种不同的数据结构提供了相对应的状态基础类型,例如原子值(value),列表(list)以及映射(map)。开发者可以基于处理函数对状态的访问方式,选择最高效、最适合的状态基础类型。
插件化的State Backend:State Backend 负责管理应用程序状态,并在需要的时候进行 checkpoint。Flink 支持多种 state backend,可以将状态存在内存或者 RocksDB。RocksDB 是一种高效的嵌入式、持久化键值存储引擎。Flink 也支持插件式的自定义 state backend 进行状态存储。
精确一次语义:Flink 的checkpoint和故障恢复算法保证了故障发生后应用状态的一致性。因此,Flink 能够在应用程序发生故障时,对应用程序透明,不造成正确性的影响。
超大数据量状态:Flink 能够利用其异步以及增量式的 checkpoint 算法,存储数 TB 级别的应用状态。
可弹性伸缩的应用:Flink 能够通过在更多或更少的工作节点上对状态进行重新分布,支持有状态应用的分布式的横向伸缩。

时间
时间是流处理应用另一个重要的组成部分。因为事件总是在特定时间点发生,所以大多数的事件流都拥有事件本身所固有的时间语义。进一步而言,许多常见的流计算都基于时间语义,例如窗口聚合、会话计算、模式检测和基于时间的 join。流处理的一个重要方面是应用程序如何衡量时间,即区分事件时间(event-time)和处理时间(processing-time)。
Flink 提供了丰富的时间语义支持。
事件时间模式:使用事件时间语义的流处理应用根据事件本身自带的时间戳进行结果的计算。因此,无论处理的是历史记录的事件还是实时的事件,事件时间模式的处理总能保证结果的准确性和一致性。
Watermark支持:Flink 引入了 watermark 的概念,用以衡量事件时间进展。Watermark也是一种平衡处理延时和完整性的灵活机制。
迟到数据处理:当以带有 watermark 的事件时间模式处理数据流时,在计算完成之后仍会有相关数据到达。这样的事件被称为迟到事件。Flink 提供了多种处理迟到数据的选项,例如将这些数据重定向到旁路输出(side output)或者更新之前完成计算的结果。
处理时间模式:除了事件时间模式,Flink 还支持处理时间语义。处理时间模式根据处理引擎的机器时钟触发计算,一般适用于有着严格的低延迟需求,并且能够容忍近似结果的流处理应用。

5.3 分层 API
Flink笔记
Flink笔记

(1)SQL API.
Flink 支持两种关系型的 API,Table API 和 SQL。这两个 API 都是批处理和流处理统一的 API,这意味着在无边界的实时数据流和有边界的历史记录数据流上,关系型 API 会以相同的语义执行查询,并产生相同的结果。Flink 的关系型 API 旨在简化数据分析、数据流水线和 ETL 应用的定义。Flink提供了统一的SQL API完成对批计算和流计算的处理,目前SQL API也是社区重点发展的接口层,对SQL API也正在逐步完善中,其主要因为SQL语言具有比较低的学习成本,能够让数据分析人员和开发人员更快速地上手,帮助其更加专注于业务本身而不是受限于复杂的编程接口。
(2)Table API
Flink 的关系型 API 之一,Table API将内存中的DataStream和DataSet数据集在原有的基础之上增加Schema信息,将数据类型统一抽象成表结构,然后通过Table API提供的接口处理对应的数据集。SQL API则可以直接查询Table API中注册表中的数据表。Table API构建在DataStream和DataSet之上的同时,提供了大量面向领域语言的编程接口,例如GroupByKey、Join等操作符,提供给用户一种更加友好的处理数据集的方式。除此之外,Table API在转换为DataStream和DataSet的数据处理过程中,也应用了大量的优化规则对处理逻辑进行了优化。同时Table API中的Table可以和DataStream 及DataSet之间进行相互转换。
(3)DataStream API和DataSet API
DataStream API和DataSet API主要面向具有开发经验的用户,用户可以使用DataStream API处理无界流数据,使用DataSet API处理批量数据。DataStream API和DataSet API接口同时提供了各种数据处理接口,例如map,filter、oins、aggregations、window等方法,同时每种接口都支持了Java、Scala及Python等多种开发语言的SDK。
(4)Stateful Stream Process API
Stateful Stream Process API是Flink中处理Stateful Stream最底层的接口,用户可以使用Stateful Stream Process 接口操作状态、时间等底层数据。ProcessFunction 可以处理一或两条输入数据流中的单个事件或者归入一个特定窗口内的多个事件。它提供了对于时间和状态的细粒度控制。开发者可以在其中任意地修改状态,也能够注册定时器用以在未来的某一时刻触发回调函数。因此,你可以利用 ProcessFunction 实现许多有状态的事件驱动应用所需要的基于单个事件的复杂业务逻辑。使用Stream Process API接口开发应用的灵活性非常强,可以实现非常复杂的流式计算逻辑,但是相对用户使用成本也比较高,一般企业在使用Flink进行二次开发或深度封装的时候会用到这层接口。

5.4 编程模型
5步曲
第一步:设定执行环境 getExecutionEnvironment
第二步:初始化数据,指定数据源,读入输入数据 datasource
第三步:对数据执行转换分区操作,对数据集指定转换操作逻辑 transformation
第四步:指定输出位置及输出结果 sink
第五步:指定任务名称并出发任务执行 execute

public class StreamingJob {
public static void main(String[] args) throws Exception {
// 第一步,设定执行环境,创建Flink的流式计算环境
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// 第二步:初始化数据,指定数据源,读入输入数据 datasource监听本地9000端口
DataStream text = env.socketTextStream(“127.0.0.1”, 9000, “\n”);
// 第三步:对数据执行转换分区操作,将接收的数据进行拆分,分组,窗口计算并且进行聚合输出
DataStream windowCounts = text.flatMap(new FlatMapFunction<String, WordWithCount>() {
@Override
public void flatMap(String value, Collector out) {
for (String word : value.split("\s")) {
out.collect(new WordWithCount(word, 1L));
}
}
})
.keyBy(“word”)
.timeWindow(Time.seconds(5), Time.seconds(1))
.reduce(new ReduceFunction() {
@Override
public WordWithCount reduce(WordWithCount a, WordWithCount b) {
return new WordWithCount(a.word, a.count + b.count);
}
});
// 第四步:指定输出位置及输出结果 sink,打印结果
windowCounts.print().setParallelism(1);
//第五步:指定任务名称并出发任务执行 execute,打印结果
env.execute(“Socket Window WordCount”);
}
// Data type for words with count
public static class WordWithCount {

public String word;
public long count;

public WordWithCount() {}

public WordWithCount(String word, long count) {
this.word = word;
this.count = count;
}

@Override
public String toString() {
return word + " : " + count;
}
}

5.5 API 简介

SQL API
Table API
DataSet API
DataStream API
Stateful Stream Process API
Flink笔记
Flink笔记
Api 详情 :

https://ci.apache.org/projects/flink/flink-docs-release-1.11/dev/datastream_api.html

Connector 详情 :

https://ci.apache.org/projects/flink/flink-docs-master/dev/batch/connectors.html

5.6 组件栈简介
Flink复杂事件处理
Flink Gelly 图计算
Flink 机器学习

5.7 环境、部署及升级

环境:

jdk环境
maven环境
scala环境
hadoop环境

部署:

(集群部署7*24小时运行)
Flink已与多种集群管理服务紧密集成,如 Hadoop YARN, Mesos, 以及 Kubernetes。当集群中某个流程任务失败后,一个新的流程服务会自动启动并替代它继续执行。同时Flink内置了为解决单点故障问题的高可用性服务模块,此模块是基于Apache ZooKeeper 技术实现的,Apache ZooKeeper是一种可靠的、交互式的、分布式协调服务组件

1)基于standalone集群
2)基于第三方组件(hadoop Yarn、Apache Mesos、Kubernetes)

升级:
驱动关键业务服务的流应用是经常需要维护的。比如需要修复系统漏洞,改进功能,或开发新功能。然而升级一个有状态的流应用并不是简单的事情,因为在我们为了升级一个改进后版本而简单停止当前流应用并重启时,我们还不能丢失掉当前流应用的所处于的状态信息。

Flink的 Savepoint 服务就是为解决升级服务过程中记录流应用状态信息及其相关难题而产生的一种唯一的、强大的组件。一个 Savepoint,就是一个应用服务状态的一致性快照,因此其与checkpoint组件的很相似,但是与checkpoint相比,Savepoint 需要手动触发启动,而且当流应用服务停止时,它并不会自动删除。Savepoint 常被应用于启动一个已含有状态的流服务,并初始化其(备份时)状态。

https://flink.apache.org/zh/flink-operations.html

5.8 监控与性能优化

监控
系统指标:Flink集群层面指标,CPU负载,各组件内存使用情况
用户指标:用户在任务中自定义注册的监控指标,用于获取用户的业务状况(Flink UI,Rest Api,Reporter)

优化
1,backpressure监控与优化
当系统中下游算子的处理速度下降,导致数据处理速率低于数据接入熟虑时,从而导致大量数据积压在Flink系统中,导致系统无法正常进行。
解决机制:backpressure 反压,Flink反压数据采集,在Flink UI 点击Back pressure 标签触发反压检测,通过触发JVM进程获取到反压监控数据。反压比例等于反压出现次数/采样次数。三个级别:OK(比例010%)、LOW(1050%)、HIGH(50~100%)。当所有subtasks都是HIGH,表示系统触发了比较多的触发,需要适当增加subtask并发度或者降低数据生产速度
web.backpressure.cleanup-interval:60s //等待页面并获取反压数据的时间间隔
web.backpressure.delay-between-samples:50ms //抽样到确认到反压状态之间的时延
web.backpressure.num-samples:100 //抽样数

2,checkpointing 监控与优化
最小时间间隔,设置较小的时间间隔设置,可以降低Checkpointing对系统的性能影响
状态容量预估,对整个任务的状态数据量进行预估
异步Snapshot,默认情况下,Checkpointing操作是同步执行的,在条件允许的情况下应该尽可能使用异步
状态数据压缩

3,内存优化
调整JobManager内存配置:主要承担管理集群资源、接收任务、调度Task、收集任务状态、及管理TaskManager
调整TaskManager内存配置:集群中的工作节点,所有任务的计算都逻辑均在该上执行。
设置堆内存、设置是否开启堆外内存、为每个TaskManager分配slot数量
调整Network Buffers配置:主要缓存分布式数据处理过程中的输入数据,在Repartitionting和Broadcating操心作过程中需消耗大量的内存进行缓冲。可通过指定Network Buffers内存数量和配置内存比例。
taskmanager.network.numberOfBuffers:500 // Network Buffer 内存块数量
taskmanager.memory.segment-size:24k//内存块大小
taskmanager.network.memory.fraction://JVM 中用于network buffers内存比例

5.9 其他

老师领进门,修为靠自身!

https://bbs.huaweicloud.com/blogs/148583
《Flink原理、实战与性能优化》 @张利兵