简介
Apache Flink 是一个开源的流处理框架,具有强大的流处理和批处理功能
Apache Flink 是一个’框架’和’分布式’处理引擎,用于对无界和有界数据流
进行状态计算
Apache Flink 的定义
Apache Flink是一个框架和分布式处理引擎,用于在无界和有界数据流上进行有状态计算。Flink被设计为可以在所有常见的集群环境中运行,以内存中的速度和任意规模执行计算。
Flink核心
- 状态 + 时间(水位线) + 事件驱动
- 有状态 : 输入值 + 初始值 = 输出值
- 无状态 : 输入值 = 输出值
Flink 主要特点
流数据
更真实地反映了我们的生活方式- 低延迟(Spark Streaming 的延迟是秒级,Flink 延迟是毫秒级)
- 高吞吐(阿里每秒钟使用Flink 处理4.6PB,双十一大屏)
- 结果的准确性和良好的容错性(exactly-once)
Flink 其他特点
- 支持事件时间(event-time)和处理时间(processing-time)语义
- 精确一次(exactly-once)的状态一致性保证
- 低延迟,每秒处理数百万个事件,毫秒级延迟(实际上就是没有延迟)
- 与众多常用存储系统的连接(ES,HBase,MySQL,Redis⋯)
- 高可用(zookeeper),动态扩展,实现7*24 小时全天候运行
Flink vs Spark Streaming区别
数据模型
- Spark 采用’RDD’模型,Spark Streaming 的DStream 实际上是一组组小批数据RDD的集合
- Flink ‘基本数据模型’是数据流,以及事件(Event)序列(Integer. String. Long. POJO Class)
运行时架构
- Spark 是’批计算’,将DAG 划分为不同的Stage,一个Stage完成后才可以计算下一个Stage
- Flink 是’流计算’,一个事件在一个节点处理完后可以直接发往下一个节点进行处理
Flink 应用场景
- 电商和市场营销 # 数据报表. 广告投放. 业务流程需要
- 物联网(IOT)# 传感器实时数据采集和显示. 实时报警,交通运输业(自动驾驶)
- 电信业 # 基站流量调配
- 银行和金融业 # 实时结算和通知推送,实时检测异常行为(信用卡盗卡)
数据架构演变
事务处理 OLTP
- 分析处理 OLAP : 将数据从业务数据库复制到数仓,再进行分析和查询
-
Lambda Architecture : 用两套系统,同时保证低延迟和结果准确
-
有状态的流式处理流程
- 本质 : 事件驱动(Event-driven)
- 基于流的世界观 : 一切都是由流组成的,离线数据是有界的流;实时数据是一个没有界限的流:这就是所谓的有界流和无界流
- Flink 分层API
- 有状态 与 无状态
运行架构
Flink 运行时的组件
- 作业管理器 JobManager
- 资源管理器 ResourceManager
- 任务管理器 TaskManager
- 分发器 Dispatcher
数据流
- Source # 负责读取数据源
- Transformation # 利用各种算子进行处理加工
- Sink # 负责输出
网络IO通信底层
- erlang
- akka
- netty
典型的Master-Slave 架构
任务提交流程
任务调度原理
任务管理器和插槽
并行度 Parallelism
并行子任务分配
数据流
任务链
DataSteam API
- 流处理 API
Flink中的算子是将’一个或多个DataStream’转换为’新的DataStream’,可以将多个转换组合成复杂的数据流拓扑。
- 源算子 Source # 数据读取,从集合. 文件. kafka. 自定义…
- 转换算子 Transformation
- 输出算子 Sink # 数据输出,写入文件. kafka. redis. Elasticsearch. JDBC…
转换算子 Transformation
-
map # 理解为映射,对每个元素进行一定的变换后,映射为另一个元素。
-
flatmap # 理解为将元素摊平,每个元素可以变为0个. 1个. 或者多个元素。
-
filter # 进行筛选。
-
keyBy # 将Stream根据指定的Key进行分区,是根据key的散列值进行分区的。
-
滚动聚合算子( Rolling Aggregation ) : sum() min() max() minBy() maxBy()
-
reduce # 归并操作,它可以将KeyedStream 转变为 DataStream。
-
split 和 select # 将一个流拆分为多个流
-
connect 和 CoMap # 将两个流纵向地连接起来,数据类型可不同
-
union # 多个流合并到一个流中,以便对合并的流进行统一处理。是对多个流的水平拼接。参与合并的流必须是同一种类型。
-
fold # 给定一个初始值,将各个元素逐个归并计算。它将KeyedStream转变为DataStream。
-
join # 指定的Key将两个流进行关联。
map 和 flatMap 区别:
map:map方法返回的是一个object,map将流中的当前元素替换为此返回值;
flatMap:flatMap方法返回的是一个stream,flatMap将流中的当前元素替换为此返回流拆解的流元素;
例子 : 有二箱鸡蛋,每箱5个,现在要把鸡蛋加工成煎蛋,然后分给学生。
map做的事情:把二箱鸡蛋分别加工成煎蛋,还是放成原来的两箱,分给2组学生;
flatMap做的事情:把二箱鸡蛋分别加工成煎蛋,然后放到一起【10个煎蛋】,分给10个学生
基础数据类型
-
支持所有的 Java 和 Scala 基础数据类型, Int, Double, Long, String, …
-
Java 和 Scala 元组( Tuples )
-
Scala样例类( case classes )
-
Java简单对象( POJOs )
-
其它( Arrays, Lists, Maps , Enums, 等等)
实现 UDF 函数 更细粒度的控制流
-
函数类( Function Classes )
-
匿名函数( Lambda Functions )
-
富函数( Rich Functions ) # 可以获取运行环境的上下文,并拥有一些生命周期方法,所以可以实现更复杂的功能。
-
open()
-
getRuntimeContext().getState();
-
close()
Flink RichFunction & state
class flatMap_rich extends RichFlatMapFunction<In,Out>{
override def open(configuration:Confuration) : kic Unit = {}
//创建初始话函数,例如创建和外部系统的连接
override def flatMap(in : In,out:Collector<Out>)() :Unit = {}
//做一些操作
override def close : Unit = {}
//做一些清理工作,例如关闭和外部系统的连接
}
- DataStream
Window API
窗口(Window): [ ) 左闭右开
: 将无限流切割为有限流的一种方式,它会将流数据分发到有限大小的桶(bucket)中进行分析
窗口分类
-
滚动窗口 Tumbling Windows
- 将数据依据固定的窗口长度对数据进行切分
- 时间对齐,窗口长度固定,没有重叠
-
滑动窗口 Sliding Windows
- 滑动窗口是固定窗口的更广义的一种形式,滑动窗口由固定的窗口长度和滑动间隔组成
- 窗口长度固定,可以有重叠
-
会话窗口 Session Windows
- 由一系列事件组合一个指定时间长度的timeout 间隙组成,也就是一段时间没有接收到新数据就会生成新的窗口
- 时间无对齐
- 只有Flink 支持会话窗口
- 有界的流 ⇒ 窗口
Wartermark
在Flink中,水位线(watermark)是一种’衡量Event Time进展’的机制,用来’处理实时数据中的乱序’问题的,通常是’水位线’和’窗口’结合使用来实现
- 水位线是一种逻辑时钟
- 水位线由程序员编程插入到数据流中
- 水位线是一种特殊的事件
- 在事件时间的世界里,水位线就是时间
- 水位线 = 观察到的最大时间戳 - 最大延迟时间 - 1 毫秒
- 水位线超过窗口结束时间,窗口闭合,默认情况下,迟到元素被抛弃
- Flink 会在流的最开始插入一个时间戳为负无穷大的水位线
- Flink 会在流的最末尾插入一个时间戳为正无穷大的水位线
- Event Time(事件时间):事件创建的时间(必须包含在数据源中的元素里面)
- Ingestion Time(摄入时间):数据进入Flink 的source 算子的时间,与机器相关
- Processing Time(处理时间):执行操作算子的本地系统时间,与机器相关
迟到数据处理的原因 : 由于网络. 分布式等原因,会导致乱序数据的产生
1. 直接抛弃迟到的元素
2. 将迟到的元素发送到另一条流中去
3. 可以更新窗口已经计算完的结果,并发出计算结果
状态管理
Flink 中的状态 # 类似本地变量
- 算子状态 Operatior State # 算子状态的作用范围限定为算子任务
- 列表状态 List state
- 联合列表状态 Union list state
- 广播状态 Broadcast state
- 键控状态 Keyed State # 根据输入数据流中定义的键( key )来维护和 访问
- 值状态(ValueState):将状态表示为单个的值
- 列表状态(List State):将状态表示为一组数据的列表
- 字典状态(MapState):将状态表示为一组Key-Value 对
- 聚合状态:将状态表示为一个用于聚合操作的列表
- 状态后端 State Backends # 状态的存储 . 访问以及维护
容错机制
- Flink 故障恢复机制的核心 : 应用状态的一致性检查点
- 应用状态的一致性检查点 : 所有任务的状态,在某个时间点的一份的快照 ( 时间点 : 是所有任务都恰好处理完一个相同的输入数据的时候)
- 从检查点恢复状态
- 重启应用
- 从 checkpoint 中读取状态,将状态重置
- 开始消费并处理检查点到发生故障之间的所有数据 # 精确一次
状态一致性
状态一致性分类
- AT-MOST-ONCE(最多一次) - 当任务故障时,最简单的做法是什么都不干,既不恢复丢失的状态,也不重播丢失的数据。At-most-once 语义的含义是最多处理一次事件。例如:UDP,不提供任何一致性保障
- AT-LEAST-ONCE(至少一次) - 在大多数的真实应用场景,我们希望不丢失事件。这种类型的保障称为at-least-once,意思是所有的事件都得到了处理,而一些事件还可能被处理多次。
- EXACTLY-ONCE(精确一次) - 恰好处理一次是最严格的保证,也是最难实现的。恰好处理一次语义不仅仅意味着没有事件丢失,还意味着针对每一个数据,内部状态仅仅更新一次。
端到端 exactly once 1. 内部保证——checkpoint(分布式异步快照算法) 2. Source 端——可重设数据的读取位置(Kafka,FileSystem) 3. Sink 端——从故障恢复时,数据不会重复写入外部系统 幂等写入 事务写入
- 幂等写入 : 是说一个操作,可以重复执行很多次,但只导致一次结果更改,也就是说,后面再重复执行就不起作用了
- 事务写入 : 应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消(ACID);具有原子性:一个事务中的一系列的操作要么全部成功,要么一个都不做 实现: 1. 预写日志 2. 两阶段提交