flink优于spark的特性:
首先明确计算模型是不同的:
minibatch vs dataflow模型
minibatch:微批,时间驱动;
dataflow模型:事件驱动的
长尾效应
比如某个task数据量偏大或者有异常,整个stage要等这个task结束才能进行下一轮计算。这样既增大了延迟又浪费了资源。Flink上游的数据会持续发送到下游,不存在这个问题。
处理延迟
在正常情况下,SparkStreaming一个批次的时间会留有50%的空闲时间来抗突发,这50%的时间就是延迟时间。虽然SparkStreaming一个批次时间最小也可以是秒级别,但是相比Flink的任务来讲会有延迟。
资源使用
- 流处理可以同时利用所有节点,没有空闲时间,sparkstreaming的任务有空闲时间,机器的资源使用存在波峰波谷。
- 序列化:Spark默认使用java原生的序列化方式,用户也可以配置使用Kryo;Flink实现了自己的一套序列化方式,每种类型有自己的序列化器,序列化的时候只需要把值本身写入,节省资源并且提高效率。
- slot sharing:flink可以把资源密集型和非资源密集型的算子分到一个slot里面。
流处理语义
Flink的时间语义有三种:事件时间(Event Time)、接入时间(Ingestion Time)和处理时间(Processing Time), 窗口计算中使用watermark机制处理乱序数据。相比SparkStreaming其实只有处理时间,也无法处理乱序数据 。 在线上有个topurl场景,需求是计算每个小时的topurl。用Flink很容易实现,但是如果用SparkStreaming,它的一小时窗口是按照任务开始时间的一小时,不会按照事件时间取整的一小时,所以用SparkStreaming是无法实现。
flink实现了真正的流批一体
- 从API的层面,DataStream API 来处理有限流
- 从调度的层面,统一的调度策略,基于pipline region调度
- 从shuffle的层面,同时支持Pipelined Shuffle 和 Blocking Shuffle
spark优于flink的特性:
容错机制
spark支持backlist机制:三种级别的黑名单:application,stage,task,对于失败多次的节点或者executor禁用。
flink 重启策略:重启pipline region和重启全部,但是对于流式作业都是pipline的边,整个拓扑图是一个region,所以等于重启所有算子,依然会从checkpoint恢复。
本质上是调度机制的不同,一个是调度计算一个是调度数据。spark的时代还没有存算分离,所以倾向于计算在存储的节点上避免调度数据,在存算分离这种架构出现之后,spark本地性调度已经没有意义。
现在很多团队为了降低作业重启的巨大开销,引入了单点重启的机制,适用于允许数据少量丢失的场景。比如腾讯云的作业稳定性优化实践,京东云对Flink的优化。
反压问题
flink反压导致checkpoint时间变长,checkpoint过大。从而会导致checkpoint失败。
结论
- 如果已有的是sparkstreaming实现,并且对延迟要求不高,使用场景上都能满足,不要求降本增效,可以不更换Flink
- 如果集群服务器质量较差,过保机器比较多,甚至每天都有机器挂掉,在SparkStreaming能满足的时候使用SparkStreaming
- 场景不满足,降本增效,要求秒级甚至毫秒级的低延迟,使用Flink