Spark-streaming kafka數據接收兩種方式

@Author  : Spinach | GHB
@Link    : http://blog.csdn.net/bocai8058

1 Receiver-based Approach

import org.apache.spark.streaming.kafka._ 
val kafkaStream = KafkaUtils.createStream(streamingContext, 
[ZK quorum], [consumer group id], [per-topic number of Kafka partitions to consume])

這種方式利用接收器(Receiver)來接收kafka中的數據,其最基本是使用Kafka高階用戶API接口。對於所有的接收器,從kafka接收來的數據會存儲在spark的executor中,之後spark streaming提交的job會處理這些數據。

Receiver-based的Kafka讀取方式是基於Kafka高階(high-level) api來實現對Kafka數據的消費。在提交Spark Streaming任務後,Spark集羣會劃出指定的Receivers來專門、持續不斷、異步讀取Kafka的數據,讀取時間間隔以及每次讀取offsets範圍可以由參數來配置。讀取的數據保存在Receiver中,具體StorageLevel方式由用戶指定,諸如MEMORY_ONLY等。當driver 觸發batch任務的時候,Receivers中的數據會轉移到剩餘的Executors中去執行。在執行完之後,Receivers會相應更新ZooKeeper的offsets。如要確保at least once的讀取方式,可以設置spark.streaming.receiver.writeAheadLog.enable爲true。具體Receiver執行流程見下圖:

還有幾個需要注意的點:

  • 在Receiver的方式中,Spark中的partition和kafka中的partition並不是相關的,所以如果我們加大每個topic的partition數量,僅僅是增加線程來處理由單一Receiver消費的主題。但是這並沒有增加Spark在處理數據上的並行度。
  • 對於不同的Group和topic我們可以使用多個Receiver創建不同的Dstream來並行接收數據,之後可以利用union來統一成一個Dstream。
  • 如果我們啓用了Write Ahead Logs複製到文件系統如HDFS,那麼storage level需要設置成StorageLevel.MEMORY_AND_DISK_SER,也就是KafkaUtils.createStream(…,StorageLevel.MEMORY_AND_DISK_SER)

2 Direct Approach (No Receivers)

val stream = KafkaUtils.createDirectStream()

Direct方式採用Kafka簡單的consumer api方式來讀取數據,無需經由ZooKeeper,此種方式不再需要專門Receiver來持續不斷讀取數據。當batch任務觸發時,由Executor讀取數據,並參與到其他Executor的數據計算過程中去。driver來決定讀取多少offsets,並將offsets交由checkpoints來維護。將觸發下次batch任務,再由Executor讀取Kafka數據並計算。從此過程我們可以發現Direct方式無需Receiver讀取數據,而是需要計算時再讀取數據,所以Direct方式的數據消費對內存的要求不高,只需要考慮批量計算所需要的內存即可;另外batch任務堆積時,也不會影響數據堆積。其具體讀取方式如下圖:

這種方法相較於Receiver方式的優勢在於:

  • 簡化的並行:在Receiver的方式中我們提到創建多個Receiver之後利用union來合併成一個Dstream的方式提高數據傳輸並行度。而在Direct方式中,Kafka中的partition與RDD中的partition是一一對應的並行讀取Kafka數據,這種映射關係也更利於理解和優化。
  • 高效:在Receiver的方式中,爲了達到0數據丟失需要將數據存入Write Ahead Log中,這樣在Kafka和日誌中就保存了兩份數據,浪費!而第二種方式不存在這個問題,只要我們Kafka的數據保留時間足夠長,我們都能夠從Kafka進行數據恢復。
  • 精確一次:在Receiver的方式中,使用的是Kafka的高階API接口從Zookeeper中獲取offset值,這也是傳統的從Kafka中讀取數據的方式,但由於Spark Streaming消費的數據和Zookeeper中記錄的offset不同步,這種方式偶爾會造成數據重複消費。而第二種方式,直接使用了簡單的低階Kafka API,Offsets則利用Spark Streaming的checkpoints進行記錄,消除了這種不一致性。

引用:https://www.jianshu.com/p/d031132d131c


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