目前实时计算的业务场景愈来愈多,实时计算引擎技术及生态也愈来愈成熟。以Flink和Spark为首的实时计算引擎,成为实时计算场景的重点考虑对象。那么,今天就来聊一聊基于Kafka的实时计算引擎如何选择?Flink or Spark?程序员
根据IBM的统计报告显示,过去两年内,当今世界上90%的数据产生源于新设备、传感器以及技术的出现,数据增加率也会为此加速。而从技术上将,这意味着大数据领域,处理这些数据将变得更加复杂和具备挑战性。例如移动应用广告、欺诈检测、出租车预订、患者监控等场景处理时,须要对实时数据进行实时处理,以便作出快速可行的决策。算法
目前业界有开源很多实时计算引擎,以Apache基金会的两款开源实时计算引擎最受欢迎,它们分别是Apache Flink和Apache Spark。接下来,咱们来聊一聊它们的使用场景、优点、局限性、类似性、以及差别性。方便你们在作技术选型时,选择切合项目场景的实时计算引擎。sql
提及实时计算,可能会说到流式计算,那么流式和实时是不是等价的呢?严格意义上讲,它们没有必然的联系。实时计算表明的是处理数据耗时状况,而流式计算表明的是处理数据的一种方式。后端
首先,它是一种数据处理引擎,其设计时考虑了无边界的数据集。其次,它与批处理不一样,批处理的Job与数据的起点和终点有关系,而且Job在处理完有限数据后结束,而流式处理用于处理连续数天、数月、数年、或是永久实时的无界数据。网络
流处理的特色:架构
流式处理能够分析连续的数据流,在这种方式中,数据被视为连续流,处理引擎在很短的时间内(几毫米到几分钟)内取数、分析、以及响应。下面让咱们来看看流式处理的场景使用场景:并发
Spark已成为批处理中Hadoop的真正继承者,也是第一个完美支持Lambda架构的框架。Spark受欢迎度极高,成熟而且普遍使用。Spark免费提供Spark Streaming,它使用微批处理进行流式传输。在Spark2.0以后,添加了许多优秀的功能(例如对tungsten、watermarks、event time处理的支持),同时结构化流也更加抽象,截止本篇博客Spark发布的可用版本为2.4.3,能够在最新版本中在微批处理和连续流模式之间进行切换。框架
结构化流式传输默认采用微批处理执行,Spark流式计算引擎会定时检查流数据。在连续流处理中,Spark不会启动定时任务,而是启动一组长时间运行的任务,这些任务能够连续读取、处理、写入数据。机器学习
微批处理中,驱动程序经过将记录Offset保存到预写Log来检测进度,而后可使用该Log从新进行查询。须要注意的是,在微批处理处理开始以前,须要在下一个微批处理中处理的范围Offset保存到Log中,以便获取肯定性的从新执行和端到端语义。所以,源记录可能须要等待当前的微批处理处理完成,而后记录其Offset。异步
连续流处理中,经过完善和改进算法来检测查询进度,特殊标记的记录被写入到每一个任务的输入数据流中。当任务遇到标记时,任务会异步报告处理的最后一个Offset,一旦驱动程序收到写入接收器的全部任务的Offset,它就会将它们写入预写Log中。因为Checkpoint彻底异步,所以任务能够不间断的继续,并提供一致的毫秒级延时。
对于Spark Streaming来讲,当不一样的数据来源输入进来时,基于固定的时间间隔,会造成一系列固定不变的数据集或者事件集(例如Kafka、Flume等)。这正好和Spark RDD基于固定的数据集吻合,从每个批处理来看,空间维度的RDD依赖关系一致,不一样的是这4个批处理输入的数据规模和数据内容不一样,因此生成的RDD依赖关系实例不同。
列举了Spark常见优点,以下所示:
另外,Spark也有它不足的地方,以下所示:
Flink也是来自Spark相似的学术背景,Spark来自加州大学伯克利分校,Flink来自柏林大学。像Spark同样,它也支持Lambda,但实现与Spark彻底相反。Flink本质上是一个真正的实时计算引擎,将批处理做为有限数据流的特殊状况。虽然两个计算框架中的API类似,但它们在实现中没有任何类似之处,在Flink中,Map、Filter、Reduce等各个函数实现为长时间运行的运算符(相似于Storm中的Bolt)。
Flink是一个开源的实时计算引擎,是实时计算领域的领导者。它拥有出色的图计算和机器学习功能,其底层支持On YARN模式,且提供了本地&分布式模式,以及Docker&Kubernetes等容器部署。
在低延时场景,须要实时数据,以便可以更快的检测和解决关键事件。例如,在使用Flink以前,计算的基本业务指标,实现的延时时间约为3到4小时,这意味着,若是工程师在早上10点左右检测到业务指标变化异常,只能在下午14点左右开始排查。若是可以立马解决,则只能在下午18左右时来验证解决方案,这样实现起来效率不是很高。
假如你的业务数据是基于时间序列的,那么咱们须要使用事件时间来处理在时间窗口内对业务指标进行分组。同时,Flink也能够很轻松的与存储在Kafka和HDFS中的业务数据进行集成。另外,Flink具备良好的非功能特性,便于在生产中运行,易于与不一样的监控后端集成(例如Graphite、Prometheus等),以及提供良好的UI界面。此外,Flink工做的快速开发周期以及简单的执行模型使得学习曲线平稳,开发效率高。
Flink相比较Spark Streaming不只提供了更低的延时,并且Flink还对窗口和事件时间提供了更好的支持。
现实场景中,大部分的数据来源都是无界的,不少状况下,咱们会对固定时间间隔的数据进行统计,好比每隔10秒统计一下集群服务的QPS,此时,窗口机制可以很好的帮助咱们实现这类需求。
如今咱们尝试使用事件时间来解决 状况二 的延时问题。要启用事件时间处理,须要一个时间戳提取器,从消息中提取事件时间信息。流式计算按照数据的事件时间来将数据分配到对应的窗口,而不是按照处理数据的时间,处理结果以下图。
引入事件时间后的结果看起来更好了,窗口2和窗口3发出了正确的结果,可是窗口1仍然是错误的。Flink没有将延迟的消息分配给窗口3,由于它如今检查的是消息的事件时间了,而且理解它不在窗口中。可是为何没有将消息分配给窗口1呢?缘由在于延迟的消息到达系统时(第19秒),窗口1的评估已经完成了(15秒)。
为了达到解决 状况二 的问题,达到 状况一 的预期结果。引入水印机制,水印机制能够看做是一种告诉Flink一个消息延迟多少的方式。如今将水印设置为当前时间负5秒,告诉Flink但愿消息最多有5秒的延迟,这是由于每一个窗口在水印经过时被评估。因为设置的水印时间为当前时间负5秒,因此窗口1(5秒~15秒)将在第20秒时被评估,以此类推,窗口2(10秒~20秒)将在第25秒时进行评估。优化后的结果以下:
最后调整引入水印机制后,获得正确的结果,这3个窗口均按照预期的方式发出计数,即(F,2)、(F,3)、(F,1)。
了解了Flink和Spark各自的特色后,知道了Spark Streaming经过小批量的方式保证了吞吐的状况下,同时提供了Exactly Once语义,可是不是严格意义上的实时,并且因为微批处理的方式,对窗口和事件时间的支持比较有限。Flink采用分布式快照的方式实现了一个高吞吐、低延时,而且支持Exactly Once的实时计算引擎,同时Flink的实时计算引擎也能更好支持窗口和事件时间。
经过对Flink和Spark特色的掌握,再结合实际的项目需求、业务场景、以及技术储备,来选取最适合的计算引擎。
欢迎工做一到五年的Java工程师朋友们加入Java程序员开发: 721575865 群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用本身每一分每一秒的时间来学习提高本身,不要再用"没有时间“来掩饰本身思想上的懒惰!趁年轻,使劲拼,给将来的本身一个交代!