本講內容:
a. Executor的WAL機制詳解
b. 消息重放Kafka
注:本講內容基於Spark 1.6.1版本(在2016年5月來說是Spark最新版本)講解。
上節回顧
上一講中,我們主要解密了ReceiverTracker具體的架構及其功能、源碼實現;
ReceiverTracker的架構設計
a. ReceiverTracker以Driver中具體的算法在具體的Executor之上啓動Receiver,而且啓動Receiver的方式是把每個Receiver封裝成一個Task, 此時一個Job中就一個Task,而Task中就一條數據,也就是Receiver數據,實質上說,ReceiverTracker啓動Receiver之時就會封裝在一個個Job,有多個Job就有多個Receiver,即有多個Receiver啓動就有多個Job封裝
b. ReceiverTracker在啓動Receiver的時候,有一個Receiversupervisor其裏面有一個ReceiversupervisorImpl實現類, Receiversupervisor實際上啓動之時就啓動了Receiver,Receiver不斷的接收數據,通過BlockGenerator把自已“接收的數據”變成一個個的Block。然後在時間定時器的作用下會不斷的把數據存儲(此時存儲有2種方式,第一種是通過BlockManager方式存儲,另一種先寫日誌Write,通過WAL方式),數據存儲之後ReceiverSupervisorImpl會把存儲後的數據的元數據Metadate彙報給ReceiverTracker,其實是彙報給ReceiverTracker中的RPC實體ReceiverTrackerEndpoint
c. ReceiverTracker用來管理Receiver中的數據執行,數據執行層面包括Receiver的啓動、回收、執行過程中接收數據的管理,當然也包括“Receiver”的容錯
d. Receiver接收到數據之後合併存儲數據後,ReceiverSupervisorImpl會把數據彙報給ReceiverTracker, ReceiverTracker接收到元數據,其內部彙報的是RPC通信體,接收到數據之後,內部有ReceivedBlockTracker會管理數據的分配,JobGenerator會將每個Batch,每次工作的時候會根據元數據信息從ReceiverTracker中獲取相應的元數據信息生成RDD。
e. ReceiverBlockTracker中 allocateBlocksToBatch專門管理Block元數據信息,作爲一個內部的管理對象。
還了解了什麼是門面設計模式
從設計模式來講:ReceiverTrackerEndpoint和ReceivedBlockTracker是門面設計模式,。
ReceiverTracker和ReceivedBlockTracker的關係是:內部實際幹事情的是ReceivedBlockTracker,外部通信體或者代表者就是ReceiverTracker
開講
本講我們從安全角度來講解Spark Streaming,由於Spark Streaming會不斷的接收數據、不斷的產生job、不斷的提交job。所以數據的安全性至關重要。
首先我們來談談,對於數據安全性的考慮:
a. Spark Streaming是基於Spark Core之上的,如果能夠確保數據安全可好的話,在Spark Streaming生成Job的時候裏面是基於RDD,即使運行的時候出現問題,那麼Spark Streaming也可以藉助Spark Core的容錯機制自動容錯
b. 對於executor的安全容錯主要是數據的安全容錯。Executor計算時候的安全容錯是藉助Spark core的RDD的,所以天然是安全的
那麼Executor容錯方式是什麼呢?
a. 最簡單的容錯是副本方式,基於底層BlockManager副本容錯,也是默認的容錯方式
b. 接收到數據之後不做副本,支持數據重放,所謂重放就是支持反覆讀取數據
ReceiverSupervisorImpl在存儲數據的時候會有兩種方式,一種是WAL的方式,究竟是不是WAL得方式是通過配置修改的。默認是false。如果用WAL的方式必須有checkpoint的目錄,因爲WAL的數據是放在checkpoint的目錄之下的
BlockManager備份
Blockmanager存儲數據的時候有很多storagelevel,Receiver接收數據後,存儲的時候指定storagelevel爲MEMORY_AND_DISK_SER_2的方式。Blockmanager早存儲的時候會先考慮memory,只有memory不夠的時候纔會考慮disk,一般memory都是夠的。所以至少兩個executor上都會有數據,假設一個executor掛掉,就會馬上切換到另一個executor
Storagelevel是在構建InputDStream的時候傳入的,默認就是MEMORY_AND_DISK_SER_2
我們來看看Receiver,發現都有StorageLevel變量
現在來看ReceiverSupervisorImpl
所以ReceiverSupervisorImpl在以副本方式存儲數據的時候;根據指定的storagelevel把接收的blocks交給blockmanager。也就是通過blockmanager來存儲
Blockmanager存儲的時候會分爲多種不同的數據類型,ArrayBufferBlock,IteratorBlock,ByteBufferBlock
有上面的BlockManagerBasedBlockHandler源碼具體實現是通過putIterator
doPut源碼如下
replicate源碼如下:
把數據備份到另一個節點
WAL方式
WAL的方式原理:在具體的目錄下會做一份日誌,假設後續處理的過程中出了問題,可以基於日誌恢復,日誌是寫在checkpoint下。在生產環境下checkpoint是在HDFS上,這樣日誌就會有三份副本
進入到ReceivedBlockHandler源碼
進入到WriteAheadLogBasedBlockHandler源碼
使用WAL,就沒必要將replication變成2份。WAL是寫到checkpoint目錄中,而checkpoint是保持在HDFS中,HDFS默認是3份副本
存儲數據的時候是同時往WAL和BlockManager中放數據
然後將數據存儲到BlockManager中
使用write方法寫入到log中
WAL寫數據的時候是順序寫,數據不可修改,所以讀的時候只需要按照指針(也就是要讀的record在那,長度是多少)讀即可。所以WAL的速度非常快
FileBasedWriteAheadLog管理WAL文件
直接將數據寫入到HDFS的checkpoint
不同時間不同條件下,會寫入到不同的文件中,會有很多小文件
Read部分
不管是WAL還是直接交給blockmanager都是採用副本的方式。還有一種是數據源支持數據存放,典型的就是kafka。Kafka已經成爲了數據存儲系統,它天然具有容錯和數據副本
Kafka有receiver和direct的方式。Receiver的方式其實是交給zookeper來管理matadata的(偏移量offset),如果數據處理失敗後,kafka會基於offset重新讀取數據。爲什麼可以重新讀取?如果程序崩潰或者數據沒處理完是不會給zookeper發ack。Zookeper就認爲這個數據沒有被消費。實際生產環境下越來越多的使用directAPI的方式,直接去操作kafka並且是自己管理offset。這就可以保證有且只有一次的容錯處理。DirectKafkaInputDstream,它會去看最新的offset,並把這個內容放入batch中
獲取最新的offset,通過最新的offset減去上一個offset就可以確定讀哪些數據,也就是一個batch中的數據
a. 容錯的弊端就是消耗性能,佔用時間。也不是所有情況都不能容忍數據丟失。有些情況下可以不進行容錯來提高性能
b. 假如一次處理1000個block,但是有1個block出錯,就需要把1000個block進行重新讀取或者恢復,這也有性能問題