【转】Spark Streaming和Kafka整合开发指南
基于Receivers的方法
这个方法使用了Receivers来接收数据。Receivers的实现使用到Kafka高层次的消费者API。对于所有的Receivers,接收到的数据将会保存在Spark executors中,然后由Spark Streaming启动的Job来处理这些数据。
然而,在默认的配置下,这种方法在失败的情况下会丢失数据,为了保证零数据丢失,你可以在Spark Streaming中使用WAL日志,这是在Spark 1.2.0才引入的功能,这使得我们可以将接收到的数据保存到WAL中(WAL日志可以存储在HDFS上),所以在失败的时候,我们可以从WAL中恢复,而不至于丢失数据。
下面,我将介绍如何使用这种方法来接收数据。
1、引入依赖。
对于Scala和Java项目,你可以在你的pom.xml文件引入以下依赖:
<dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-streaming-kafka_2. 10 </artifactId> <version> 1.3 . 0 </version> </dependency> |
如果你是使用SBT,可以这么引入:
libraryDependencies += "org.apache.spark" % "spark-streaming-kafka_2.10" % "1.3.0" |
2、编程
在Streaming程序中,引入KafkaUtils,并创建一个输入DStream:
import org.apache.spark.streaming.kafka. _ val kafkaStream = KafkaUtils.createStream(streamingContext, [ZK quorum], [consumer group id], [per-topic number of Kafka partitions to consume]) |
在创建DStream的时候,你也可以指定数据的Key和Value类型,并指定相应的解码类。
1、Kafka中Topic的分区和Spark Streaming生成的RDD中分区不是一个概念。所以,在
KafkaUtils.createStream()
增加特定主题分区数仅仅是增加一个receiver中消费Topic的线程数。并不增加Spark并行处理数据的数量;
2、对于不同的Group和tpoic我们可以使用多个receivers创建不同的DStreams来并行接收数据;
3、如果你启用了WAL,这些接收到的数据将会被持久化到日志中,因此,我们需要将storage level 设置为StorageLevel.MEMORY_AND_DISK_SER
,也就是:
KafkaUtils.createStream(..., StorageLevel.MEMORY _ AND _ DISK _ SER) |
3、部署
对应任何的Spark 应用,我们都是用spark-submit
来启动你的应用程序,对于Scala和Java用户,如果你使用的是SBT或者是Maven,你可以将spark-streaming-kafka_2.10及其依赖打包进应用程序的Jar文件中,并确保spark-core_2.10和 spark-streaming_2.10标记为provided,因为它们在Spark 安装包中已经存在:
<dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-streaming _ 2.10 </artifactId> <version> 1.3 . 0 </version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-core _ 2.10 </artifactId> <version> 1.3 . 0 </version> <scope>provided</scope> </dependency> |
然后使用spark-submit来启动你的应用程序。
[iteblog@ spark]$ spark-1.3.0-bin-2.6.0 /bin/spark-submit --master yarn-cluster --class iteblog.KafkaTest --jars lib /spark-streaming-kafka_2 .10-1.3.0.jar, lib /spark-streaming_2 .10-1.3.0.jar, lib /kafka_2 .10-0.8.1.1.jar,lib /zkclient-0 .3.jar, lib /metrics-core-2 .2.0.jar . /iteblog-1 .0-SNAPSHOT.jar |
下面是一个完整的例子:
object KafkaWordCount { def main(args : Array[String]) { if (args.length < 4 ) { System.err.println( "Usage: KafkaWordCount <zkQuorum> <group> <topics> <numThreads>" ) System.exit( 1 ) } StreamingExamples.setStreamingLogLevels() val Array(zkQuorum, group, topics, numThreads) = args val sparkConf = new SparkConf().setAppName( "KafkaWordCount" ) val ssc = new StreamingContext(sparkConf, Seconds( 2 )) ssc.checkpoint( "checkpoint" ) val topicMap = topics.split( "," ).map(( _ ,numThreads.toInt)).toMap val lines = KafkaUtils.createStream(ssc, zkQuorum, group, topicMap).map( _ . _ 2 ) val words = lines.flatMap( _ .split( " " )) val wordCounts = words.map(x = > (x, 1 L)) .reduceByKeyAndWindow( _ + _ , _ - _ , Minutes( 10 ), Seconds( 2 ), 2 ) wordCounts.print() ssc.start() ssc.awaitTermination() } } |
Direct的方法
和基于Receiver接收数据不一样,这种方式定期地从Kafka的topic+partition中查询最新的偏移量,再根据定义的偏移量范围在每个batch里面处理数据。当作业需要处理的数据来临时,spark通过调用Kafka的简单消费者API读取一定范围的数据。这个特性目前还处于试验阶段,而且仅仅在Scala和Java语言中提供相应的API。
和基于Receiver方式相比,这种方式主要有一些几个优点:
(1)、简化并行。我们不需要创建多个Kafka 输入流,然后union他们。而使用directStream,Spark Streaming将会创建和Kafka分区一样的RDD分区个数,而且会从Kafka并行地读取数据,也就是说Spark分区将会和Kafka分区有一一对应的关系,这对我们来说很容易理解和使用;
(2)、高效。第一种实现零数据丢失是通过将数据预先保存在WAL中,这将会复制一遍数据,这种方式实际上很不高效,因为这导致了数据被拷贝两次:一次是被Kafka复制;另一次是写到WAL中。但是本文介绍的方法因为没有Receiver,从而消除了这个问题,所以不需要WAL日志;
(3)、恰好一次语义(Exactly-once semantics)。《Spark Streaming和Kafka整合开发指南(一)》文章中通过使用Kafka高层次的API把偏移量写入Zookeeper中,这是读取Kafka中数据的传统方法。虽然这种方法可以保证零数据丢失,但是还是存在一些情况导致数据会丢失,因为在失败情况下通过Spark Streaming读取偏移量和Zookeeper中存储的偏移量可能不一致。而本文提到的方法是通过Kafka低层次的API,并没有使用到Zookeeper,偏移量仅仅被Spark Streaming保存在Checkpoint中。这就消除了Spark Streaming和Zookeeper中偏移量的不一致,而且可以保证每个记录仅仅被Spark Streaming读取一次,即使是出现故障。
但是本方法唯一的坏处就是没有更新Zookeeper中的偏移量,所以基于Zookeeper的Kafka监控工具将会无法显示消费的状况。然而你可以通过Spark提供的API手动地将偏移量写入到Zookeeper中。如何使用呢?其实和方法一差不多
1、引入依赖。
对于Scala和Java项目,你可以在你的pom.xml文件引入以下依赖:
<dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-streaming-kafka_2. 10 </artifactId> <version> 1.3 . 0 </version> </dependency> |
如果你是使用SBT,可以这么引入:
libraryDependencies += "org.apache.spark" % "spark-streaming-kafka_2.10" % "1.3.0" |
2、编程
在Streaming应用程序代码中,引入KafkaUtils ,并创建DStream输入流:
import org.apache.spark.streaming.kafka. _ val directKafkaStream = KafkaUtils.createDirectStream[ [key class ], [value class ], [key decoder class ], [value decoder class ] ]( streamingContext, [map of Kafka parameters], [set of topics to consume]) |
在 Kafka parameters参数中,你必须指定 metadata.broker.list或者bootstrap.servers参数。在默认情况下,Spark Streaming将会使用最大的偏移量来读取Kafka每个分区的数据。如果你配置了auto.offset.reset为smallest,那么它将会从最小的偏移量开始消费。
当然,你也可以使用KafkaUtils.createDirectStream的另一个版本从任意的位置消费数据。如果你想回去每个batch中Kafka的偏移量,你可以如下操作:
directKafkaStream.foreachRDD { rdd = > val offsetRanges = rdd.asInstanceOf[HasOffsetRanges] // offsetRanges.length = # of Kafka partitions being consumed ... } |
你可以通过这种方式来手动地更新Zookeeper里面的偏移量,使得基于Zookeeper偏移量的Kafka监控工具可以使用。
还有一点需要注意,因为这里介绍的方法没有使用到Receiver,所以Spark中关于spark.streaming.receiver.*相关的配置参数将不会对创建DStreams 有影响。我们可以使用spark.streaming.kafka.*参数进行配置。
3、部署
对应任何的Spark 应用,我们都是用spark-submit
来启动你的应用程序,对于Scala和Java用户,如果你使用的是SBT或者是Maven,你可以将spark-streaming-kafka_2.10及其依赖打包进应用程序的Jar文件中,并确保spark-core_2.10和 spark-streaming_2.10标记为provided,因为它们在Spark 安装包中已经存在:
<dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-streaming _ 2.10 </artifactId> <version> 1.3 . 0 </version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-core _ 2.10 </artifactId> <version> 1.3 . 0 </version> <scope>provided</scope> </dependency> |
然后使用spark-submit来启动你的应用程序。
【转】Spark Streaming和Kafka整合开发指南的更多相关文章
- Spark Streaming和Kafka整合开发指南(二)
在本博客的<Spark Streaming和Kafka整合开发指南(一)>文章中介绍了如何使用基于Receiver的方法使用Spark Streaming从Kafka中接收数据.本文将介绍 ...
- Spark Streaming和Kafka整合开发指南(一)
Apache Kafka是一个分布式的消息发布-订阅系统.可以说,任何实时大数据处理工具缺少与Kafka整合都是不完整的.本文将介绍如何使用Spark Streaming从Kafka中接收数据,这里将 ...
- spark streaming基于Kafka的开发
spark streaming使用Kafka数据源进行数据处理,本文侧重讲述实践使用. 一.基于receiver的方式 在使用receiver的时候,如果receiver和partition分配不当, ...
- Spark Streaming和Kafka整合保证数据零丢失
当我们正确地部署好Spark Streaming,我们就可以使用Spark Streaming提供的零数据丢失机制.为了体验这个关键的特性,你需要满足以下几个先决条件: 1.输入的数据来自可靠的数据源 ...
- Spark Streaming和Kafka整合是如何保证数据零丢失
转载:https://www.iteblog.com/archives/1591.html 当我们正确地部署好Spark Streaming,我们就可以使用Spark Streaming提供的零数据丢 ...
- Spark Streaming与kafka整合实践之WordCount
本次实践使用kafka console作为消息的生产者,Spark Streaming作为消息的消费者,具体实践代码如下 首先启动kafka server .\bin\windows\kafka-se ...
- Spark streaming消费Kafka的正确姿势
前言 在游戏项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark streaming从kafka中不 ...
- spark streaming集成kafka
Kakfa起初是由LinkedIn公司开发的一个分布式的消息系统,后成为Apache的一部分,它使用Scala编写,以可水平扩展和高吞吐率而被广泛使用.目前越来越多的开源分布式处理系统如Clouder ...
- Spark Streaming on Kafka解析和安装实战
本课分2部分讲解: 第一部分,讲解Kafka的概念.架构和用例场景: 第二部分,讲解Kafka的安装和实战. 由于时间关系,今天的课程只讲到如何用官网的例子验证Kafka的安装是否成功.后续课程会接着 ...
随机推荐
- BestCoder Round #34_1002 以及 hdu 5191
枚举最终的W堆积木在哪,确定了区间,那么就需要把高于H的拿走,低于H的补上,高处的积木放到矮的上面,这样最优. 注意多出来的积木可以放在已有积木的前面或者后面,独立成一堆积木,所以需要在n堆积木的前后 ...
- jquery的2.0.3版本源码系列(4):285-348行,extend方法详解
目录 1 . jquery extend的基本使用 通过285行的源码 jQuery.extend = jQuery.fn.extend = function() { ,extend方法要么是直接挂在 ...
- 求最长公共前缀和后缀—基于KMP的next数组
KMP算法最主要的就是计算next[]算法,但是我们知道next[]求的是当前字符串之前的子字符串的最大前后缀数,但是有的时候我们需要比较字符串中前后缀最大数,比如 LeetCode的shortest ...
- Scala中柯里化函数
高阶函数转一阶函数: val add1 = (x: Int) => x + 5 def add2(x: Int)(y: Int) = x + y //传入一个参数转换为一阶函数 def add3 ...
- 高阶自定义View --- 粒子变幻、隧道散列、组合文字
高阶自定义View --- 粒子变幻.隧道散列.组合文字 作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:h ...
- win7系统盘扩容后不识别修复方法
谢天谢地 终于在不重装系统的情况下,把C盘修复好了. win7系统,C盘之前是200G,使用中慢慢的就用完, 虽然把几乎所有的软件都移植到D盘了但是还是不能释放更多的空间.剩下60多G的空间,一般够用 ...
- 理解 angular 的路由功能
相信很多人使用angular 都是因为他路由功能而用的 深入理解ANGULARUI路由_UI-ROUTER 最近在用 ionic写个webapp 看到几个demo中路由有好几种,搞的有点晕,查下资料研 ...
- 基于NIOS-II的示波器:PART2 界面动态显示功能
本文所有的硬件基础以及工程参考来自魏坤示波仪,重新实现驱动并重构工程. version 0.2 界面动态显示功能 界面显示功能原理 显示波形有如下两个方案: 每一帧直接重绘显示界面,再显示下一帧图形 ...
- AT&T汇编语言学习:利用c库、文件读写
AT&T汇编.调用C库函数.读/写文件 d0321:更新读文件代码(图片)以后会更新代码版. d0329:汇编文本读取.简单动画. ============================== ...
- React和Vue的组件更新比较
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 24.0px "Helvetica Neue"; color: #404040 } p. ...