赞
踩
Flink项目的理念是:Apache Flink是为分布式、高性能、随时可用以及准确的流处理应用程序打造的开源流处理框架。
Apache Flink是一个框架和分布式处理引擎,用于对无界和有界数据流进行有状态计算。Flink被设计在所有常见的集群环境中运行,以内存执行速度和任意规模来执行计算。
Flink能够提供毫秒级别的延迟,同时保证了数据处理的低延迟、高吞吐和结果的正确性,还提供了丰富的时间类型和窗口计算、Exactly-once(就一次)语义支持,另外还可以进行状态管理,并提供了 CEP(复杂事件处理)的支持。
Storm | Flink | |
---|---|---|
状态管理 | 无状态,需用户自行进行状态管理 | 有状态 |
窗口支持 | 对事件窗口支持较弱,缓存整个窗口的所有数据,窗口结束时一起计算 | 窗口支持较为完善,自带一些窗口聚合方法,并且会自动管理窗口状态 |
消息投递 | At Most Once/At Least Once | At Most Once/At Least Once/Exactly Once |
容错方式 | ACK机制:对每个消息进行全链路跟踪,失败或超时进行重发 | 检查点机制:通过分布式一致性快照机制,对数据流和算子状态进行保存;在发生错误时,使系统能够进行回滚 |
应用现状 | 在美团点评实时计算业务中已有较为成熟的运用,有管理平台、常用API和相应的文档,大量实时作业基于Storm构建 | 在美团点评实时计算业务中已有一定应用,但是管理平台、API及文档等仍需进一步完善 |
这个问题是一个非常宏观的问题,因为两个框架的不同点非常之多,但是在面试时有非常重要的一点一定要回答出来:Flink是标准的实时处理引擎,基于事件驱动;SparkStreaming是微批(Micro-Batch)的模型。
SparkStreaming | Flink | |
---|---|---|
架构模型 | 主要角色包括:Master、Worker、Driver和Executor | 主要包括:JobManager、TaskManager和Slot |
任务调度 | 连续不间断的生成微小的数据批次,构建有向无环图DAG,会依次创建DStreamGraph、JobGenerator、JobScheduler | 根据用户提交的代码生成StreamGraph,经过优化生成JobGraph,然后提交给JobManager进行处理,JobManager会根据JobGraph生成ExecutionGraph,ExecutionGraph是Flink调度最核心的数据结构,JobManager根据ExecutionGraph对Job进行调度 |
时间机制 | 只支持处理时间 | 支持处理时间、事件时间、注入时间;同时也支持watermark机制来处理滞后数据 |
容错机制 | 可以设置checkpoint,假如发生故障并重启,可以从上次checkpoint之处恢复,但是这个行为只能使得数据不丢失,可能会重复处理,不能做到恰好一次处理语义 | 使用两阶段提交(2PC)协议来解决可能重复处理问题,做到恰好一次处理语义 |
时间驱动型(Event-driven)
时间驱动型应用是一类具有状态的应用,它从一个或多个事件流提取数据,并根据到来的时间触发计算、状态更新或其他外部动作
流与批的世界观
分层API
Flink提供的最高层级的抽象是SQL
越顶层越抽象,表达含义越明显,使用越方便
越底层越具体,表达能力越丰富,使用越灵活
无界数据流
无界数据流有一个开始但是没有结束,它们不会在生成时终止并提供数据,必须连续处理无界流,也就是说必须再获取后立即处理event;
对于无界数据流是无法等待所有数据都到达,因为输入是无界的,并且再任何时间点都不会完成;
处理无界数据通常要求以特定顺序(例如事件发生的顺序)获取event,以便能够推断结果完整性。
有界数据流
有界数据流有明确定义的开始和结束,可以在执行任何计算之前通过获取所有数据来处理有界流;
处理有界流不需要有序获取,因为可以始终对有界数据集进行排序,有界流的处理也称为批处理。
这种以流为世界观的架构,获得的最大好处就是具有极低的延迟。
作业管理器(JobManager)
任务管理器(TaskManager)
资源管理器(ResourceManager)
分发器(Dispatcher)
插槽的数量限制了TaskManager能够执行的任务数量
TaskManager插槽是Flink中定义的处理资源单元
Flink的各个组件的交互协作
如果部署的集群环境不同(如YARN、Mesos、K8s以及Standalone等),其中一些步骤可以被省略,或是有些组件会运行在同一个JVM进程中
Flink集群部署到YARN上
所有的Flink程序都是由三部分组成的:Source、Transformation和Sink
Source:负责读取数据源
Transformation:利用各种算子进行处理加工
Sink:负责输出
Flink中的执行图可以分成四层:
StreamGraph:根据用户通过Stream API编写的代码生成的最初的图;用来表示程序的拓扑结构
JobGraph:StreamGraph经过优化后生成了JobGraph,提交给JobManager的数据结构;主要的优化为,将多个符合条件的节点链接在一起,这样可以减少数据在节点之间流动所需要的序列化/反序列化/传输消耗
ExecutionGraph:JobManager根据JobGraph生成ExecutionGraph;ExecutionGraph是JobGraph的并行化版本,是调度层最核心的数据结构
物理执行图:JobManager根据ExecutionGraph对Job进行调度后,在各个TaskManager上部署Task后形成的“图”,并不是一个具体的数据结构
One-to-one:类似于Spark中的窄依赖
stream(比如在source和map operator之间)维护着分区以及元素的顺序,那意味着map算子的子任务看到的元素的个数以及顺序跟source算子的子任务生产的元素的个数、顺序相同,map、fliter、flatMap等算子都是one-to-one的对应关系
Redistributing:类似于Spark中的宽依赖
stream(map()跟keyBy/window之间或者keyBy/window跟sink之间)的分区会发生改变;每一个算子的子任务依据所选择的transformation发送数据到不同的目标任务。例如,keyBy()基于hashCode重分区、broadcast和rebalance会随机重新分区,这些算子都会引起redistribute过程,而redistribute过程就类似于Spark中的shuffle过程
Flink采用了一种称为任务链的优化技术,可以在特定条件下减少本地通信的开销;为了满足任务链的要求,必须将两个或多个算子设为相同的并行度,并通过本地转发(local forward)的方式进行连接
相同并行度的one-to-one操作,Flink这样相连的算子连接在一起形成一个task,原来的算子成为u里面的subtask
并行度相同、并且是one-to-one操作,两个条件缺一不可
DataStream → SplitStream:根据某些特征把一个DataStream拆分成两个或者多个DataStream
SplitStream →DataStream:从一个SplitStream中获取一个或者多个DataStream
“富函数”是DataStream API提供的一个函数类的接口,所有Flink函数类都有其Rich版本
它与常规函数的不同在于,可以获取运行环境的上下文,并拥有一些生命周期方法,所以可以实现更复杂的功能
Rich Functions
有一个生命周期的概念,典型的生命周期方法有:
CountWindow
:按照指定的数据条数生成一个Window,与时间无关TimeWindow
:按照时间生成WindowGlobal Window
:全局窗口滚动窗口(Tumbling Windows
):将数据依据固定的窗口长度对数据进行切片
特点:时间对齐,窗口长度固定,没有重叠
适用场景:适合做 BI 统计等(做每个时间段的聚合计算)
滑动窗口(Sliding Windows
):是固定窗口的更广义的一种形式,滑动窗口由固定的窗口长度和滑动间隔组成
特点:时间对齐,窗口长度固定,可以有重叠
适用场景:对最近一个时间段内的统计
会话窗口(Session Windows
):由一系列事件组合一个指定时间长度的timeout间隙组成,类似于web应用session,也就是一段时间没有接收到新数据就会生成新的窗口
特点:时间无对齐
增量聚合函数(incremental aggregation functions)
每条数据到来就进行计算,保持一个简单的状态
典型的增量聚合函数有ReduceFunction,AggregateFunction
全窗口函数(full window functions)
先把窗口所有数据收集起来,等到计算的时候会遍历所有数据
ProcessWindowFunction就是一个全窗口函数
Context和OnTimerContext所持有的TimerService对象拥有以下方法:
当定时器timer触发时,会执行回调函数onTimer();注意定时器timer只能在keyed streams上面使用
列表状态(List state)
将状态表示为一组数据的列表
联合列表状态(Union list state)
也将状态表示为数据的列表;它与常规列表状态的区别在于,在发生故障时,或者从保存点(savepoint)启动应用程序时如何恢复
广播状态(Broadcast state)
如果一个算子有多项任务,而它的每项任务状态又都相同,那么这种特殊情况最适合应用广播状态
at-most-once
这其实是没有正确性保障的委婉说法,故障发生之后,计数结果可能丢失
at-least-once
这表示计数结果可能大于正确值,但绝对不会小于正确值;也就是说,计数程序在发生故障后可能多算,但是绝不会少算
exactly-once
这指的是系统保证在发生故障后得到的计数结果与正确值一致
目前我们看到的一致性保证都是由流处理器实现的,也就是说都是在 Flink 流处理器内部保证的;而在真实应用中,流处理应用除了流处理器以外还包含了数据源(例如Kafka)和输出到持久化系统
端到端的一致性保证,意味着结果的正确性贯穿了整个流处理应用的始终;每一个组件都保证了它自己的一致性,整个端到端的一致性级别取决于所有组件中一致性最弱的组件
内部保证:依赖checkpoint
source端:需要外部源可重设数据的读取位置
sink端:需要保证从故障恢复时,数据不会重复写入外部系统
幂等写入
所谓幂等操作,是说一个操作,可以重复执行很多次,但只导致一次结果更改,也就是说,后面再重复执行就不起作用了
事务写入
需要构建事务来写入外部系统,构建的事务对应着checkpoint,等到checkpoint真正完成的时候,才把所有对应的结果写入sink系统中
预写日志(WAL)
两阶段提交(2PC)
每传入一条数据,有状态的算子任务都会读取和更新状态
由于有效的状态访问对于处理数据的低延迟至关重要,因此每个并行任务都会在本地维护其状态,以确保快速的状态访问
状态的存储、访问以及维护,由一个可插入的组件决定,这个组件就叫做状态后端(state backend)
MemoryStateBackend
FsStateBackend
RocksDBStateBackend
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。