Kafaka和Flink的流式处理比较

转载翻译自: Flink and Kafka Streams: a Comparison and Guideline for Users


Apache Kafka项目在大多数开源流处理器中一直是一个共同的组件,用以低延迟存储和数据移动。最近,Kafka社区引进了Kafka stream,一个流处理库,作为Kafka的一部分。随着Kafka stream和Kafka Connect的加入,Kafka现在增加了重要的流处理功能。

Apache Flink 根植在高性能集群计算和数据处理框架中。Flink可以运行内建的的流式处理计算,这些计算可以部署在 YARN、Mesos 或 Kubernetes 等资源管理器上。Flink jobs使用流数据并将数据生成到流、数据库或流处理器本身。Flink 通常与 Kafka 一起用作底层的存储层,但二者互相独立。

在 Flink 之前,流处理框架必须权衡延迟、吞吐量或结果准确性。Flink 是第一个开源框架(现在仍然是唯一的一个),它已被证明(1)在中等群集中以每时数千万的事件的顺序提供吞吐量,(2)低至小于 10 毫秒的延迟,(3)保证完全一致的应用程序状态语义,以及在源和接收器的支持下,精确的一次性的端到端交付与(例如,从Kafka到Flink到HDFS或Cassandra的管道),和 (4)通过对事件时间的支持,在出现无序数据到达的情况下获得准确的结果。Flink基于具有主节点和辅助节点的集群体系结构。Flink 群集高度可用,可以独立部署,也可以与YARN和Mesos等资源管理器一起部署。此体系结构允许Flink使用轻量级checkpoint机制来保证在发生故障时只产生一次结果,并允许通过checkpoint简单正确地重新处理,而不会牺牲延迟或吞吐量。最后,Flink也是一个成熟的批处理框架,除了其DataStream和DataSet API(分别用于流和批处理)之外,还提供各种更高级别的API和库,例如CEP(用于复杂事件处理)、SQL和Table(用于结构化流和表)、FMLlink(用于机器学习)和 Gelly(用于图形处理)。Flink 已被多家公司证明在生产中非常稳健,为最终客户每天使用的应用程序提供动力。

Streams API的目标是简化流处理,使其成为主流应用程序编程模型。为了帮助实现这个目标,Streams API中有一些经过深思熟虑的设计决策(1)它是一个没有集群的可嵌入library,只有Kafka和应用程序。使用Streams API,可以专注于构建驱动业务的应用程序,而不是构建集群。这使得它对于希望进行流式处理的应用程序开发人员来说更加容易实现,因为它与公司现有的打包、部署、监视和操作工具无缝集成。(2)它与Kafka中的核心抽象完全集成,因此Kafka的所有优势包括故障转移、弹性、容错,可扩展性和安全性可用于Stream API;Kafka在全球范围内的数千家公司中进行了大规模的测试和部署。3)它引入了新的概念和功能来允许流处理,例如,流和表的抽象的全聚合,您可以在应用程序中互换使用这些抽象来实现高性能的连接操作和连续查询。

Flink Kafka Stream API
部署 Flink 是一个群集框架,独立部署应用程序,使用 YARN、Mesos 或容器Docker、Kubernetes Streams API 是标准 Java 库,不会指定部署方法;可以使用任何部署技术,包括但不限于:容器(Docker、Kubernetes)、资源管理器(Mesos、YARN)、部署自动化(Puppet、Chef、Ansible)和自定义内部工具。
生命周期 用户的流处理代码在 Flink 集群中部署并运行作业 用户的流处理代码在应用程序内运行
所属团队 数据基础架构或 BI 团队 管理相应应用程序的业务线团队
协调 Flink 主服务器(作业管理器) 利用 Kafka 集群进行协调、负载平衡和容错。
连续数据源 Kafka、文件系统、其他消息队列 严格与Kafka的连接 API 服务, 以解决数据进入, 超出Kafka问题
结果接收器 Kafka、其他MQ、文件系统、分析数据库、密钥/值存储、流处理器状态和其他外部系统 Kafka、应用程序状态、操作数据库或任何外部系统
有界和无界数据流 有界和无界 无界
语义保证 对于内部 Flink 状态对应一次语义保证;端到端选定的源和接收器对应一次语义保证(例如,Kafka 到 Flink 到 HDFS);当Kafka被用作sinks至少一次 只需一次端到端保证

部署和组织管理

Flink流程序被建模为独立的流处理计算,通常称为job。Flink job的整个生命周期由Flink框架负责,包括部署、容错或升级。Flink job使用的资源来自资源管理器(如YARN、Mesos、现有群集中部署的Docker容器池(例如,YARN中的Hadoop群集)或来自独立的Flink安装。Flink job可以启动和停止自身,这对于有限的流式处理作业或批处理作业非常重要。从所有权的角度来看,Flink job通常是拥有框架运行的群集的团队的责任,通常是数据基础结构、BI或ETL团队。

Kafka中的StreamsAPI是一个可以嵌入到任何标准Java应用程序中的库。因此,Kafka Stream API应用程序的生命周期由应用程序开发人员或操作员负责。StreamsAPI并不规定应如何配置、监视或部署应用程序,并与公司现有的打包、部署、监视和操作工具无缝集成。从所有权的角度来看,Streams应用程序通常由各个产品团队负责。

除了影响部署模型之外,运行嵌入在应用程序中的流处理计算与作为群集中的独立进程运行还涉及资源隔离等问题。例如,在应用程序内运行流处理计算意味着它使用应用程序本身的打包和部署模型。在中央集群上运行流处理计算意味着您可以允许集中管理它,并使用集群已经提供的打包和部署模型。同样,在中央群集上运行流处理计算提供资源隔离,因为应用程序业务逻辑的流处理部分与应用程序的其余部分和消息传输层分开(例如,这意味着专用于流进程的资源与专用于Kafka的资源隔离)。另一方面,如果要使用一组统一的操作工具管理整个应用程序以及流处理部分,则在应用程序内运行流处理计算非常方便。

调用:流处理用于组织中的不同位置-从面向用户的应用程序到运行流数据分析。Kafka和Flink中的流API同时使用。主要区别在于这些应用程序位于其所在位置-如中央群集(Flink)中的作业或微服务(StreamsAPI)中的job。

分布式协调和容错

在分布式协调方面,两个系统之间的最大区别在于,Flink 具有专用的主节点进行协调,而 Streams API 则依赖于 Kafka 代理通过 Kafka 的协议进行分布式协调和容错。

在 Apache Flink 中,故障容错、缩放和状态的均匀分布由专用主节点全局协调。Flink 的主节点实现了基于 ZooKeeper 的自身高可用性。一个节点的故障也经常触发其他节点的恢复操作(如回滚更改)。此方法可帮助 Flink 获得高吞吐量,它支持 Flink 的checkpoint功能(用于应用程序快照、程序及框架升级),并且它支持 Flink 的接收器(例如,HDFS 和 Cassandra,但不是 Kafka)。即使对于非确定性程序,Flink 也可以这样保证结果等同于有效的无故障执行。值得指出的是,由于卡夫卡还没有提供一次完全的生产者,Flink当与卡夫卡作为水槽使用时,并没有提供结束到结束完全一次的保证的结果。

Kafka 中的 Streams API 通过利用 Kafka 中的核心单元提供容错性,保证持续处理和高可用性。用户应用程序或微服务的每个分片或实例都独立运行。所有协调工作由Kafka 代理进行;各个应用程序实例只需接收回调即可调整其他分区大小。故障容错内置于Kafka协议中;如果应用程序实例已结束或启动新实例,它会自动从代理接收一组新的分区来处理。嵌入 Streams API 程序的应用程序不必集成任何特殊的容错 API,甚至不必了解容错模型。这允许非常轻量级的集成;任何标准 Java 应用程序都可以使用 Streams API。

总之,虽然全局协调模型对于 Flink 中的流式处理作业功能强大,但它对于需要执行流处理的独立应用程序和微服务效果较低:应用程序必须参与 Flink 的检查点(实现某些 API),并且需要通过回滚某些状态更改来参与其他失败分片的恢复,以保持一致性。这显然不像 Streams API 方法那样轻量级。同样,这两种方法都显示了它们在不同情况下的优势。

结论

总之,虽然 Kafka 和 Flink 中的 Streams API 之间肯定有重叠,但它们部署在公司的不同部分,这主要是因为它们的体系结构不同,因此我们认为它们是互补系统。Streams API 使流处理可作为应用程序编程模型进行访问,而作为微服务构建的应用程序可以利用这些模型,并受益于 Kafka 的核心能力(性能、可扩展性、安全性、可靠性和快速、端到端的一次性处理),因为它与 Kafka 中的核心抽象紧密集成。另一方面,Flink 非常适合部署在现有群集中的应用程序,并受益于吞吐量、延迟、事件时间语义、保存点和操作功能、应用程序状态的一次保证、端到端的完全一次保证和批处理。