------概括
1个低延迟,高吞吐,统一的大数据计算引擎
-
达到毫秒级延迟
-
金融级的数据处理能力
因为:Flink提供了一个Exactly-once(只执行一次)的一致性语义。保证了数据的正确性。flink还提供很多高级的功能。比如它提供了有状态的计算,支持状态管理,支持强一致性的数据语义以及支持Event Time,WaterMark对消息乱序的处理。
------大数据计算引擎
流式计算:
Storm , Flink , SparkStream
批处理:
Spark , MR ,Pig ,Flink
同时支持流式和批处理:
Apache Spark 和 Apache Flink
Spark是基于批来模拟流计算,Flink是基于流来模拟批计算.
------statefule 有状态计算
- Flink提供了内置的对状态的一致性处理,即任何任务发生Failover,其状态不会丢失,不会被多算少算,同时提供了非常高的性能.
- Flink提供内置的状态处理,将状态存储在Flink内部.
这种方式的优点:
- 降低了计算引擎对外部系统的依赖以及部署,使运维更加简单
- 对性能带来极大提升(无需外部访问 定期持久化)
------Spark Flink Storm对比
- Spark:
以批处理为核心,用微批处理来模拟流式计算
支持sql处理 , 流处理 , 批处理
关于流处理:因为是微批处理模拟,所以实时性弱,吞吐量大,延迟度高. - Flink: (碾压另外两种流式框架)
以流式处理为核心,用流式处理来模拟批处理
支持sql处理 , 流处理 , 批处理
对于流处理:实时性强,吞吐量大,延迟度低. - Storm:
一条一条处理数据,实时性强,吞吐量低,延迟度低.
------有界流 & 无界流
Flink是一个流式分布式计算引擎,用于对无界和有界数据流进行计算.
-
无界流:
有开始时间但没有截止时间,它们在生成时提供数据,但不会被终止。
无界流必须连续处理数据,即必须在摄取事件后立即处理事件。
它无法等待所有输入数据到达,因为输入是无界的,如果是这样,在任何 时间点都不会完成。
处理无界数据通常要求以特定顺序摄取事件,例如事件发生的顺序,以便 能够推断结果完整性。 -
有界流:
具有起始时间和截止时间,它可以在执行任何的计算之前,先通过摄取所有 数据后再来处理有界流。
处理有界流不需要有序摄取,因为可以对有界数据集进行排序。
有界流的处理也称为批处理。
------代码流程
- 创建ExecutionEnvironment/StreamExecutionEnvironment 执行环境对象
- 通过执行环境对象创建出source(源头)对象
- 基于source对象做各种转换,注意:在flink中转换算子也是懒执行的
- 定义结果输出到哪里(控制台,kafka,数据库等)
- 最后调用StreamExecutionEnvironment/ExecutionEnvironment 的excute方法,触发执行。
注:每个flink程序由source operator + transformation operator + sink operator组成
scala 代码需要引入scala隐式转换
import org.apache.flink.api.scala._
------Flink提交任务方式
standalone
1.命令行提交
bin目录下
./flink run -c 方法全路径(com.xxxxx.xxx) jar包的路径
2. webui方式提交
yarn
1. Yarn-session模式
该模式是预先在yarn上面划分一部分资源给flink集群用,flink提交的所有任务,共用这些资源。如下图所示
1.1启动yarn-session,并指明分配资源
./yarn-session.sh -n 3 -jm 1024 -tm 1024
1.2从日志中知道 jobmanager地址后,提交任务:
./flink run -m node01:55695 /opt/sxt/flinkTest.jar
需指定jobmanager地址
1.3找到application_id停止yarn上的flink集群
2. Single job模式
该模式是每次提交任务,都会创建一个新的flink集群,任务之间互相独立,互不影响,方便管理。任务执行完成之后,flink集群也会消失。如下图:
任务提交命令:
./flink run -m yarn-cluster -yn 2 /opt/sxt/flinkTest.jar
无需指定jobmanager地址(不固定)
------flink on yarn 的运行原理
步骤:
- 当启动了Flink Yarn Client会话,客户端首先检查请求资源(容器 内存)是否可用.之后它会上传包含Flink配置文件和jar包到HDFS上
- 客户端向ResourceManage申请1个container资源去启动ApplicationMaster进程
- ResourceManager选择1台NodeManager, NodeManager根据配置文件和jar包做初始化工作,然后启动ApplicationMaster同时启动JobManager,AM知道JobMaster地址(自己),它为TaskManager生成1个新的Flink文件并上传到HDFS上,用来连接JobManager和TaskManager
- AM开始为Flink的TaskManager分配container(容器)在对应的NodeManager上启动taskManager
- TaskManager从HDFS上下载 配置文件和jar包一旦这些下载完成就开始准备任务的接收和运行
------Windows-窗口机制 ★
Windows将流拆分为有限大小的桶,Flink认为batch是Streaming的一个特例,Flink底层是一个流式引擎,在上面实现了流处理和批处理.而窗口(window)就是从Streaming到Batch的一个桥梁.
窗口是可以基于时间驱动的(timeWindow 例如每30秒),也可以是基于数据驱动的(countWindow 例如每100个元素)
Flink要操作窗口,先得将StreamSource 转成WindowedStream
其他流 → window流
Window
KeyedStream → WindowedStream
WindowAll
DataStream → AllWindowedStream
window流 → 其他流
Window Apply
WindowedStream → DataStream
AllWindowedStream → DataStream
Window Reduce
WindowedStream → DataStream
Aggregations on windows
WindowedStream → DataStream
基于不同事件驱动的窗口可以分为以下几类:
翻滚窗口(tumblingWindow)
可看成翻折,每个事件只能属于1个窗口, 窗口有固定尺寸窗口与窗口 之间没有重叠.
翻滚窗口基于时间驱动
//基于时间驱动,每隔1分钟划分一个窗口
xxx.timeWindow(Time.minutes(1))
翻滚窗口基于事件驱动
//基于事件驱动,每100个事件,划分一个窗口
xxx.countWindow(100)
滑动窗口(SlidingWindow)
窗口与窗口之间有重叠,一个元素可对应多个窗口
滑动窗口基于时间驱动
//基于时间驱动,每隔30s计算一下最近一分钟的数据
xxx.timeWindow(Time.minutes(1),Time.seconds(30))
滑动窗口基于事件驱动
//基于事件驱动,每10个元素触发一次计算,窗口里的事件数据最多 为100个
xxx.countWindow(100,10)
滑动窗口和滚动窗口都使用timeWindow时区分看参数数量(翻滚是1个参数,滑动是2个参数)
会话窗口(SessionWindow)
会话窗口不重叠,没有固定开始和结束时间,当会话一段时间未接收到元素后会关闭会话窗口.
//如果连续10s内,没有数据进来,则会话窗口断开。 xxx.window(ProcessingTimeSessionWindows.withGap(Time.seconds(30)))
------★★★时间(event time)与水印/水位线(watermark)
时间类型
Event Time (事件时间)
事件时间是每个事件在其设备上发生的时间.
一般发生在进入Flink之前嵌入到记录,并可从记录中提取时间戳
事件时间对于乱序,延时,或者数据重放等情况都能给出正确结果.
事件时间依赖事件本身,和物理时间没有关系.
使用事件时间的程序必须指定如何生成事件时间watermark(水印/水位线)
Ingestion time (摄入时间)
摄入时间是数据进入Flink框架的时间,在Source Operator中设置的.
相比Processing time可提供更可预测结果,时间戳比较稳定(只在源头记 录一次).
Processing time(处理时间)
处理时间指当前机器处理该事件的时间.
它是当数据流入到具体某个算子时候相应的系统时间。
虽提供了最小的延时和最佳的性能。但在分布式和异步环境中,处理时间不能提供确定性.
设置时间
一般写在Flink代码开头, 用于定义数据源使用什么时间,在时间窗口处理中使用什么时间。
分别对应:处理时间 摄入时间 事件时间
WaterMark (水印/水位线)
产生/使用原因:
流处理从事件产生到流经source再到operator,中间是有一些过程和时间的,少数情况下由于网络,背压等原因使数据流到operator时不能按照事件产生时间来排序,造成乱序(out-of-order或说late element)
我们对于数据延迟不能无限期的等待,必须要有机制保证特定时间必须去触发window进行计算.这个机制就是WaterMark
介绍:
WaterMark是为了处理EventTime时间类型的窗口计算提出的一种机制,本质上是时间戳.通常用WaterMark结合window来实现乱序处理.
流程/详细
operator处理基于EventTime的时间窗口来处理数据时,必须确定所有属于该窗口的消息全部流入此算子(operator),才能开始处理数据.
但由于数据可能是乱序的,operator无法直接确认数据全部流入该算子的时间.
WaterMark包含一个时间戳,Flink用WaterMark来标记所有小于该时间戳的消息都已经流入,Flink数据源再确认所有小于某时间戳消息都已输入到Flink流系统之后,会生成1个包含该时间戳的WaterMark,插入到消息流中输入到Flink流处理系统中,Fling operator算子按照时间窗口缓存所有流入的消息,当操作符处理到WaterMark时,会对所有小于WaterMark时间戳的时间窗口的数据进行处理,与WaterMark一并发送到下一个操作符节点.
问题:
- 各个时间窗口里的数据,什么时候触发计算?
当watermark时间 >= window_endTime - WaterMark是怎么产生的?
当[window_startTime,window_endTime)中有数据存在
WaterMark产生方式
Punctuated(不时打断) – 数据流中每一个递增的EventTime都会产生一个WaterMark
—也就是每个没出现新的最大的EventTime时间就会产生新的WaterMark
这种方式实际生产中在TPS很高的情况下会产生大量的WaterMark,会对下游算子造成一定压力.一般只在实时性要求高的情况下使用.
Periodic(周期) – 一定时间间隔或达到一定记录数产生一个WaterMark
实际生产中必须结合时间和累积条数两个维度继续周期性产生WaterMark,否则极端情况下会有很大的延时.
------累加器 & 广播变量 & 分布式缓存
Accumulator – 累加器
可在分布式统计数据,只有在任务结束之后才能获取累加器的最终结果。计数器是累加器的具体实现,
有:IntCounter,LongCounter和DoubleCounter。
累加器注意事项:
1.需要在算子内部创建累加器对象
2. 通常在Rich函数中的open方法中注册累加器,指定累加器的名称
3. 在当前算子内任意位置可以使用累加器
4. 必须当任务执行结束后,通过env.execute(xxx)执行后的JobExecutionResult对象获取累加器的值。
累加器代码
广播变量
- 广播:数据集合通过withBroadcastSet进行广播
- 访问:可通过getRuntimeContext().getBroadcastVariable访问
分布式缓存
Flink提供了一个分布式缓存,类似于Apache Hadoop。执行程序时,Flink会自动将文件或目录复制到所有Worker的本地文件系统。用户函数可以查找指定名称下的文件或目录,并从worker的本地文件系统访问它。
分布式缓存
------容错机制和状态
1.简介
Flink提供了一种容错机制,可以持续恢复数据流应用程序的状态。该机制确保即使出现故障,经过恢复,程序的状态也会回到以前的状态。
Flikn支持at least once语义和exactly once语义
Flink通过定期地做checkpoint来实现容错和恢复,容错机制不断地生成数据流的快照。对于小状态的流应用程序,这些快照非常轻量级并且可以经常生成快照,而不会对性能产生太大的影响。流应用程序的状态存储在一个可配置的地方(例如主节点或HDFS)。
如果出现程序故障(由于机器、网络或软件故障),Flink将停止分布式流数据流。然后系统重新启动operator,并将其设置为最近一批的检查点。
注意:
- 默认情况下,禁用checkpoint(检查点)
- 要使得容错机制正常运行,数据流source需要能够将流倒回到指定的之前的点。比如Apache Kafka有这种方法,flink与Kafka的connector可以利用重置kafka topic的偏移量来达到数据重新读取的目的。
- 由于Flink的检查点由分布快照实现,以下的“检查点”和“快照”是同意义的
2.CheckPoint检查点
Flink的容错机制的核心部分是生成分布式数据流和operator状态一致的快照。这些快照充当检查点,系统可以在发生故障时将其回滚。分布式快照是由Chandy-Lamport算法实现的
Barriers (栅栏)
Flink的分布式快照的核心元素是stream barriers。这些barriers被注入到数据流中,作为数据流的一部分和其他数据一同流动,barriers不会超过其他数据提前到达(不会乱序到达)。一个Barrier将数据流中的数据分割成两个数据集,即进入当前快照的数据和进入下一次快照的数据。每个Barrier带有一个ID,该ID为将处于该Barrier之前的数据归入快照的检查点的ID。Barrier不会打断数据流的流动,所以它是十分轻量级的。来自不同的快照的多个Barrier可以同一时间存在于同一个流中,也就是说,不同的快照可以并行同时发生。如下图所示: