Spark Streaming和Kafka整合開發指南(二)

五柳-先生發表於2015-12-09

本文將介紹如何使用Spark 1.3.0引入的Direct API從Kafka中讀資料。

  和基於Receiver接收資料不一樣,這種方式定期地從Kafka的topic+partition中查詢最新的偏移量,再根據定義的偏移量範圍在每個batch裡面處理資料。當作業需要處理的資料來臨時,spark通過呼叫Kafka的簡單消費者API讀取一定範圍的資料。這個特性目前還處於試驗階段,而且僅僅在Scala和Java語言中提供相應的API。

  和基於Receiver方式相比,這種方式主要有一些幾個優點:
  (1)、簡化並行。我們不需要建立多個Kafka 輸入流,然後union他們。而使用directStream,Spark Streaming將會建立和Kafka分割槽一樣的RDD分割槽個數,而且會從Kafka並行地讀取資料,也就是說Spark分割槽將會和Kafka分割槽有一一對應的關係,這對我們來說很容易理解和使用;

  (2)、高效。第一種實現零資料丟失是通過將資料預先儲存在WAL中,這將會複製一遍資料,這種方式實際上很不高效,因為這導致了資料被拷貝兩次:一次是被Kafka複製;另一次是寫到WAL中。但是本文介紹的方法因為沒有Receiver,從而消除了這個問題,所以不需要WAL日誌;

  (3)、恰好一次語義(Exactly-once semantics)。《Spark Streaming和Kafka整合開發指南(一)》文章中通過使用Kafka高層次的API把偏移量寫入Zookeeper中,這是讀取Kafka中資料的傳統方法。雖然這種方法可以保證零資料丟失,但是還是存在一些情況導致資料會丟失,因為在失敗情況下通過Spark Streaming讀取偏移量和Zookeeper中儲存的偏移量可能不一致。而本文提到的方法是通過Kafka低層次的API,並沒有使用到Zookeeper,偏移量僅僅被Spark Streaming儲存在Checkpoint中。這就消除了Spark Streaming和Zookeeper中偏移量的不一致,而且可以保證每個記錄僅僅被Spark Streaming讀取一次,即使是出現故障。

  但是本方法唯一的壞處就是沒有更新Zookeeper中的偏移量,所以基於Zookeeper的Kafka監控工具將會無法顯示消費的狀況。然而你可以通過Spark提供的API手動地將偏移量寫入到Zookeeper中。如何使用呢?其實和方法一差不多


  1、引入依賴。

  對於Scala和Java專案,你可以在你的pom.xml檔案引入以下依賴:

1 <dependency>
2   <groupId>org.apache.spark</groupId>
3   <artifactId>spark-streaming-kafka_2.10</artifactId>
4   <version>1.3.0</version>
5 </dependency>

  如果你是使用SBT,可以這麼引入:

1 libraryDependencies += "org.apache.spark" "spark-streaming-kafka_2.10" "1.3.0"

  2、程式設計

  在Streaming應用程式程式碼中,引入KafkaUtils ,並建立DStream輸入流:

1 import org.apache.spark.streaming.kafka._
2  
3 val directKafkaStream = KafkaUtils.createDirectStream[
4     [key class], [value class], [key decoder class], [value decoder class] ](
5     streamingContext, [map of Kafka parameters], [set of topics to consume])

  在 Kafka parameters引數中,你必須指定 metadata.broker.list或者bootstrap.servers引數。在預設情況下,Spark Streaming將會使用最大的偏移量來讀取Kafka每個分割槽的資料。如果你配置了auto.offset.reset為smallest,那麼它將會從最小的偏移量開始消費。

  當然,你也可以使用KafkaUtils.createDirectStream的另一個版本從任意的位置消費資料。如果你想回去每個batch中Kafka的偏移量,你可以如下操作:

1 directKafkaStream.foreachRDD { rdd =>
2     val offsetRanges = rdd.asInstanceOf[HasOffsetRanges]
3     // offsetRanges.length = # of Kafka partitions being consumed
4     ...
5 }

你可以通過這種方式來手動地更新Zookeeper裡面的偏移量,使得基於Zookeeper偏移量的Kafka監控工具可以使用。

  還有一點需要注意,因為這裡介紹的方法沒有使用到Receiver,所以Spark中關於spark.streaming.receiver.*相關的配置引數將不會對建立DStreams 有影響。我們可以使用spark.streaming.kafka.*引數進行配置。

  3、部署

  對應任何的Spark 應用,我們都是用spark-submit來啟動你的應用程式,對於Scala和Java使用者,如果你使用的是SBT或者是Maven,你可以將spark-streaming-kafka_2.10及其依賴打包進應用程式的Jar檔案中,並確保spark-core_2.10和 spark-streaming_2.10標記為provided,因為它們在Spark 安裝包中已經存在:

01 <dependency>
02           <groupId>org.apache.spark</groupId>
03           <artifactId>spark-streaming_2.10</artifactId>
04           <version>1.3.0</version>
05           <scope>provided</scope>
06 </dependency>
07  
08 <dependency>
09           <groupId>org.apache.spark</groupId>
10           <artifactId>spark-core_2.10</artifactId>
11           <version>1.3.0</version>
12           <scope>provided</scope>
13 </dependency>

然後使用spark-submit來啟動你的應用程式。

  本文翻譯自:https://spark.apache.org/docs/latest/streaming-kafka-integration.html
尊重原創,轉載請註明: 轉載自過往記憶(http://www.iteblog.com/)
本文連結地址: 《Spark Streaming和Kafka整合開發指南(二)》(http://www.iteblog.com/archives/1326)

相關文章