说明:此程序使用的scala编写

在spark-stream+kafka使用的时候,有两种连接方式一种是Receiver连接方式,一种是Direct连接方式。

  两种连接方式简介:

  Receiver接受固定时间间隔的数据(放在内存中),达到固定的时间才进行处理,效率极并且容易丢失数据。通过高阶API,不用管理偏移量,由zk管理,若是拉取的数据超过,executor内存大小,消息会存放到磁盘上面。0.10之后被舍弃。
  弊端:效率极并且容易丢失数据

  直连(Direct)方式:**********重点
相当于直接连接到了kafka的分区上面,舍弃了高阶API,所以需要自己手动管理偏移量。运用底层API。效率高。需要手动的维护偏移量。企业生产使用。
  好处:不会走磁盘了,在拉取数据的时候,会有一个预处理机制。效率高。

                             

  两者的区别:  

  Receiver连接方式:他使用的是高级API实现Offset自动管理,不需要我们管理,所以他的灵活性特别差,不好,而且他处理数据的时候,如果某一时刻所传来的数据量特别大那么就会造成磁盘溢写的情况,他通过WALs进行磁盘的写入。
  直连方式:他使用的是底层的API实现Offset我们开发人员管理,这样的话,他的灵活性很好,并且可以保证数据的安全性,而且不用孤单行数据量过大。
  现在主要使用的Direct直连的方式,而不在使用receiver方式
  直连代码如下:
  

import kafka.common.TopicAndPartition
import kafka.message.MessageAndMetadata
import kafka.serializer.StringDecoder
import kafka.utils.{ZKGroupTopicDirs, ZkUtils}
import org.I0Itec.zkclient.ZkClient
import org.apache.spark.SparkConf
import org.apache.spark.rdd.RDD
import org.apache.spark.streaming.dstream.InputDStream
import org.apache.spark.streaming.kafka.{HasOffsetRanges, KafkaUtils, OffsetRange}
import org.apache.spark.streaming.{Duration, StreamingContext}
import redis.clients.jedis.Jedis object KafkaDirectConsumer {
def main(args: Array[String]): Unit = {
// 创建streaming
val conf = new SparkConf().setAppName("demo").setMaster("local[2]")
val ssc = new StreamingContext(conf, Duration(5000))
// 创建
// 指定消费者组
val groupid = "gp01"
// 消费者
val topic = "tt1"
// 创建zk集群连接
val zkQuorum = "spark101:2181,spark102:2181,spark103:2181"
// 创建kafka的集群连接
val brokerList = "spark101:9092,spark102:9092,spark103:9092"
// 创建消费者的集合
// 在streaming中可以同时消费多个topic
val topics: Set[String] = Set(topic)
// 创建一个zkGroupTopicDir对象
// 此对象里面存放这zk组和topicdir的对应信息
// 就是在zk中写入kafka的目录
// 传入 消费者组,消费者,会根据传入的参数生成dir然后存放在zk中
val TopicDir = new ZKGroupTopicDirs(groupid, topic)
// 获取存放在zk中的dir目录信息 /gp01/offset/tt
val zkTopicPath: String = s"${TopicDir.consumerOffsetDir}"
// 准备kafka的信息、
val kafkas = Map(
// 指向kafka的集群
"metadata.broker.list" -> brokerList,
// 指定消费者组
"group.id" -> groupid,
// 从头开始读取数据
"auto.offset.reset" -> kafka.api.OffsetRequest.SmallestTimeString
)
// 创建一个zkClint客户端,用host 和 ip 创建
// 用于从zk中读取偏移量数据,并更新偏移量
// 传入zk集群连接
val zkClient = new ZkClient(zkQuorum)
// 拿到zkClient后去,zk中查找是否存在文件
// /gp01/offset/tt/0/10001
// /gp01/offset/tt/1/20001
// /gp01/offset/tt/2/30001
val clientOffset = zkClient.countChildren(zkTopicPath)
// 创建空的kafkaStream 里面用于存放从kafka接收到的数据
var kafkaStream: InputDStream[(String, String)] = null
// 创建一个存放偏移量的Map
// TopicAndPartition [/gp01/offset/tt/0,10001]
var fromOffsets: Map[TopicAndPartition, Long] = Map()
// 判断,是否妇女放过offset,若是存放过,则直接从记录的
// 偏移量开始读
if (clientOffset > 0) {
// clientOffset的数量就是 分区的数目量
for (i <- 0 until clientOffset) {
// 取出 /gp01/offset/tt/i/ 10001 -> 偏移量
val paratitionOffset = zkClient.readData[String](s"${zkTopicPath}/${i}")
// tt/ i
val tp = TopicAndPartition(topic, i)
// 添加到存放偏移量的Map中
fromOffsets += (tp -> paratitionOffset.toLong)
}
// 现在已经把偏移量全部记录在Map中了
// 现在读kafka中的消息
// key 是kafka的kay,为null, value是kafka中的消息
// 这个会将kafka的消息进行transform 最终kafka的数据都会变成(kafka的key,message)这样的tuple
val messageHandlers = (mmd: MessageAndMetadata[String, String]) => (mmd.key(), mmd.message())
// 通过kafkaUtils来创建DStream
// String,String,StringDecoder,StringDecoder,(String,String)
// key,value,key的解码方式,value的解码方式,(接受的数据格式)
kafkaStream = KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder, (String, String)](
ssc, kafkas, fromOffsets, messageHandlers
)
} else { // 若是不存在,则直接从头读
// 根据kafka的配置
kafkaStream = KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder](ssc, kafkas, topics)
} // 偏移量范围
var offsetRanges = Array[OffsetRange]() kafkaStream.foreachRDD {
kafkaRDD =>
// 得到kafkaRDD,强转为HasOffsetRanges,获得偏移量
// 只有Kafka可以强转为HasOffsetRanges
offsetRanges = kafkaRDD.asInstanceOf[HasOffsetRanges].offsetRanges // 触发Action,这里去第二个值为真实的数据
val mapRDD = kafkaRDD.map(_._2)
/*=================================================*/
     // mapRDD为数据,在这里对数据操作
     // 在这里写你自己的业务处理代码代码
     // 此程序可以直接拿来使用,经历过层层考验      /*=================================================*/ // 存储更新偏移量
for (o <- offsetRanges) {
// 获取dir
val zkPath = s"${zkTopicPath}/${o.partition}"
ZkUtils.updatePersistentPath(zkClient, zkPath, o.untilOffset.toString)
}
} ssc.start()
ssc.awaitTermination() }
}

  以上为Direct直连方式的代码,直接可以使用的,根据自己的集群,和topic,groupid等配置稍作修改即可。

kafka结合Spark-streming的直连(Direct)方式的更多相关文章

  1. Spark Streaming消费Kafka Direct方式数据零丢失实现

    使用场景 Spark Streaming实时消费kafka数据的时候,程序停止或者Kafka节点挂掉会导致数据丢失,Spark Streaming也没有设置CheckPoint(据说比较鸡肋,虽然可以 ...

  2. Spark+Kafka的Direct方式将偏移量发送到Zookeeper实现(转)

    原文链接:Spark+Kafka的Direct方式将偏移量发送到Zookeeper实现 Apache Spark 1.3.0引入了Direct API,利用Kafka的低层次API从Kafka集群中读 ...

  3. 使用 Kafka 和 Spark Streaming 构建实时数据处理系统

    使用 Kafka 和 Spark Streaming 构建实时数据处理系统 来源:https://www.ibm.com/developerworks,这篇文章转载自微信里文章,正好解决了我项目中的技 ...

  4. 使用 Kafka 和 Spark Streaming 构建实时数据处理系统(转)

    原文链接:http://www.ibm.com/developerworks/cn/opensource/os-cn-spark-practice2/index.html?ca=drs-&ut ...

  5. Spark Streaming、Kafka结合Spark JDBC External DataSouces处理案例

    场景:使用Spark Streaming接收Kafka发送过来的数据与关系型数据库中的表进行相关的查询操作: Kafka发送过来的数据格式为:id.name.cityId,分隔符为tab zhangs ...

  6. TOP100summit:【分享实录-Microsoft】基于Kafka与Spark的实时大数据质量监控平台

    本篇文章内容来自2016年TOP100summit Microsoft资深产品经理邢国冬的案例分享.编辑:Cynthia 邢国冬(Tony Xing):Microsoft资深产品经理.负责微软应用与服 ...

  7. 整合Kafka到Spark Streaming——代码示例和挑战

    作者Michael G. Noll是瑞士的一位工程师和研究员,效力于Verisign,是Verisign实验室的大规模数据分析基础设施(基础Hadoop)的技术主管.本文,Michael详细的演示了如 ...

  8. Kafka与Spark案例实践

    1.概述 Kafka系统的灵活多变,让它拥有丰富的拓展性,可以与第三方套件很方便的对接.例如,实时计算引擎Spark.接下来通过一个完整案例,运用Kafka和Spark来合理完成. 2.内容 2.1 ...

  9. Spark Streaming揭秘 Day15 No Receivers方式思考

    Spark Streaming揭秘 Day15 No Receivers方式思考 在前面也有比较多的篇幅介绍了Receiver在SparkStreaming中的应用,但是我们也会发现,传统的Recei ...

随机推荐

  1. 如何修改config?

    这几天在做给WCF做加密传输,结果当然是实现了加密传输,同时也发现了一个问题,有没有大神来答疑解惑一下. 事情是这样的. 在客户端的配置中,需要加入一个behavior,在config文件中是这样的. ...

  2. jQuery判断复选框checkbox的选中状态

    通过jQuery设置复选框为选中状态 复选框 <input type="checkbox"/> 错误代码: $("input").attr(&quo ...

  3. JavaScript 函数式编程读书笔记1

    概述 这是我读<javascript函数式编程>的读书笔记,供以后开发时参考,相信对其他人也有用. 说明:虽然本书是基于underscore.js库写的,但是其中的理念和思考方式都讲的很好 ...

  4. [git] 常用配置

    基本配置 对git进行配置时使用 git config 命令进行操作 1. git config 的作用域,缺省等于 local git config --local   #只针对某个仓库有效 git ...

  5. LeetCode--No.002 Add Two Numbers

    Add Two Numbers Total Accepted: 160702 Total Submissions: 664770 Difficulty: Medium You are given tw ...

  6. HDU 5113--Black And White(搜索+剪枝)

    题目链接 Problem Description In mathematics, the four color theorem, or the four color map theorem, stat ...

  7. 串口USB单一映射及重命名

    本文针对在开发过程中有时会出现用到多个串口设备,usb端口号会发生变化,如设备的灯指示信号和其他控制器都是ttyUSB* .其序号与控制接入的顺序有关,对于写好的launch每次修改串口连接名很麻烦. ...

  8. 使用Spring Boot开发 “Hello World” Web应用

    环境准备 由于现在很多IDE都支持Maven, 所以我们将使用Maven构建该工程: 开始之前,需要先安装Java和Maven: 本工程将基于Spring Boot 1.4.3.RELEASE开发,推 ...

  9. 从零开始学 Web 之 BOM(二)定时器

    大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...

  10. Python 虚拟环境 | Mac/Linux下如何避坑安装配置Virtualenv

    1.为什么要使用虚拟环境 在Python中,不同的应用可能需要用到不同版本的第三方包,而这些第三方包被统一存放到目录site-packages中,不同版本的包容易相互覆盖,如安装Django 2.1时 ...