Spark Streaming與kafka整合有以下兩種接收資料的方式:
基於Receiver的方式 基於Direct的方式 基於Receiver方式
這種方式使用Receiver來接收kafka中的資料,Receiver是基於kafka的高層Consumer API來實現的。Receiver從Kafka中獲取的資料都是儲存在Spark Executor的記憶體中的,然後Spark Streaming啟動的job會去處理那些資料。 在提交Spark Streaming任務後,Spark叢集會劃出指定的Receivers來專門、持續不斷、非同步讀取kafka資料,讀取時間間隔以及每次讀取offsets訪問由引數來配置。讀取的資料儲存在Receiver中,具體StorageLevel方式由使用者指定。當Driver觸發batch任務的時候,Receivers中的資料會轉移到Executors中去執行。在執行完之後,Receivers會相應更新Zookeeper的offsets。 在預設的配置下,這種方式可能會因為底層的失敗而丟失資料。如果要啟用高可靠機制,讓資料零丟失,就必須啟用Spark Streaming的預寫日誌機制(Write Ahead Log, WAL)。該機制會同步地將接收到的kafka資料寫入到分散式檔案系統(如HDFS)上的預寫日誌中。所以,即使底層節點出現了失敗,也可以通過預寫日誌中的資料進行恢復。 確保At least once的讀取方式,可以設定:spark.streaming.receiver.writeAheadLog.enable = true
基於Receiver方式讀取資料,使用者可以專注於所讀資料,而不用關注或維護consumer的offsets,這減少了使用者的工作以及程式碼量,而且相對比較簡單。 基於Receiver方式存在的問題:
啟用WAL機制,每次處理之前需要將該batch內的資料備份到checkpoint目錄中,這降低了資料處理效率,同時加重了Receiver的壓力;另外由於資料備份機制,會收到負載影響,負載一高就會出現延遲的風險,導致應用崩潰。 採用MEMORY_AND_DISK_SER降低對記憶體的要求,但是在一定程度上影響了計算的速度。 單Receiver記憶體。由於Receiver是屬於Executor的一部分,為了提高吞吐量,提高Receiver的記憶體。但是在每次batch計算中,參與計算的batch並不會使用這麼多記憶體,導致資源嚴重浪費。 提高並行度,採用多個Receiver來儲存kafka的資料。Receiver讀取資料是非同步的,不會參與計算。如果提高了並行度來平衡吞吐量很不划算。 Receiver和計算的Executor是非同步的,在遇到網路等因素時,會導致計算出現延遲,計算佇列一直在增加,而Receiver一直在接收資料,這非常容易導致程式崩潰。 在程式失敗恢復時,有可能出現資料部分落地,但是程式失敗,未更新offsets的情況,這會導致資料重複消費。
基於Direct方式
在Spark1.3版本中引入,替代使用Receiver來接收資料,這種方式會週期性地查詢kafka,來獲得每個topic+partition的最新的offset,從而定義每個batch的offset的範圍,當處理資料的job啟動時,就會使用kafka的簡單Consumer API來獲取kafka中指定offset範圍的資料。 基於Direct方式的優勢:簡化並行讀取:如果要讀取多個partition,不需要建立多個輸入DStream然後對他們進行union操作。Spark會建立跟Kafka partition一樣多的RDD partition,並且會並行從kafka中讀取資料。所以在kafka partition和RDD partition之間,有一一對應的關係。 高效能:如果要保證資料零丟失,在基於Receiver的方式中,需要開啟WAL機制。這種方式其實效率很低,因為資料實際被複制了兩份,kafka自己本身就有高可靠的機制,會對資料複製一份,而這裡又會複製一份到WAL中。而基於Direct的方式,不依賴於Receiver,不需要開啟WAL機制,只要kafka中做了資料的複製,那麼就可以通過kafka的副本進行恢復。 強一致語義:基於Receiver的方式,使用kafka的高階API來在Zookeeper中儲存消費過的offset。這是消費kafka資料的傳統方式。這種方式配合WAL機制,可以保證資料零丟失的高可靠性,但是卻無法保證資料被處理一次且僅一次,可能會處理兩次。因為Spark和Zookeeper之間可能是不同步的。基於Direct的方式,使用kafka的簡單api,Spark Streaming自己就負責追蹤消費的offset,並儲存在checkpoint中。Spark自己一定是同步的,因此可以保證資料時消費一次且僅消費一次。 降低資源:Direct不需要Receiver,其申請的Executors全部參與到計算任務中;而Receiver則需要專門的Receivers來讀取kafka資料且不參與計算。因此相同的資源申請,Direct能夠支援更大的業務。Receiver與其他Executor是非同步的,並持續不斷接收資料,對於小業務量的場景還好,如果遇到大業務量時,需要提高Receiver的記憶體,但是參與計算的Executor並不需要那麼多的記憶體,而Direct因為沒有Receiver,而是在計算的時候讀取資料,然後直接計算,所以對記憶體的要求很低。 魯棒性更好:基於Receiver方式需要Receiver來非同步持續不斷的讀取資料,因此遇到網路、儲存負載等因素,導致實時任務出現堆積,但Receiver卻還在持續讀取資料,此種情況容易導致計算崩潰。Direct則沒有這種顧慮,其Driver在觸發batch計算任務時,才會讀取資料並計算,佇列出現堆積並不不會引起程式的失敗。
基於Direct方式的不足
Direct方式需要採用checkpoint或者第三方儲存來維護offset,而不是像Receiver那樣,通過Zookeeper來維護offsets,提高了使用者的開發成本。 基於Receiver方式指定topic指定consumer的消費情況均能夠通過Zookeeper來監控,而Direct則沒有這麼便利,如果想做監控並視覺化,則需要投入人力開發。
感興趣可以加Java架構師群獲取Java工程化、高效能及分散式、高效能、深入淺出。高架構。效能調優、Spring,MyBatis,Netty原始碼分析和大資料等多個知識點高階進階乾貨的直播免費學習許可權 都是大牛帶飛 讓你少走很多的彎路的 群..號是:855801563 對了 小白勿進 最好是有開發經驗
注:加群要求
1、具有工作經驗的,面對目前流行的技術不知從何下手,需要突破技術瓶頸的可以加。
2、在公司待久了,過得很安逸,但跳槽時面試碰壁。需要在短時間內進修、跳槽拿高薪的可以加。
3、如果沒有工作經驗,但基礎非常紮實,對java工作機制,常用設計思想,常用java開發框架掌握熟練的,可以加。
4、覺得自己很牛B,一般需求都能搞定。但是所學的知識點沒有系統化,很難在技術領域繼續突破的可以加。
5.阿里Java高階大牛直播講解知識點,分享知識,多年工作經驗的梳理和總結,帶著大家全面、科學地建立自己的技術體系和技術認知!