flink是标准的实时处理引擎,而且Spark的两个模块Spark Streaming和Structured Streaming都是基于微批处理的,不过现在Spark Streaming已经非常稳定基本都没有更新了,然后重点移到spark sql和structured Streaming了。
Flink作为一个很好用的实时处理框架,也支持批处理,不仅提供了API的形式,也可以写sql文本。这篇文章主要是帮着大家对于Structured Streaming和flink的主要不同点。文章建议收藏后阅读。
1. 运行模型
Structured Streaming 的task运行也是依赖driver 和 executor,当然driver和excutor也还依赖于集群管理器Standalone或者yarn等。可以用下面一张图概括:
Flink的Task依赖jobmanager和taskmanager。官方给了详细的运行架构图,可以参考:
Structured Streaming 周期性或者连续不断的生成微小dataset,然后交由Spark SQL的增量引擎执行,跟Spark Sql的原有引擎相比,增加了增量处理的功能,增量就是为了状态和流表功能实现。由于是也是微批处理,底层执行也是依赖Spark SQL的。
Flink 中的执行图可以分成四层:StreamGraph-> JobGraph -> ExecutionGraph -> 物理执行图。细分:
StreamGraph: 是根据用户通过 Stream API 编写的代码生成的最初的图。用来表示程序的拓扑结构。
JobGraph: StreamGraph经过优化后生成了JobGraph,提交给 JobManager 的数据结构。主要的优化为,将多个符合条件的节点 chain 在一起作为一个节点,这样可以减少数据在节点之间流动所需要的序列化/反序列化/传输消耗。这个可以用来构建自己的自己的集群任务管理框架。
ExecutionGraph: JobManager 根据 JobGraph 生成的分布式执行图,是调度层最核心的数据结构。
物理执行图: JobManager 根据ExecutionGraph 对 Job 进行调度后,在各个TaskManager 上部署 Task 后形成的“图”,并不是一个具体的数据结构。
2. 编程风格
两者的编程模型基本一致吧,都是链式调用。
3. 时间概念
三种处理时间:事件时间,注入时间,处理时间。
Flink支持三种时间,同时flink支持基于事件驱动的处理模型,同时在聚合等算子存在的时候,支持状态超时自动删除操作,以避免7*24小时流程序计算状态越来越大导致oom,使得程序挂掉。
Structured Streaming仅支持事件时间,处理时间。
对于基于事件时间的处理flink和Structured Streaming都是支持watemark机制,窗口操作基于watermark和事件时间可以对滞后事件做相应的处理,虽然听起来这是个好事,但是整体来说watermark就是鸡肋,它会导致结果数据输出滞后,比如watermark是一个小时,窗口一个小时,那么数据输出实际上会延迟两个小时,这个时候需要进行一些处理。
4. 维表实现及异步io
Structured Streaming不直接支持与维表的join操作,但是可以使用map、flatmap及udf等来实现该功能,所有的这些都是同步算子,不支持异步IO操作。但是Structured Streaming直接与静态数据集的join,可以也可以帮助实现维表的join功能,当然维表要不可变。
Flink也不支持与维表进行join操作,除了map,flatmap这些算子之外,flink还有异步IO算子,可以用来实现维表,提升性能。关于flink的异步IO可以参考浪尖以前的文章:
5. 状态管理
状态维护应该是流处理非常核心的概念了,比如join,分组,聚合等操作都需要维护历史状态,那么flink在这方面很好,structured Streaming也是可以,但是spark Streaming就比较弱了,只有个别状态维护算子upstatebykye等,大部分状态需要用户自己维护,虽然这个对用户来说有更大的可操作性和可以更精细控制但是带来了编程的麻烦。flink和Structured Streaming都支持自己完成了join及聚合的状态维护。
Structured Streaming有高级的算子,用户可以完成自定义的mapGroupsWithState和flatMapGroupsWithState,可以理解类似Spark Streaming 的upstatebykey等状态算子。
就拿mapGroupsWithState为例:
由于Flink与Struct