本期內容:
Exactly once
輸出不重複
Exactly once
1,事務一定會被處理,且只被處理一次;
2,輸出能夠輸出且只會被輸出。
- Receiver:數據通過BlockManager寫入內存+磁盤或者通過WAL來保證數據的安全性。
- WAL機制:寫數據時先通過WAL寫入文件系統然後存儲的Executor(存儲在內存和磁盤中,由StorageLevel設定),假設前面沒有寫成功後面一定不會存儲在Executor,如不存在Executor中的話,彙報Driver數據一定不被處理。WAL能對要寫入的數據,能保證其安全,失敗的可能性不大。
- 注意點:Receiver會把數據積累到一定程度才能寫入內存磁盤或WAL,如果還沒積累到一定程度,Executor或Receiver崩潰了怎麼辦?答案是數據還是可能會丟失幾條。因爲尚未做備份,根本沒有準備好數據塊。
- SparkStreaming說白了就兩點:獲取數據和產生作業。作業是通過SparkContext來執行的。
- 關於恢復:Driver級別的恢復:直接在Driver進行Checkpoint文件系統把數據讀入,內部則重啓SparkContext。InputDStream是Driver端產生的(因爲是框架調度層面的),這是在邏輯級別而言的。恢復過數據後,重新構建StreamingContext其實也就是構建SparkContext,恢復出的源數據再次產生RDD。恢復時根據上次的Job執行,所以恢復對應的Job,再次提交至Spark集羣,再次執行。另一方面,Receiver重新恢復,在以前的數據基礎上接收數據,曾經接收的數據根據WAL之類的機制從磁盤中恢復回來。通過這種方式 ,SparkStreaming是個相對可靠的系統,Driver發生故障後重新啓動可以在原有基礎上繼續執行,這樣我們就可以繼續原有任務而不丟失數據。
- Receiver只接收幾條,沒有及時WAL其實還是會丟失數據的,這是從整體SparkStreaming考慮而言的;而和Kafka結合的話不會有上面這種問題。
- 我們要做SparkStreaming的話,必須從生產作業流水線考慮輸入和輸出。外部數據源輸入Kafka,然後通過Kafka再交給SparkStreaming,SparkStreaming通過處理後將數據交給離線存儲系統或繼續交給Kafka或交給實時消費系統。
Exactly Once的事務處理:
1,數據零丟失:必須有可靠的數據來源和可靠的Receiver,且整個應用程序的metadata必須進行checkpoint,且通過WAL來保證數據安全;
2,Spark Streaming 1.3的時候爲了避免WAL的性能損失和實現Exactly Once而提供了Kafka Direct API,把Kafka作爲文件存儲系統!!!
此時兼具有流的優勢和文件系統的優勢,至此,Spark Streaming+Kafka就構建了完美的流處理世界!!!
所有的Executors通過Kafka API直接消費數據,直接管理Offset,所以也不會重複消費數據;事務實現啦!!!
數據丟失及其具體的解決方式:
在Receiver收到數據且通過Driver的調度Executor開始計算數據的時候如果Driver突然崩潰,則此時Executor會被Kill掉,那麼Executor中的數據就會丟失,此時就必須通過例如WAL的方式讓所有的數據都通過例如HDFS的方式首先進行安全性容錯處理,此時如果Executor中的數據丟失的話就可以通過WAL恢復回來;
數據重複讀取的情況:
在Receiver收到數據且保存到了HDFS等持久化引擎但是沒有來得及進行updateOffsets,此時Receiver崩潰後重新啓動就會通過管理Kafka的ZooKeeper中元數據再次重複讀取數據,但是此時SparkStreaming認爲是成功的,但是Kafka認爲是失敗的(因爲沒有更新offset到ZooKeeper中),此時就會導致數據重新消費的情況。
性能損失:
1,通過WAL方式會極大的損傷Spark Streaming中Receivers接受數據的性能;
2,如果通過Kafka的作爲數據來源的話,Kafka中有數據,然後Receiver接受的時候又會有數據副本,這個時候其實是存儲資源的浪費;
關於Spark Streaming數據輸出多次重寫及其解決方案:
1,爲什麼會有這個問題,因爲SparkStreaming在計算的時候基於SparkCore,SparkCore天生會做以下事情導致SparkStreaming的結果(部分)重複輸出:
Task重試;
慢任務推測;
Stage重複;
Job重試;
2,具體解決方案:
設置spark.task.maxFailures次數爲1;
設置spark.speculation爲關閉狀態(因爲慢任務推測其實非常消耗性能,所以關閉後可以顯著提高Spark Streaming處理性能)
Spark Streaming on Kafka的話,Job失敗後可以設置auto.offset.reset爲“largest”的方式。