SparkStreaming整合Kafka

1.Receiver模式

1.KafkaUtils.createDStream--API创建。
2.会有一个Receiver作为常驻Task运行在Executor进行中,一直等待数据的到来。
3. 一个Receiver效率会比较低,那么可以使用多个Receiver,但是多个Receiver中的数据又需要手动进行合并,很麻烦,且其中某个Receiver挂了之后,会导致数据丢失,需要开启WAL预写日志来保证数据的安全,但是效率又低了。
4.Receiver模式使用Zookeeper来连接Kafka(Kafka的新版本中已经不推荐使用该方式了)
5.Receiver模式使用的是Kafka的高阶API(高度封装),offset由Receiver提交到ZK中(Kafka新版本的offset默认存储在__consumer_offset),容易与spark维护在Checkpoint中的offset不一样

2.Direct模式

1.KafkaUtils.CreateDirectStream--API创建
2. Direct模式是直接连接到Kafka的各个分区,并拉取数据,提高了数据读取的并发能力
3.Direct模式使用的是Kafka低阶API(底层API),可以自己维护偏移量到任何地方
4.Direct模式+手动操作可以保证数据的Exact-Once精确一次(数据仅会被处理一次)

注意

这两者模式都是依赖于此依赖

<dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-streaming-kafka-0-10_2.12</artifactId>
            <version>3.0.0</version>
        </dependency>

SparkStreaming整合Kafka的两个版本的API

Spark-streaming-kafka-0-8

支持Receiver、Direct模式,但不支持offset维护API,不支持动态分区。

Spark-streaming-kafka-0-10

支持Direct,不支持Receiver模式,支持维护offset维护API,支持动态订阅,推荐使用。

使用案例

1.创建环境

    // 配置环境
    val conf = new SparkConf().setAppName("Covid10WzApplication").setMaster("local[*]")
    val sc = new SparkContext(conf)
    sc.setLogLevel("WARN") // 设置日志打印等级
    val ssc = new StreamingContext(sc, Seconds(5))
    ssc.checkpoint("./sscckp") // 设置检查点

2.设置kafka连接参数

    // 准备Kafka的连接参数
    val kafkaParams = Map[String, Object](
      "bootstrap.servers" -> "hadoop102:9092,hadoop103:9092,hadoop104:9092", // 集群地址
      "group.id" -> "SparkKafka", // 消费者名称
      // latest表示如果记录了偏移量则从记录的位置开始读取数据,如果没有记录则从最新/最后的位置开始消费
      // earliest表示如果记录了偏移量则从记录的位置开始读取,如果没有记录则从最开始的位置开始消费
      // none 表示如果记录了偏移量则从记录的位置开始读取,如果没有则报错
      "auto.offset.reset" -> "latest",
      "enable.auto.commit" -> (false: java.lang.Boolean),// 是否自动提交偏移量
      "key.deserializer" -> classOf[IntegerDeserializer], // 反序列化类型
      "value.deserializer" -> classOf[StringDeserializer] // 反序列化类型
    )

3.订阅主题

    // 设置需订阅的Kafka主题
    val topics = Array[String]("covid_wz")
    // 连接Kafka,获取流式数据
    val KafkaDs = KafkaUtils.createDirectStream[Int, String](
        ssc,
        LocationStrategies.PreferConsistent,
        ConsumerStrategies.Subscribe[Int, String](topics, kafkaParams))

4.消费数据,手动提交偏移量

// 手动提交偏移量
    // 我们要手动提交偏移量,那么就意味着消费了一批数据(rdd)就应该提交一次偏移量
    KafkaDs.foreachRDD(rdd => {
      if (rdd.count() > 0) { // 判断rdd中是否有数据
        rdd.foreach(record => {
          println("从Kafka中消费的数据:" + record)
          // 从Kafka中消费的数据:ConsumerRecord(topic = covid_wz, partition = 0, leaderEpoch = 0, offset = 0, CreateTime = 1655871649181, serialized key size = -1, serialized value size = 3, headers = RecordHeaders(headers = [], isReadOnly = false), key = null, value = hhh)
        })
        // 获取偏移量
        // 使用Spark-streaming-kafka-0-10中封装好的API来存放偏移量并提交
        val offsets = rdd.asInstanceOf[HasOffsetRanges].offsetRanges
        for (o <- offsets) {
          println(o)
          // OffsetRange(topic: 'covid_wz', partition: 1, range: [2 -> 2])
           println(s"topic=${o.topic},partition=${o.partition},fromOffset=${o.fromOffset},until=${o.untilOffset}")
          //topic=covid_wz,partition=1,fromOffset=2,until=2
          //topic=covid_wz,partition=0,fromOffset=1,until=2
          //topic=covid_wz,partition=2,fromOffset=2,until=4
        }
         // 手动提交偏移量到Kafka的默认主题:__consumer_offsets中,如果还开启了Checkpoint还会提交给Checkponit
         KafkaDs.asInstanceOf[CanCommitOffsets].commitAsync(offsets)
      }
    })
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值