专栏名称: About云
about云-为热爱云开发技术人员提供最全面的信息传播和服务平台
目录
相关文章推荐
51好读  ›  专栏  ›  About云

Structured Streaming与Flink比较

About云  · 公众号  ·  · 2019-01-10 20:12

正文

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可以参考浪尖以前的文章:

Flink异步IO第一讲

5. 状态管理

状态维护应该是流处理非常核心的概念了,比如join,分组,聚合等操作都需要维护历史状态,那么flink在这方面很好,structured Streaming也是可以,但是spark Streaming就比较弱了,只有个别状态维护算子upstatebykye等,大部分状态需要用户自己维护,虽然这个对用户来说有更大的可操作性和可以更精细控制但是带来了编程的麻烦。flink和Structured Streaming都支持自己完成了join及聚合的状态维护。

Structured Streaming有高级的算子,用户可以完成自定义的mapGroupsWithState和flatMapGroupsWithState,可以理解类似Spark Streaming 的upstatebykey等状态算子。

就拿mapGroupsWithState为例:

由于Flink与Structured Streaming的架构的不同,task是常驻运行的,flink不需要状态算子,只需要状态类型的数据结构。

首先看一下Keyed State下,我们可以用哪些原子状态:

ValueState :即类型为T的单值状态。这个状态与对应的key绑定,是最简单的状态了。它可以通过update方法更新状态值,通过value()方法获取状态值。

ListState :即key上的状态值为一个列表。可以通过add方法往列表中附加值;也可以通过get()方法返回一个Iterable 来遍历状态值。

ReducingState :这种状态通过用户传入的reduceFunction,每次调用add方法添加值的时候,会调用reduceFunction,最后合并到一个单一的状态值。

FoldingState :跟ReducingState有点类似,不过它的状态值类型可以与add方法中传入的元素类型不同(这种状态将会在Flink未来版本中被删除)。

MapState :即状态值为一个map。用户通过put或putAll方法添加元素。

6. join操作

flink的join操作没有大的限制,支持种类丰富,比:

Inner Equi-join

SELECT




    
 * FROM Orders INNER JOIN Product ONOrders.productId = Product.id

Outer Equi-join

SELECT *

FROM Orders LEFT JOIN Product ON Orders.productId =Product.id

SELECT *

FROM Orders RIGHT JOIN Product ON Orders.productId =Product.id

SELECT *

FROM Orders FULL OUTER JOIN Product ONOrders.productId = Product.id

Time-windowed Join

SELECT * FROM Oderso,Shipmentss WHEREo.id=s.orderIdAND o.ordertimeBETWEENs.shiptime INTERVAL'4'HOURANDs.shiptime

Expanding arrays into a relation

SELECT users, tag
FROM Orders CROSS JOIN UNNEST(tags) AS t (tag)

Join with Table Function

Inner Join

A row of the left (outer) table is dropped, if its table function call returns an empty result.

SELECT users, tag
FROM Orders, LATERAL TABLE(unnest_udtf(tags)) t AS tag

Left
 Outer Join
If a table function call returns an empty result, the corresponding outer row is preserved and the result padded with null values.

SELECT users, tag
FROM Orders LEFT JOIN LATERAL TABLE(unnest_udtf(tags)) t AS tag ON TRUE

Join with Temporal Table

SELECT






请到「今天看啥」查看全文