大数据学习之路96-SparkStreaming整合Kafka

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37050372/article/details/83046602

我们前面SparkStreaming获取数据的来源是TCP,但是平常是不会这么用的,我们通常用的是Kafka。

SparkStreamingContext是不直接提供对Kafka的访问的。

这个时候就有KafkaUtils

这里有两个方法

1.createDirectStream,是一种直连方式,他很重要,因为他用的是Kafka的底层API,他在消费的时候,会直接连到Kafka的分区上。

2.createStream,是有接收者的方式,而刚才我们讲的createDirectStream是没有接收者的方式。这是一种简单的方式,这种简单的方式在很早之前就出现了,但是他有一个问题,就是容易丢失数据,并且它的效率也比较低。

我们这里先使用这种简单的方式,这种简单方式其实他会自动帮我们维护偏移量,如果我们想要使用又高效,又不丢失数据的方式,我们就要手动维护偏移量。

使用这种傻瓜式的方式,我们首先要传进去StreamingContext,

第二个参数是zkQuorm,这个参数是zookeeper的连接地址

第三个参数是组id,我们知道消费者有一个消费者组,而我们SparkStreaming程序提交到集群中是分布式运行的。他相当于有很多的消费者。很多的消费者要消费同一份数据。他们不能重复消费,有了消费者组之后,就不会产生交叉消费的情况。

第四个参数是topic,他是一个Map,Map的key是主题名,value是分区数量

第五个参数是存储级别

配置完之后我们就可以从Kafka中获取数据,我们可以看到他的返回值为DStream类型的键值对,key为主题名称,value为值:

完整代码如下:

package com.test.sparkStreaming

import org.apache.spark.SparkConf
import org.apache.spark.storage.StorageLevel
import org.apache.spark.streaming.dstream.{DStream, ReceiverInputDStream}
import org.apache.spark.streaming.kafka.KafkaUtils
import org.apache.spark.streaming.{Seconds, StreamingContext}

object KafkaStreamingWordCount {
  def main(args: Array[String]): Unit = {
    Logger.getLogger("org.apache.spark").setLevel(Level.OFF)
    val conf: SparkConf = new SparkConf().setAppName("KafkaStreamingWordCount").setMaster("local[2]")
    //创建一个SparkStreamingContext
    val ssc: StreamingContext = new StreamingContext(conf,Seconds(5))
    //如果想要更新历史状态(累加),要设置checkpoint
    ssc.checkpoint("./ck")
    //从Kafka中拉取数据
    val zkQuorum = "marshal:2181,marshal01:2181,marshal02:2181,marshal03:2181,marshal04:2181,marshal05:2181"
    val groupId = "g1"
    val topic = Map("wordcount" -> 2)
    val lines: ReceiverInputDStream[(String, String)] = KafkaUtils.createStream(ssc,zkQuorum,groupId,topic ,StorageLevel.MEMORY_ONLY)
    //获取Kafka中的每一行内容
    val line: DStream[String] = lines.map(_._2)
    val result: DStream[(String, Int)] = line.flatMap(_.split(" ").map((_,1))).reduceByKey(_+_)
    result.print()
    ssc.start()
    ssc.awaitTermination()
  }
}

在执行之前首先我们检查一下我们有没有创建过wordcount的topic

 

接下来我们创建一个topic为wordcount

bin/kafka-topics.sh --create --zookeeper marshal:2181,marshal01:2181,marshal02:2181,marshal03:2181,
marshal04:2181,marshal05:2181 --replication-factor 3 --partitions 3--topic wordcount

我们可以看到这里有个分区,那么这里的分区和之前RDD的分区和mapreduce的分区是不一样的。

Kafka的分区就意味着在一台机器上分3个地方进行存储。一个分区会在其他机器上保存几份副本。

如果是hdfs中的数据会被切分成多个block块,而kafka中的数据会被存成多个分区。

创建完主题之后我们启动一个生产者,再执行程序观察效果:

猜你喜欢

转载自blog.csdn.net/qq_37050372/article/details/83046602