本文从编程模型、任务调度、时間机制、Kafka 动态分区的感知、容错及处理语义、背压等几个方面对比 flink和spark对比 Stream 与 Flink希望对有实时处理需求业务的企业端用户在框架选型有所启發。本文篇幅较长建议先收藏~
- Master:主要负责整体集群资源的管理和应用程序调度;
- Executor:负责执行 task,反馈执行状态和执行结果
flink和spark对比 Streaming 是微批处悝,运行的时候需要指定批处理的时间每次运行 job 时处理一个批次的数据,流程如图 3 所示:
Flink 是基于事件驱动的事件可以理解为消息。事件驱动的应用程序是一种状态应用程序它会从一个或者多个流中注入事件,通过触发计算更新状态或外部动作对注入的事件作出反应。
编程模型对比主要是对比 flink 和 flink和spark对比 Streaming 两者在代码编写上的区别。
以上两种模型编程机构近似只是在 api 和内部数据获取有些区别,新版本嘚已经取消了基于 receiver 这种模式企业中通常采用基于 direct Dstream 的模式。
通过以上代码我们可以 get 到:
接下来看 flink 与 kafka 结合是如何编写代码的Flink 与 kafka 结合是事件驅动,大家可能对此会有疑问消费 kafka 的数据调用 poll 的时候是批量获取数据的(可以设置批处理大小和超时时间),这就不能叫做事件触发了而實际上,flink 内部对 poll 出来的数据进行了整理然后逐条 emit,形成了事件触发的机制 下面的代码是
flink和spark对比 Streaming 任务如上文提到的是基于微批处理的,實际上每个批次都是一个 flink和spark对比 Core 的任务对于编码完成的 flink和spark对比 Core 任务在生成到最终执行结束主要包括以下几个部分:
假设有两个 executor,其中每個 executor 三个核那么每个批次相应的 task 运行位置是固定的吗?是否能预测 由于数据本地性和调度不确定性,每个批次对应 kafka 分区生成的 task 运行位置並不是固定的
可以看出 flink 的拓扑生成提交执行之后,除非故障否则拓扑部件执行位置不变,并行度由每一个算子并行度决定类似于 storm。洏 flink和spark对比 Streaming 是每个批次都会根据数据本地性和资源情况进行调度无固定的执行拓扑结构。 flink 是数据在拓扑结构里流动执行而 flink和spark对比 Streaming 则是对數据缓存批次并行处理。
流处理程序在时间概念上总共有三个时间概念:
处理时间是指每台机器的系统时间当流程序采用处理时间时将使用运行各个运算符实例的机器时间。处理时间是最简单的时间概念不需要流和机器之间的协调,它能提供最好的性能和最低延迟然洏在分布式和异步环境中,处理时间不能提供消息事件的时序性保证因为它受到消息传输延迟,消息在算子之间流动的速度等方面制约
事件时间是指事件在其设备上发生的时间,这个时间在事件进入 flink 之前已经嵌入事件然后 flink 可以提取该时间。基于事件时间进行处理的流程序可以保证事件在处理的时候的顺序性但是基于事件时间的应用程序必须要结合 watermark 机制。基于事件时间的处理往往有一定的滞后性因為它需要等待后续事件和处理无序事件,对于时间敏感的应用使用的时候要慎重考虑
注入时间是事件注入到 flink 的时间。事件在 source 算子处获取 source 嘚当前时间作为事件注入时间后续的基于时间的处理算子会使用该时间处理数据。
相比于事件时间注入时间不能够处理无序事件或者滯后事件,但是应用程序无序指定如何生成 watermark在内部注入时间程序的处理和事件时间类似,但是时间戳分配和 watermark 生成都是自动的
图 8 可以清晰地看出三种时间的区别:
flink 支持三种时间机制:事件时间,注入时间处理时间,同时支持 watermark 机制处理滞后数据
对于有实时处理业务需求嘚企业,随着业务增长数据量也会同步增长将导致原有的 kafka 分区数不满足数据写入所需的并发度,需要扩展 kafka 的分区或者增加 kafka 的 topic这时就要求实时处理程序,如 flink和spark对比Streaming、flink 能检测到 kafka 新增的 topic 、分区及消费新增分区的数据
其中确认的是 flink和spark对比 Streaming 与 kafka 0.8 版本结合不支持动态分区检测,与 0.10 版夲结合支持接着通过源码分析。
*源码分析只针对分区检测
// 改行代码会计算这个job要消费的每个kafka分区的最大偏移
// 可以看到的是用来指定获取最大偏移分区的列表还是只有currentOffsets,没有发现关于新增的分区的内容
// 获取当前生成job,要用到的KafkaRDD每个分区最大消费偏移值
// 做差获取新增的分區信息
接是创建了一个线程该线程会定期检测 kafka 新增分区,然后将其添加到 kafkaFetcher 里
/ 容错机制及处理语义 /
本节内容主要是想对比两者在故障恢複及如何保证仅一次的处理语义。这个时候适合抛出一个问题:实时处理的时候如何保证数据仅一次处理语义?
对于 flink和spark对比 Streaming 任务我们鈳以设置 checkpoint,然后假如发生故障并重启我们可以从上次 checkpoint 之处恢复,但是这个行为只能使得数据不丢失可能会重复处理,不能做到恰一次處理语义
之前会导致数据多次处理,这个时候我们需要保证处理结果多次输出不影响正常的业务
由此可以分析,假设要保证数据恰一佽处理语义那么结果输出和 offset 提交必须在一个事务内完成。在这里有以下两种做法:
也就是结果数据包含 offset这样提交结果和提交 offset 就是一个操作完成,不会数据丢失也不会重复处理。故障恢复的时候可以利用上次提交结果带的 offset
若要 sink 支持仅一次语义,必须以事务的方式写数據到 Kafka这样当提交事务时两次 checkpoint 间的所有写入操作作为一个事务被提交。这确保了出现故障或崩溃时这些写入操作能够被回滚
在一个分布式且含有多个并发执行 sink 的应用中,仅仅执行单次提交或回滚是不够的因为所有组件都必须对这些提交或回滚达成共识,这样才能保证得箌一致性的结果Flink 使用两阶段提交协议以及预提交(pre-commit)阶段来解决这个问题。
本例中的 Flink 应用如图 11 所示包含以下组件:
- 一个时间窗口化的聚会操莋
下面详细讲解 flink 的两段提交思路:
当一个进程仅有它的内部状态的时候除了在 checkpoint 之前将需要将数据更改写入到 state backend,不需要在预提交阶段做其怹的动作在 checkpoint 成功的时候,Flink 会正确的提交这些写入在 checkpoint 失败的时候会终止提交,过程可见图 13
当结合外部系统的时候,外部系统必须要支歭可与两阶段提交协议捆绑使用的事务显然本例中的 sink 由于引入了 kafka sink,因此在预提交阶段 data sink 必须预提交外部事务如下图:
当 barrier 在所有的算子中傳递一遍,并且触发的快照写入完成预提交阶段完成。所有的触发状态快照都被视为 checkpoint 的一部分也可以说 checkpoint 是整个应用程序的状态快照,包括预提交外部状态出现故障可以从 checkpoint 恢复。下一步就是通知所有的操作算子 checkpoint 成功该阶段
本例中 data source 和窗口操作无外部状态,因此该阶段這两个算子无需执行任何逻辑,但是 data sink 是有外部状态的因此,此时我们必须提交外部事务如下图:
以上就是 flink 实现恰一次处理的基本逻辑。
消费者消费的速度低于生产者生产的速度为了使应用正常,消费者会反馈给生产者来调节生产者生产的速度以使得消费者需要多少,生产者生产多少
flink和spark对比 Streaming 跟 kafka 结合是存在背压机制的,目标是根据当前 job 的处理情况来调节后续批次的获取 kafka 消息的条数为了达到这个目的,flink和spark对比 Streaming 在原有的架构上加入了一个 RateController利用的算法是 PID,需要的反馈数据是任务处理的结束时间、调度时间、处理时间、消息条数这些数據是通过 flink和spark对比Listener 体系获得,然后通过 PIDRateEsimator 的 compute 计算得到一个速率进而可以计算得到一个 offset,然后跟限速设置最大消费条数比较得到一个最终要消費的消息最大 offset
阻塞占比在 web 上划分了三个等级:
美图的大数据团队在近几年的发展中,逐步演进和发展出美图的大数据体系以及在美图業务场景下数据技术应用的最佳实践。8月11日我们将在深圳开设一场技术沙龙我们邀请了来自美图公司的大数据负责人、架构师、魅族公司的数据技术专家、以及来自 Apache kylin 的 PMC。美图的大数据技术负责人和架构师会为大家分享美图在大数据技术上的探索、大数据的架构、以及数据技术的应用落地魅族的数据技术专家会为大家介绍魅族的 DMP 系统的架构设计以及系统的演进历程。来自 Apache 顶级项目 kylin 的架构师会为大家分享 kylin 的技术原理与应用实践四位技术专家会从多个角度不同层次,为大家分享各自在大数据技术上的实践经验