SparkStreaming操作Kafka
Kafka为一个分布式的消息队列,spark流操作kafka有两种方式:
一种是利用接收器(receiver)和kafaka的高层API实现。
一种是不利用接收器,直接用kafka底层的API来实现(spark1.3以后引入)。
Receiver方式
基于Receiver方式实现会利用Kakfa的高层消费API,和所有的其他Receivers一样,接受到的数据会保存到excutors中,然后由spark Streaming 来启动Job进行处理这些数据。
在默认的配置下,这种方式在失败的情况下,会丢失数据,如果要保证零数据丢失,需要启用WAL(Write Ahead Logs)。它同步将接受到数据保存到分布式文件系统上比如HDFS。 所以数据在出错的情况下可以恢复出来。
使用两个步骤:
1、添加依赖:spark-streaming-kafka_2.10-1.3.0
2、编程:import org.apache.spark.streaming.kafka._
val kafkaStream = KafkaUtils.createStream(streamingContext,[ZK quorum], [consumer group id], [per-topic number of Kafka partitions to consume])
注意:
- kafka的分区数和Spark的RDD的分区不是一个概念。所以在上述函数中增加特定主题的分区数,仅仅增加了一个receiver中消费topic的线程数,并不难增加spark并行处理数据的数量。
(那是不是多少个paratition最好对应多少个receiver的消费线程啊?)
- 对于不同的group和topic,可以使用多个recivers创建多个DStreams来并行处理数据(如果是同一个topic如何保证数据不被重复消费?)
如果启用了WAL,接收到的数据会被持久化一份到日志中,因此需要将storage_lever设置成StorgeLevel.MEMORY_AND_DISK_SER
开启:val conf = new SparkConf()
conf.
set
(
"spark.streaming.receiver.writeAheadLog.enable"
,
"true"
)
val sc= new SparkContext(conf)
val ssc = new StreamingContext(sc,Seconds(5))
ssc.checkpoint(
"checkpoint"
)
val lines = KafkaUtils.createStream[String, String, StringDecoder, StringDecoder](ssc, kafkaParams, topicMap, StorageLevel.MEMORY_AND_DISK_SER).map(_._2)
//
开启在强行终止的情况下,数据仍然会丢失,解决办法:
sys.addShutdownHook({
ssc.stop(
true
,
true
)
)})
3、运行
运行提交代码的时候,需要添加以下基本Jar包依赖:
--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,
4、例子
object KafkaWordCount { def main(args: Array [ String ]) { if (args.length < 4) { System .err.println( "Usage: KafkaWordCount <zkQuorum> <group> <topics> <numThreads>" ) System .exit(1) } StreamingExamples .set StreamingLogLevels () val Array (zk Quorum , group, topics, num Threads ) = args val spark Conf = new SparkConf ().set AppName ( "KafkaWordCount" ) val ssc = new StreamingContext (spark Conf , Seconds (2)) //保证元数据恢复,就是 Driver 端挂了之后数据仍然可以恢复 ssc.checkpoint( "checkpoint" ) val topic Map = topics.split( "," ).map((_,num Threads .to Int )).to Map val lines = KafkaUtils .create Stream (ssc, zk Quorum , group, topic Map ).map(_._2) val words = lines.flat Map (_.split( " " )) val word Counts = words.map(x => (x, 1L)) .reduce ByKeyAndWindow (_ + _, _ - _, Minutes (10), Seconds (2), 2) word Counts .print() ssc.start() ssc.await Termination () } } |
5、图示:
<接收示意图>
<元数据恢复>
直接操作方式
不同于Receiver接收数据方式,这种方式定期从kafka的topic下对应的partition中查询最新偏移量,并在每个批次中根据相应的定义的偏移范围进行处理。Spark通过调用kafka简单的消费者API读取一定范围的数据。
相比基于Receiver方式有几个优点:
- 简单的并发:
不需要创建多个kafka输入流,然后Union他们,而使用DirectStream,spark Streaming将会创建和kafka分区一样的RDD的分区数,而且会从kafka并行读取数据,Spark的分区数和Kafka的分区数是一一对应的关系。
- 高效
第一种实现数据的零丢失是将数据预先保存在WAL中,会复制一遍数据,会导致数据被拷贝两次:一次是被Kafka复制;另一次是写入到WAL中,没有Receiver消除了这个问题。
- 仅一次语义:
Receiver方式读取kafka,使用的是高层API将偏移量写入ZK中,虽然这种方法可以通过数据保存在WAL中保证数据的不对,但是可能会因为sparkStreaming和ZK中保存的偏移量不一致而导致数据被消费了多次,
第二种方式不采用ZK保存偏移量,消除了两者的不一致,保证每个记录只被Spark Streaming操作一次,即使是在处理失败的情况下。如果想更新ZK中的偏移量数据,需要自己写代码来实现。
1、引入依赖
同第一种方式。
2、编程
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]) |
如果想获得每个topic中每个分区的在spark streaming中的偏移量,可以通过以下代码:
directKafkaStream.foreachRDD { rdd => val offsetRanges = rdd.asInstanceOf[HasOffsetRanges] // offsetRanges.length = # of Kafka partitions being consumed ... } //例子: val ssc = new StreamingContext(sc, Seconds( 2 )) val kafkaParams = Map( "zookeeper.connect" -> zkConnect, "group.id" -> kafkaGroupId, "metadata.broker.list" -> "10.15.42.23:8092,10.15.42.22:8092" , "auto.offset.reset" -> "smallest" ) val topics = Set(topic) val directKafkaStream = KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder]( ssc, kafkaParams, topics) //KafkaCluster 需要从源码拷贝,此类是私有类。 directKafkaStream.foreachRDD( rdd => { val offsetLists = rdd.asInstanceOf[HasOffsetRanges].offsetRanges val kc = new KafkaCluster(kafkaParams) for (offsets <- offsetLists) { val topicAndPartition = TopicAndPartition(offsets.topic, offsets.partition) val o = kc.setConsumerOffsets(kafkaGroupId, Map((topicAndPartition, offsets.untilOffset))) if (o.isLeft) { println(s "Error updating the offset to Kafka cluster: ${o.left.get}" ) } } } ) |
3、部署:
同第一种方式。
4、图示:
SparkStreaming操作Kafka的更多相关文章
- spark-streaming集成Kafka处理实时数据
在这篇文章里,我们模拟了一个场景,实时分析订单数据,统计实时收益. 场景模拟 我试图覆盖工程上最为常用的一个场景: 1)首先,向Kafka里实时的写入订单数据,JSON格式,包含订单ID-订单类型-订 ...
- SparkStreaming 整合kafka Demo
这里使用的是低级API,因为高级API非常不好用,需要繁琐的配置,也不够自动化,却和低级API的效果一样,所以这里以低级API做演示 你得有zookeeper和kafka 我这里是3台节点主机 架构图 ...
- SparkStreaming获取kafka数据的两种方式:Receiver与Direct
简介: Spark-Streaming获取kafka数据的两种方式-Receiver与Direct的方式,可以简单理解成: Receiver方式是通过zookeeper来连接kafka队列, Dire ...
- 【Spark】SparkStreaming和Kafka的整合
文章目录 Streaming和Kafka整合 概述 使用0.8版本下Receiver DStream接收数据进行消费 步骤 一.启动Kafka集群 二.创建maven工程,导入jar包 三.创建一个k ...
- 图解SparkStreaming与Kafka的整合,这些细节大家要注意!
前言 老刘是一名即将找工作的研二学生,写博客一方面是复习总结大数据开发的知识点,一方面是希望帮助更多自学的小伙伴.由于老刘是自学大数据开发,肯定会存在一些不足,还希望大家能够批评指正,让我们一起进步! ...
- SparkStreaming和Kafka基于Direct Approach如何管理offset实现exactly once
在之前的文章<解析SparkStreaming和Kafka集成的两种方式>中已详细介绍SparkStreaming和Kafka集成主要有Receiver based Approach和Di ...
- Spark-读写HBase,SparkStreaming操作,Spark的HBase相关操作
Spark-读写HBase,SparkStreaming操作,Spark的HBase相关操作 1.sparkstreaming实时写入Hbase(saveAsNewAPIHadoopDataset方法 ...
- SparkStreaming与Kafka,SparkStreaming接收Kafka数据的两种方式
SparkStreaming接收Kafka数据的两种方式 SparkStreaming接收数据原理 一.SparkStreaming + Kafka Receiver模式 二.SparkStreami ...
- 大数据学习day32-----spark12-----1. sparkstreaming(1.1简介,1.2 sparkstreaming入门程序(统计单词个数,updateStageByKey的用法,1.3 SparkStreaming整合Kafka,1.4 SparkStreaming获取KafkaRDD的偏移量,并将偏移量写入kafka中)
1. Spark Streaming 1.1 简介(来源:spark官网介绍) Spark Streaming是Spark Core API的扩展,其是支持可伸缩.高吞吐量.容错的实时数据流处理.Sp ...
随机推荐
- html字符转义
常用表: No. 文字表記 10進表記 16進表記 文字 Comment 001 " " " """ quotation mark ...
- atitit.提升开发效率---MDA 软件开发方式的革命(3)----自己主动化建表
atitit.提升开发效率---MDA 软件开发方式的革命(3)----自己主动化建表 1. 建模在后自己主动建表 1 1. 传统上,须要首先建表,在业务编码.. 1 2. 模型驱动建表---很多其它 ...
- JSP常用跳转方式
常用的跳转方式有以下几种: (1)href超链接标记,属于客户端跳转 (2)使用JavaScript完成,属于客户端跳转 (3)提交表单完成跳转,属于客户端跳转 (4)使用response对象,属 ...
- maven POM.xml内的标签大全详解
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...
- python之函数用法execfile()
# -*- coding: utf-8 -*- #python 27 #xiaodeng #python之函数用法execfile() #execfile() #说明:用来执行一个文件,相对于双击的效 ...
- Intellij IDEA 快捷键整理(dyCopy)
原文:http://www.cnblogs.com/tonycody/p/3257601.html [常规] Ctrl+Shift + Enter,语句完成 “!”,否定完成,输入表达式时按 “! ...
- redhat利用yum快速搭建LAMP环境
LAMP LAMP环境,对于PHP开发及其开源的PHP项目的部署都很关键的. LAMP的含义: L ---Linux A ---Apache web M ---Mysql datab ...
- cxf之org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'cxf' available
原因是.... 把cxf的配置文件spring-cxf-rest.xml配置结束后,没有import到spring.xml中...所以才加载不到bean.... 另附:异常org.springfram ...
- 【LeetCode】145. Binary Tree Postorder Traversal (3 solutions)
Binary Tree Postorder Traversal Given a binary tree, return the postorder traversal of its nodes' va ...
- HDU 2256 Problem of Precision (矩阵乘法)
Problem of Precision Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...