实时计算框架对比-Flink/Spark Streaming/Storm
作者:互联网
欢迎关注公众号:实时计算
引言
随着互联网和大数据技术的发展,实时计算框架也在推陈出新,向着高吞吐、高可用、低延迟准实时的方向发展。本文从几个方面全面对比业界流行的实时计算框架,总结了各框架的优缺点,希望对读者进行架构设计和技术选型提供帮助。
各框架对比概览
Spark Streaming |
Flink |
Storm |
|
项目时间 |
2014年左右开始流行 |
2016年左右开始流行 |
2012年左右开始流行 |
设计理念 |
流是批的特例 |
批是流的特例 |
事件驱动 |
时间语义 |
处理时间 |
事件时间,注入时间,处理时间 |
事件时间,处理时间 |
窗口 |
滑动窗口 |
滚动窗口、滑动窗口、会话窗口 |
新版本也开始支持滚动窗口和滑动窗口 |
一致性 |
Exactly-Once |
Exactly-Once |
At-Least-Once,通过Trident可以实现Exactly-Once |
反压 |
支持 |
支持 |
支持 |
延迟 |
秒级 |
毫秒级 |
毫秒级 |
吞吐量 |
高 |
高 |
低 |
容错性 |
checkpoint |
RDD checkpoint |
Record ACKs |
状态 |
支持(DStream) |
支持(Operators) |
不支持 |
流批一体 |
支持 |
支持 |
不支持 |
开发难度 |
较容易,多语言API |
容易,多语言API和SQL |
较难 |
机器学习 |
支持(MLlib) |
支持(FlinkML) |
不支持 |
社区 |
活跃 |
活跃 |
活跃较低 |
总结
Flink目前已经被各大互联网公司广泛使用,已经成为业界事实标准。Spark Streaming 在高吞吐复杂计算场景仍具优势。Storm 是最早流行的实时计算框架,但由于开发维护较复杂,功能简单,后逐渐被取代,新版本也增加了对事件时间、watermark、窗口计算的支持,成熟度和易用性还不足
01. 设计理念
Spark Streaming
Spark Streaming是在 Spark Core API基础上扩展出来的,以微批模式实现的近实时计算框架,它认为流是批的特例,将输入数据切分成一个个小的切片,利用Spark引擎作为一个个小的batch数据来处理,最终输出切片流,以此实现近似实时计算。
Flink
Flink是事件驱动的实时计算框架,它认为批是流的特例,数据流分为有限流(Bounded)和无限流(Unbounded),离线计算是对有限数据流的批处理,实时计算是对无限数据流的连续处理。有限流是有明确的开始和结束时间,无限流有明确的开始时间但没有结束时间。Flink是基于事件驱动,内部是对消息逐条emit。
Storm
Storm也是一个事件驱动的实时流计算框架,完全由开发者自己定义消息被处理的拓扑结构(Topology),它的结构和Mapreduce任务类似,通过自定定义Spout(数据输入处理模块)和Bolt(输出处理模块)逻辑,以及自定义Bolt之间的拓扑依赖关系,完成整个实时事件流的处理逻辑搭建。
Trident是在Storm核心API基础上更高层次的抽象,以微批的方式处理实时流,增加了窗口操作、聚合操作等,并且支持Exactly once。
基础架构
Spark Streaming
Spark Streaming是基于Spark核心API的扩展,整体架构和Spark一致,角色主要有:
Master:负责集群资源管理和应用程序调度
Worker:负责单个节点的资源管理,driver 和 executor 的启动等
Driver:程序执行入口,初始化SparkContext,负责生成DAG 、划分stage、生成调度task;
Executor:负责执行 task,反馈执行状态和执行结果
对于输入的每个批次都是一个Spark Core任务,Spark Streaming每个批次执行的拓扑结构不固定,会根据数据本地性和资源情况进行调度。
Flink
JobManager::协调分布式任务执行、调度、协调 checkpoints、协调故障恢复等。高可用情况下可以启动多个 JobManager,其中一个选举为 leader,其余为 standby
TaskManager:负责执行具体的task、缓存、交换数据流
Slot:每个 task slot 代表 TaskManager 的一个固定资源,Slot 的个数代表着 TaskManager 可并行执行的 task 数。
对于 Flink 任务客户端首先会生成 StreamGraph,然后生成 JobGraph,将 JobGraph 提交给 JobManager 由它完成 JobGraph 到 ExecutionGraph 的转换,最后由 JobManager 调度执行。
Storm
Nimbus:master节点,负责提交任务,分配到supervisor的worker上
Supervisor:slave节点,负责管理运行在supervisor节点上的worker进程,worker负责运行Topology上的Spout/Bolt任务
编程模型
Spark Streaming
Spark 的数据模型是弹性分布式数据集 RDD(Resilient Distributed Datasets),相对于 MapReduce 的文件模型,RDD 是一个更抽象的模型,只存在于内存中,RDD 靠血缘(lineage) 等方式来保证可恢复性。Spark 用 RDD 上的变换(算子)来描述数据处理。每个算子(如 map,filter,join)生成一个新的 RDD。所有的算子组成一个有向无环图(DAG)。
Spark DAG(来源:http://datastrophic.io/core-concepts-architecture-and-internals-of-apache-spark/)
从 Spark 2.0 开始引入的 Structured Streaming 重新整理了流计算的语义,支持按事件时间处理和端到端的一致性,但在功能上和成熟度上相对于Flink仍有差距。
Flink
Flink 数据模型是基于流(Streams)和转换(Transformations),由一个或多个 Source作为输入,并终止于一个或多个 Sink,通过不同的转换算子对数据流进行处理,组成有向无环图(DAG)。
Flink 中每个运算子任务与另外一个运算子任务之间都是相互独立的,它们是在不同的线程中运行的,甚至有可能所运行的机器或者容器都完全不同。可以精细的定义每个算子的并行度,运算子任务的数量由算子的并发数确定。
Flink 任务图(来源:https://ci.apache.org/projects/flink/flink-docs-release-1.5/concepts/runtime.html)
Storm
Storm实时任务是一个由开发者来自定义的拓扑结构(Topology),定义Spout来处理数据输入,定义Bolt来完成逻辑处理,Bolt即可以输出到一个或者多个Bolt也可以从多个Bolt作为输入,由此沟通一个DAG的Topology。
时间语义
在实时计算中一般有三个时间概念:
事件时间(Event Time)
事件时间指的是每个事件在设备上发生的时间,Flink可以从事件消息中提取该时间。例如一个按小时的事件时间窗口,所有事件时间落在这个小时的事件都会都会包含在计算结果里,跟事件消息到达的先后顺序无关。但窗口也不能无限的等待迟到的消息,因此需要结合watermark来使用,认为所有消息都已经到达窗口可以关闭。使用事件时间窗口需要等待后续事件和处理无序事件,会有一定的滞后性。
注入时间(Ingestion Time)
注入时间是事件在 source 算子处获取当前时间作为事件注入时间。相比于事件时间,注入时间不能够处理无序事件或者滞后事件,但是应用程序无需指定如何生成 watermark。
处理时间(Processing Time)
处理时间是运行各个算子实例机器的系统时间,是最简单的时间概念,它能提供最好的性能和最低延迟,但在分布式环境中不能保证事件的时序性。
Spark Streaming
Spark Streaming 只支持处理时间,Structured streaming 支持处理时间和事件时间,同时支持 watermark 机制来处理滞后数据。
Flink
Fink 支持三种时间机制:事件时间,注入时间,处理时间,同时支持 watermark 机制处理滞后数据。
Storm
新版本的Storm也支持事件时间,处理时间,同时支持watermark 机制。
反压机制(Back pressure)
在实时应用中,当实时处理的中间计算节点或者数据输出节点处理数据的速度变慢,需要通过反压机制将阻塞反馈给数据输入节点,降低数据输入速率,避免数据持续堆积。
Spark Streaming
Spark Streaming 是增加了基于PID算法的 RateController,通过batch计算完成后反馈回来的任务处理的结束时间、调度时间、处理时间、消息条数来计算当前速率,进而可以计算得到一个 offset,然后跟限速设置最大消费条数比较得到一个最终要消费的消息最大 offset。
spark.streaming.backpressure.enabled 设置为 true 开启反压
spark.streaming.kafka.maxRatePerPartition 每个partition每秒最多消费条数
spark.streaming.backpressure.rateEstimator 速率估算器类,目前只支持 pid 。
Flink
与 Spark Streaming 的反压不同的是,Flink 是 Jobmanager 针对每一个 task 每 50ms 触发 100 次 Thread.getStackTrace() 调用,求出阻塞的占比。
阻塞占比划分了三个等级:
OK:0 <= Ratio <= 0.10
LOW:0.10 < Ratio <= 0.5
HIGH: 0.5 < Ratio <= 1
当阻塞级别达到HIGH就需要进行任务优化了。一般调整资源分配和算子并行度来进行调优。
Storm
- 当Worker Executor 的接收队列达到高水位,通知反压线程 (Backpressure thread)
- 反压线程通知 zookeeper,在zk的topology节点下增加worker节点信息
- 所有 worker 监听 zookeeper executor 繁忙的事件
- worker节点接收到繁忙事件后 spouts 降低发送 tuple 速度
引用
Spark Streaming 和 Flink 详细对比(https://mp.weixin.qq.com/s/jllAegJMYh_by95FhHt0jA)
标签:处理,Flink,Streaming,时间,事件,Storm,Spark 来源: https://www.cnblogs.com/streaming-stack/p/16390457.html