Spark Streaming整合Kafka(二)

Direct 方法(沒有Receiver)

一、概述

本方法是從Spark1.3版本引進的,提供更加強大的端到端的數據保障,改善數據丟失的情況,並且不再採用receiver的方式去接收數據,這方法週期性地從每一個topic分區裏面查詢kafka最近的偏移量(offsets),再週期性定義每個批次(batch)的offset的範圍,相當於拿到每一個批次的偏移量後,再直接通過kafka的api,去kafka裏面,把每個批次的offset的範圍給讀取出來直接操作,當啓動任務去處理這個數據,使用kafka的simple consumer API去從kafka裏讀取偏移量的範圍,這跟讀文件系統非常類似,這特性在Spark1.3裏面支持Java和Scala,在Spark1.4版本里支持Python。

二 、優點

相比於receiver方式,本方式的優點有下面幾點:

1.簡化了並行度。我們不需要創建多個Input Stream然後把它們聯合起來,而是直接使用direct stream進行處理;

2. 高性能。能達到0數據丟失。在第一種方式裏面,我們需要把數據寫到WAL裏面,以副本的方式寸尺數據才能保證無數據丟失,這不是一種高效的方法,而採用第二種方式,不用receiver讀取數據,不需要寫WAL;

3. 滿足只執行一次的語義。第一種方式是使用kafka的高級別的API在zookeeper裏面存儲offset,這是傳統的方式從kafka裏面消費數據,這會有小的機率造成數據丟失,這是由於SparkStream所接收的數據跟zookeeper所追蹤的數據可能會出現不一致。而第二種方式,採用簡單的kafka API,不使用zookeeper。Offset將被Spark Streaming 的checkpoints所追蹤,這樣就能消除Spark Streaming與 zookeeper/kafka的不一致的問題,因此,每條記錄都將被Spark Streaming進行有效準確地一次性接收(儘管有時也會失敗)。

注意:爲了使你的結果輸出滿足只執行一次的語義,你的輸出數據到其他數據存儲設備的操作必須是冪等的,即是重複執行多少次結果都是一樣的,或者採用事務的方式保存輸出結果和offset,保持其原子性。

三、缺點

無法更新偏移量到Zookeeper裏面去,使得基於zookeeper的kafka監控工具無法使用,需要自己週期性地把每個批次消費的offsets更新到zookeeper裏去。

四、整合步驟

1. 導入依賴

groupId = org.apache.spark
 artifactId = spark-streaming-kafka-0-8_2.11
 version = 2.2.0

2.編碼

引入KafkaUtils建DirectStream(注意與第一種方式的差別)

 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])

Demo

import org.apache.spark.SparkConf
import org.apache.spark.streaming.kafka.KafkaUtils
import org.apache.spark.streaming.{Seconds, StreamingContext}
import kafka.serializer.StringDecoder
/**
  * Spark Streaming對接Kafka的方式二
  */
object KafkaDirectWordCount {

  def main(args: Array[String]): Unit = {

    if(args.length != 2) {
      System.err.println("Usage: KafkaDirectWordCount <brokers> <topics>")
      System.exit(1)
    }

    val Array(brokers, topics) = args

    val sparkConf = new SparkConf() //.setAppName("KafkaReceiverWordCount")
      //.setMaster("local[2]")

    val ssc = new StreamingContext(sparkConf, Seconds(5))

    val topicsSet = topics.split(",").toSet
    val kafkaParams = Map[String,String]("metadata.broker.list"-> brokers)

    // TODO... Spark Streaming如何對接Kafka
    val messages = KafkaUtils.createDirectStream[String,String,StringDecoder,StringDecoder](
    ssc,kafkaParams,topicsSet
    )

    // TODO... 自己去測試爲什麼要取第二個
    messages.map(_._2).flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).print()

    ssc.start()
    ssc.awaitTermination()
  }
}

3.部署

步驟同方式一,spark-submit命令如下:

spark-submit \
--class com.imooc.spark.KafkaDirectWordCount \
--master local[2] \
--name KafkaDirectWordCount \
--packages org.apache.spark:spark-streaming-kafka-0-8_2.11:2.2.0 \
/home/hadoop/lib/sparktrain-1.0.jar  hadoop000:9092 kafka_streaming_topic


官網地址:http://spark.apache.org/docs/latest/streaming-kafka-0-8-integration.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章