1. Kafka Stream Introduction
假设我们需要对kafka 消息做流数据分析,例如:
- 对部分消息做过滤
- 每分钟计算一次收到了多少消息
这种情况下,对于消息过滤以及定时统计,甚至是进行流的合并,是几个基本的流式处理。但是在这种情况下,仅使用Kafka Producer 与 Consumer 很难实现这些功能,因为它们属于非常底层的API,并且并不是developer friendly 的API。在这种情况下,我们可以考虑使用Kafka Stream。
什么是Kafka Stream?
它是一个Kafka提供,进行数据处理与转换的库,有如下特点:
- 由Java 标准实现
- 不需要创建另一个独立的kafka集群
- 较好的扩展、弹性以及容错能力
- 可实现Exactly Once传输语义
- 每次处理一个条目(no batching),不像spark streaming那样是微批处理
- 适用于任何规模的应用
常规的Kafka Stream处理架构如下,其中producer端使用了开源的kafka connector:
2. Differences among various Streams
当前主流的流处理有:Storm,Spark Streaming,Flink以及Kafka Stream。
Storm
Storm是最早的流处理框架,它的优点在于:
- 第延时、true streaming、高吞吐
- 非常适合复杂度不高的流场景
缺点为:
- 无状态管理(no state management)
- 缺少更高级的功能,例如事件-时间处理、聚合、窗口、sessions、watermark等等
- at-least-once 语义
Spark Streaming
Spark Streaming 非常流行,在Spark 2.0 之后的版本,称为结构化的流(structured streaming),性能提升了很多,并且增加了很多高级功能,例如定制的内存管理(tungsten),watermarks,事件事件处理等。
在2.3.0 版本之后,structured streaming除了可以(默认)使用micro-batching处理之外,还可以选择continuous streaming 模式。在micro-batching模式下,最低延时可达100ms,而在continuous streaming 模式下,最低延时可达几毫秒。在大部分real-time 应用场景下,micro-batching 的延时是可以接受的。不过如果有必要实现毫秒级别的延时(如信用卡交易欺诈之类的),则需要使用continuous streaming。
虽然spark streaming 的continuous streaming可以提供如Storm与Flink级别的低延时,不过它仅是一个预览版,尚未完全成熟。
Spark Streaming 的优点为:
- 支持Lambda架构,与Spark无缝连接
- 高吞吐,适用于大部分对延时要求不高的场景
- 默认实现的Fault tolerance(由原生的micro-batch提供)
- 简易使用的高级API
- 社区繁荣,更新频繁
- Exactly Once 语义
缺点有:
- 并不是真正的流处理,不适用于低延时的场景
- 需要调整太多参数,很难调整到合适的参数
- 默认是Stateless streaming
- 在一些高级特性上,落后于Flink
Flink
Flink 是一个真正的流处理框架,它的优点为:
- 第一个真正的流处理框架,具有所有高级功能,例如事件-时间处理,watermarks,等
- 低延时、高吞吐,可以根据需求做配置
- 自适应,没有太多的参数需要调优
- Excatly Once 语义
- 被大公司广泛使用
缺点有:
- 仅在Streaming中广泛使用,在Batch 场景中使用较少
Kafka Stream
Kafka Stream相较于其他所有流处理框架,是一个轻量级的库。常用于处理Kafka中的数据,做一些变换(transformation),然后发回Kafka。
由于它原生即为轻量级的,所以适用于一些微服务类型的架构中。kafka Stream的部署与使用非常简单,且并不需要额外建立一个集群去运行。它的内部使用的是Kafka Consumer group,与Kafka log 的机制共同实现流处理。
Kafka Stream一个最大的优点为:端到端的Exactly Once。启用时也仅需要启用一个flag即可。
它的优点有:
- 非常轻量级的库,适用于微服务,IOT应用
- 不需要一个dedicated cluster
- 继承了Kafka所有优点
- 支持Stream join,内部使用rocksDB管理state
- Exactly Once语义(Kafka 0.11 以后的版本)
缺点为:
- 与Kafka 紧密联系,无法在没有Kafka 的场景下使用
- 相较于Spark Streaming、Flink,不适用于大型业务场景
3. Stream Comparison
当前主流使用的流处理框架其实仅有两种:Spark Streaming与Flink。所以其实真正的竞争也仅在这两者之间。
一般来说,我们在比较两者的性能时,会对比一些压测数据。不过这里的问题在于:两者的压测数据对比并不能很有效的说明两者孰优孰劣,因为一个很小的因素或是配置就有可能造成两者性能的不同。
抛开数据来看,我们可以明显看到的是:Flink在流处理框架中,为一个引领者的状态。例如它的exactly once,吞吐,延时,state management,fault tolerance,以及其他高级的功能等,均是由Flink引导。Flink中的各种底层实现如light weighted snapshots、off-heap custom memory management 可能也帮助它成就了今天的地位。并且我们现在也可以看到Flink已经在各大公司被广泛地使用了。
这里有一点需要提及的是:各个原生的流处理框架,如Flink,Kafka Stream,Samza 等这些支持state management的处理框架,内部均使用的是RocksDb存储state。其中一个原因就是RocksDB在每个节点上,locally maintains 持久化的state数据,并且性能特别好。
4. 如何选择Streaming Framework
在选择Streaming Frameworks时,首先需要了解的一点是:没有万能的Streaming Framework,一切的选择都是基于需求。
如果业务场景较为简单,并不需要最新的框架(存在学习成本以及实现成本)。则可以根据可投入的成本选择一个框架。例如,如果仅是需要一个基于IOT的事件的警报系统,则Storm,Kafka Stream就已经足够了。
如果业务场景中需要一些高级的功能,如状态管理,stream join,聚合等,则要使用更先进的流处理框架如Spark Streaming或是Flink。
基于当前业务使用的技术栈,若是整个业务使用的是Kafka 端到端,则使用Kafka Stream 或是Samza会更简单。同样,如果基于的是Lambda架构,或者业务中已经使用了Spark Batch或是Flink Bath,则可以相应考虑使用Spark或是Flink。