Flink VS Spark Streaming
数据处理模式
Apache Flink是一个用于分布式流和批处理数据处理的开源平台。Flink的核心是流数据引擎,为数据流上的分布式计算提供数据分发,通信和容错,可对有限数据流和无限数据流进行有状态计算。Flink在流引擎之上构建批处理,覆盖本机迭代支持,托管内存和程序优化。
Spark Streaming是Spark的一大应用方向,它基于Spark高效的批处理能力,对流数据划分为多个小批数据,再分别对这些数据进行处理,即微批处理模式,运行的时候需要指定批处理的时间,每次运行job时处理一个批次的数据。
- Flink的计算模型抽象是有状态的流,即源源不断没有边界的数据,并且数据的状态可以改变,对于批处理则认为是有边界的流进行处理
- Spark的计算模型抽象是批,所有数据的表示本质上都是RDD抽象,对于流处理的支持,则是基于时间将流划分为多个批次,依次进行处理
两种模式的对比
item | Micro-batching | Distributed snapshots |
---|---|---|
典型代表 | Apache Spark Streaming | Apache Flink |
语义保证 | Exactly once | Exactly once |
延迟 | 高 | 低 |
吞吐 | 高 | 高 |
计算模型 | 微批 | 流 |
容错开销 | 低 | 低 |
流控 | 较差 | 好 |
业务灵活性 (业务和容错分离) | 紧耦合 | 分离 |
原理 | 连续的数据流不要切分到 record 级别,而是收敛切分为一批一批微批的、原子的数据进行类似 Batch 的计算。每个 batch 的数据可能会成功或者失败处 理,我们就对当前失败的 这一小批数据进行处理即 可 | 确定当前流式计算的状态 (包括正在处理的数据,以及 Operator 状态),生成该状态 的一致快照,并存储在持久存储中 |
运行时结构
Spark Streaming 运行时的角色(standalone 模式)主要有:
- Master:主要负责整体集群资源的管理和应用程序调度;
- Worker:负责单个节点的资源管理,driver 和 executor 的启动等;
- Driver:用户入口程序执行的地方,即 SparkContext 执行的地方,主要是 DAG 生成、stage 划分、task 生成及调度;
- Executor:负责执行 task,反馈执行状态和执行结果。
Flink 运行时的角色(standalone 模式)主要有:
- JobManager: 协调分布式执行,他们调度任务、协调 checkpoints、协调故障恢复等。至少有一JobManager,高可用情况下可以启动多个 JobManager,其中一个选举为 leader,其余为 standby;
- TaskManager: 负责执行具体的 tasks、缓存、交换数据流,至少有一个 TaskManager;
- Client:程序的提交者,用于准备,生成并优化DataFlow,然后发送给JobManager
- Slot: 每个 task slot 代表 TaskManager 的一个固定部分资源,Slot 的个数代表着 taskmanager 可并行执行的 task 数。
部署环境支持
部署环境 | Spark | Flink |
---|---|---|
Local(Single JVM) | ✔️ | ✔️ |
Standalone Cluster | ✔️ | ✔️ |
Yarn | ✔️ | ✔️ |
Mesos | ✔️ | ✔️ |
Kubernetes | ✔️ | ✔️ |
编程模型
Flink编程模型
- 最底层的抽象提供了对有状态流的支持,用户可以自由的处理和管理事件状态,并基于此开发新的算子
- 实际上,大多数应用并不需要上述的底层抽象,而是针对 核心API(Core APIs) 进行编程,比如DataStream API(有界或无界流数据)以及DataSet API(有界数据集)。这些API为数据处理提供了通用的构建模块,比如由用户定义的多种形式的转换(transformations),连接(joins),聚合(aggregations),窗口操作(windows),状态(state)等等。
- Table API是以表为中心的声明式DSL,Table API遵循(扩展的)关系模型:表有二维数据结构(schema)(类似于关系数据库中的表),同时API提供可比较的操作,例如select、project、join、group-by、aggregate等
- Flink提供的最高层级的抽象是 SQL 。这一层抽象在语法与表达能力上与Table API类似,但是是以SQL查询表达式的形式表现程序。SQL抽象与Table API交互密切,同时SQL查询可以直接在Table API定义的表上执行。
Spark Streaming编程模型
Spark Streaming编程模型是DStream(Discretized Streams),离散化数据流,其本质是对一批RDD的抽象。然后对每一批的RDD进行处理,使用spark core API。
Flink的编程模型更适用于流式计算场景,并且未来将会向流处理和基于流的批处理进行统一。而Spark Streaming的编程模型依赖于底层Spark自身的处理特性,针对RDD进行批处理。
API
API | Spark | Flink |
---|---|---|
底层API | RDD | Process Function |
核心API | DataFrame/DataSet/Structured Streaming | DataStream/DataSet |
SQL | Spark SQL | Table API & SQL |
机器学习 | MLlib | FlinkML |
图计算 | GraphX | Gelly |
其他 | CEP |
从 API 上来看,Spark 和 Flink 提供的功能领域大致相当。当然具体看各个方向支持的程度会有差异。总体来看 Spark 的 API 经过几轮迭代,在易用性,特别是机器学习的集成方面,更强一些。Flink 在流计算方面更成熟一些。
支持语言 | Spark | Flink |
---|---|---|
Java | ✔️ | ✔️ |
Scala | ✔️ | ✔️ |
Python | ✔️ | ✔️ |
R | ✔️ | 第三方 |
SQL | ✔️ | ✔️ |
API使用,以对SocketStream进行WordCount代码为例
1 | // Spark wordcount |
可以看到二者在API上也很接近,最大的区别是spark streaming在一开始便指定了切分流数据的方式val ssc = new StreamingContext(conf, Seconds(10))
即10秒切分一次,然后对这一批进行处理。
而Flink是后面自己通过timeWindow算子timeWindow(Time.seconds(10))
来指定每10秒作为一个数据窗口进行处理。
从这个简单的例子上可以看出Spark Streaming的底层为micro batch处理方式,Flink为流处理方式。
不过它们大多数API,诸如map,flatMap,filter
之类的算子基本用法都一样,这样也方便开发者从一个框架切换到另一个框架来开发应用。
Streaming处理特性
对Time的支持
Flink支持三种time
EventTime
- 事件生成时的时间,在进入Flink之前就已经存在,可以从event的字段中抽取
- 必须指定watermarks的生成方式
- 优势:确定性,乱序、延时、或者数据重放等情况,都能给出正确的结果
- 弱点:处理无序事件时性能和延迟受到影响
IngestTime
- 事件进入flink的时间,即在source里获取的当前系统的时间,后续操作统一使用该时间
- 不需要指定watermarks的生成方式(自动生成)
- 弱点:不能处理无序事件和延迟数据
ProcessingTime
- 执行操作的机器的当前系统时间(每个算子都不一样)
- 不需要流和机器之间的协调
- 优势:最佳的性能和最低的延迟
- 弱点:不确定性 ,容易受到各种因素影像(event产生的速度、到达flink的速度、在算子之间传输速度等),压根就不管顺序和延迟
Flink支持这三种时间机制,并且有watermark机制来处理时间乱序,滞后的数据
Spark Streaming仅支持ProcessingTime,不过在Spark的Structured streaming中支持ProcessingTime和EventTime,同时支持 watermark 机制处理滞后数据。
对Window的支持
Window是一种切割无限数据集为有限块并进行相应计算的处理手段。
因为Spark的微批处理机制,对window的支持十分有限,仅支持基于ProcessingTime的Sliding Window(滑动窗口)
Flink 支持的window分为两大类:基于事件数count的window和基于时间(可以是上面提到的那三种时间)的window
Count-based window:根据元素个数对数据流进行分组切片
- Tumbling CountWindow:翻滚窗口
- Sliding CountWindow :滑动窗口
Time-based window :根据时间对数据流进行分组切片
- Tumbling Window:翻滚窗口
- Sliding Window:滑动窗口
- Session Window:类似于Web编程里的session,以不活动间隙作为分隔
除此之外还有一种特殊的Global Window,即全局Window,没有进行划分,各个Window详细介绍查看https://ci.apache.org/projects/flink/flink-docs-release-1.8/dev/stream/operators/windows.html#windows
在这方面基于纯粹流处理引擎的Flink比Spark Streaming功能更加强大
生态集成
Flink支持的Connectors:
- Apache Kafka (source/sink)
- Apache Cassandra (sink)
- Amazon Kinesis Streams (source/sink)
- Elasticsearch (sink)
- Hadoop FileSystem (sink)
- RabbitMQ (source/sink)
- Apache NiFi (source/sink)
- Twitter Streaming API (source)
Spark集成的生态:
Spark与Flink都能对接大部分常用的系统,如果没有支持还可以自定义实现一个connector。
除此之外还有一个开源项目Apache Bahir,它提供了spark与flink向外扩展的多个连接,并且在不断完善中。
总结
Spark的应用更为广泛,spark streaming只是spark其中的一大应用方向,它在生态总体上更完善一些,尤其是在机器学习的集成和易用性上面。
不过Flink在流式计算上有明显的优势,这主要是它们两者底层不同的执行模型带来的差别。Flink将真正意义上的纯流式计算带入了大数据时代。
目前spark针对流式计算处理的发展也在借鉴flink的一些设计思路,例如spark 2.0 引入的Structured Streaming,不过micro batch的执行方式依然存在一些局限性,特别在数据量达到一定规模时会有性能的问题。
二者都有各自擅长的应用方向,需要根据场景和应用方向来合理选择工具。