Apache Kafka与Spark Streaming的两种整合方法及其优缺点

译文
大数据 Kafka Spark
我们在将Apache Kafka与Spark Streaming整合的实战过程中,一般可以选用两种方面来配置Spark Streaming,并接收来自Kafka的数据。第一种是利用接收器和Kafka的高级API;而第二种新的方法则并不使用接收器。这两种方法在性能特征和语义保持上,有着不同的编程模式。

【51CTO.com快译】Kafka与Spark Streaming的整合

Apache Kafka与Spark Streaming的两种整合方法及其优缺点

我们在将Apache Kafka与Spark Streaming整合的实战过程中,一般可以选用两种方面来配置Spark Streaming,并接收来自Kafka的数据。***种是利用接收器和Kafka的高级API;而第二种新的方法则并不使用接收器。这两种方法在性能特征和语义保持上,有着不同的编程模式。

Apache Kafka与Spark Streaming的两种整合方法及其优缺点

下面让我们来详细探究一下这两种方法。

一、基于接收器的方法

此法运用接收器(Receiver)来接收数据。而接收器是利用Kafka的高级消费者(consumer)API来实现的。此外,接收到的数据会被存储在Spark的各个执行器(executor)中。然后由Spark Streaming所启动的作业来处理数据。

但是在出现失败时,这种方法的默认配置可能会丢失数据。因此,我们必须在Spark Streaming中额外地启用预写日志(write-ahead log),以确保数据的零丢失。它将所有接收到的Kafka数据,同步地保存到某个分布式文件系统的预写日志中,以便在出现失败时恢复所有的数据。

下面,我们将讨论如何在Kafka-Spark Streaming应用中,使用该基于接收器的方法。

1.链接

现在,先将您的Kafka Streaming应用与如下的artifact相链接,对于Scala和Java类型的应用,我们会用到SBT(Simple Build Tool)和Maven(一种构建工具)的各种项目定义。

 

  1. groupId = org.apache.spark 
  2. artifactId = spark-streaming-kafka-0-8_2.11 
  3. version = 2.2.0 

而对于Python类型的应用,我们必须在部署自己的应用时,额外添加上述库、及其各种依赖项。

2.编程

随后,我们在streaming应用的代码中,通过导入KafkaUtils,来创建一项DStream输入:

 

  1. import org.apache.spark.streaming.kafka._ 
  2. val kafkaStream = KafkaUtils.createStream(streamingContext, 
  3.     [ZK quorum], [consumer group id], [per-topic number of Kafka partitions to consume]) 

同样,通过使用createStream的各种变形方式,我们可以制定出不同的键/值类,及其对应的解码类。

3.部署

通常情况下,对于任何Spark应用而言,您都可以使用spark-submit来发布自己的应用。当然,就具体的Scala、Java和Python应用来说,它们在细节上会略有不同。

其中,由于Python应用缺少SBT和Maven的项目管理,我们可以使用–packages spark-streaming-kafka-0-8_2.11、及其各个依赖项,直接添加到spark-submit处。

  1. ./bin/spark-submit --packages org.apache.spark:spark-streaming-kafka-0-8_2.11:2.2.0 ... 

此外,我们还可以从Maven的存储库中下载Maven artifact的spark-streaming-Kafka-0-8-assembly所对应的JAR包,然后使用-jars,将其添加到spark-submit处。

二、直接方法(无接收器)

在基于接收器的方法之后,新的一种无接收器式“直接”方法诞生了。此法提供了更强大的端到端保证。它定期查询Kafka在每个topic+分区(partition)中的***偏移量,而不再使用接收器去接收数据。同时,它也定义了要在每个批次中处理的不同偏移范围。特别是在那些处理数据的作业被启动时,其简单消费者(consumer)API就会被用于读取Kafka中预定义的偏移范围。可见,此过程类似于从某个文件系统中读取各种文件。

注:针对Scala和Java API,Spark在其1.3版本中引入了此功能;而针对Python API,它在其1.4版本中同样引入了该功能。

下面,我们将讨论如何在Streaming应用中使用该方法,并深入了解更多有关消费者API的链接:

1.链接

当然,这种方法仅被Scala和Java应用所支持,并且通过如下artifact来链接STB和Maven项目。

 

  1. groupId = org.apache.spark 
  2. artifactId = spark-streaming-kafka-0-8_2.11 
  3. version = 2.2.0 

2.编程

随后,我们在Streaming应用的代码中,通过导入KafkaUtils,来创建一项DStream输入:

 

  1. import org.apache.spark.streaming.kafka._ 
  2. val directKafkaStream = KafkaUtils.createDirectStream[ 
  3.     [key class], [value class], [key decoder class], [value decoder class] ]( 
  4.     streamingContext, [map of Kafka parameters], [set of topics to consume]) 

我们必须在Kafka的参数中,指定metadata.broker.list或bootstrap.servers,以便它能够在默认情况下,从各个Kafka分区的***偏移量开始消费。当然,如果您在Kafka的参数中将auto.offset.reset配置为最小,那么它就会从最小的偏移开始消费。

此外,通过使用KafkaUtils.createDirectStream的各种变形方式,我们能够从任意偏移量开始消费。当然,我们也可以在每一个批次中,按照如下的方式去消费Kafka的偏移量。

 

  1. // Hold a reference to the current offset ranges, so downstream can use it 
  2. var offsetRanges = Array.empty[OffsetRange] 
  3. directKafkaStream.transform { rdd => 
  4.   offsetRanges = rdd.asInstanceOf[HasOffsetRanges].offsetRanges 
  5.   rdd 
  6. }.map { 
  7.           ... 
  8. }.foreachRDD { rdd => 
  9.   for (o <- offsetRanges) { 
  10.     println(s"${o.topic} ${o.partition} ${o.fromOffset} ${o.untilOffset}"
  11.   } 
  12.   ... 

如果您想使用基于Zookeeper的Kafka监控工具(https://data-flair.training/blogs/zookeeper-in-kafka/),来显示Streaming应用的进度,那么您也可以自行将其更新到Zookeeper中。

3.部署

该方面的部署过程与基于接收器的方法类似,此处就不赘述了。

三、直接方法的优点

就Spark Streaming与Kafka整合的角度而言,第二种方法较***种方法有着如下的优点:

Apache Kafka与Spark Streaming的两种整合方法及其优缺点

1.简化并行

无需创建与合并多个输入的Kafka Streams(https://data-flair.training/blogs/kafka-streams/)。但是,Sparking Streaming会创建同样多的RDD(Resilient Distributed Datasets,弹性分布式数据集)分区,以供多个Kafka分区使用直接的方法进行消费。这些分区也会并行地从Kafka中读取数据。因此我们可以说:在Kafka和RDD分区之间存在更容易被理解和调整的、一对一的映射关系。

2.效率

为了实现数据的零丢失,***种方法需要将数据存储在预写日志中,以供进一步复制数据。此方法的效率实际上是比较低的,因为数据被Kafka和预写日志实际复制了两次。而在直接的方法中,由于没有了接收器,因此不需要预先写入日志,此问题也就迎刃而解了。只要您拥有足够多的Kafka数据保留,各种消息就能够从Kafka中被恢复回来。

3.准确到位的语义

在***种方法中,我们使用Kafka的高级API,在Zookeeper中存储被消费的偏移量。然而,这种传统的、从Kafka中消费数据的方式,虽然能够确保数据的零丢失,但是在某些失败情况下,数据可能会被小概率地消费两次。实际上,这种情况源自那些被Spark Streaming可靠地接收到的数据,与Zookeeper跟踪到的偏移量之间所产生的不一致。因此在第二种方法中,我们不再使用Zookeeper,而只是使用一个简单的Kafka API。Spark Streaming通过其各个检查点(checkpoints),来跟踪不同的偏移量,籍此消除了Spark Streaming和Zookeeper之间的不一致性。

可见,就算出现了失败的情况,那些记录也都会被Spark Streaming有效地、准确地一次性接收。它能够确保我们的输出操作,即:将数据保存到外部数据存储库时,各种保存结果和偏移量的幂等性、和原子事务性,这同时也有助于实现准确到位的语义。

不过,这种方法也有一个缺点:由于它不会在Zookeeper中更新各种偏移量,因此那些基于Zookeeper的Kafka监控工具将无法显示进度。当然,您也可以自行访问每个批次中由此方法处理的偏移量,并更新到Zookeeper之中。

结论

通过上述讨论,我们学到了Kafka与Spark Streaming整合的全体概念。同时,我们也讨论了Kafka-Spark Streaming的两种不同配置方法:接收器方法和直接方法,以及直接方法的几项优点。

原文标题:Apache Kafka + Spark Streaming Integration,作者:Rinu Gour

【51CTO译稿,合作站点转载请注明原文译者和出处为51CTO.com】

责任编辑:未丽燕 来源: 51CTO.com
相关推荐

2022-03-15 08:25:32

SparkShuffle框架

2021-08-11 06:57:16

ShuffleSpark核心

2018-12-11 10:59:35

Tomcat NginxApache

2021-01-28 17:26:57

LoRa网络架构网络技术

2017-11-17 10:46:13

NginxApache服务器

2022-02-09 07:03:01

SpringNacos服务注册

2020-02-21 17:33:17

SparkKafka数据

2017-11-22 09:00:12

RAID类型磁盘

2016-01-28 10:11:30

Spark StreaSpark大数据平台

2023-11-09 09:09:36

ZookeeperCP组件

2023-09-12 10:49:44

Redis数据库

2017-10-13 10:36:33

SparkSpark-Strea关系

2010-10-14 14:33:15

MySQL多表联查

2009-06-19 18:36:15

JPAHibernate

2011-06-23 09:07:16

2012-10-16 09:40:38

洗牌算法

2013-11-13 14:11:43

2011-04-06 11:05:21

SQL Server数交换数据

2010-09-17 09:37:27

Java安装方法

2011-08-09 13:50:01

iPhone动画UIView
点赞
收藏

51CTO技术栈公众号