Spark Streaming 性能優化

性能優化

為了獲得運行在集群上的Spark應用的最好的性能需要一些調優。這一部分介紹了一些能夠改善應用性能的一些參數和配置。從更高的角度看,你需要考慮兩件事情:
1、高效的使用集群的資源從而降低每個batch的數據處理的時間
2、設置合理的batch的大小從而數據使得數據處理的速度和接收速度一樣。

減少每個Batch的處理時間

為了減少每個batch的處理時間 是有許多可以優化操作,稍后 Tuning Guide
中有討論。這一節著重講述了比較重要的一些優化。

數據接收的并行度

通過網絡接收到的數據需要數據在spark內進行反序列化和存儲。如果數據的接收變成了系統的瓶頸,就需要考慮并行處理數據的接收。需要注意的是,每個輸入流在worker的節點上創建了單獨的receiver,它只會接收一個流的數據。接收多個數據流的花需要通過創建多個數據流并且配置它們使得能夠接收輸入流的不同分區的數據。舉個例子,一個kafka的輸入DStream 接收兩個topic的數據可以其分成兩個stream,每個接收一個topic。這樣就會運行兩個receiver,這樣就會并行接收數據,因而提高了整體的吞吐量。多個DStream 可以union成一個DStream,然后之前應用于一個DStream的transformation 操作就可以應用于被unioned的DStream上了,操作入下:

val numStreams = 5
val kafkaStreams = (1 to numStreams).map { i => KafkaUtils.createStream(...) }
val unifiedStream = streamingContext.union(kafkaStreams)
unifiedStream.print()

另外一個需要考慮的就是 receiver的 block interval(區塊時長暫時翻譯),這個由參數configuration parameter spark.streaming.blockInterval 決定
接收多個數據流數據另外一個選擇是使用inputStream.repartition(<number of partitions>) 明確的切分輸入數據流。它會在數據處理之前,把接收到的多個batch的數據分發到集群中的指定數量的機器上

數據處理的并行度

如果并行計算的task的數量不夠大的話,集群的資源利用率是不高的。舉個例子,分布式的reduce操作,比如reduceByKey和reduceByKeyAndWindow,這個默認的并行度是參數 spark.default.parallelism 控制的。你可以作為參數傳入并行度或者配置這個參數來修改默認值。

數據的序列化

數據序列化的壓力可以通過優化序列化方式的方法解決降低。針對于streaming的情況,這里有兩種類型的數據可以被序列化。

  • InputData:默認情況下,Receiver接收到的數據是存儲在executors的內存內的,存儲的級別是StorageLevel.MEMORY_AND_DISK_SER_2.也就是說,數據是被序列化成字節以減少剛才的壓力。并且會被復制以防executor失敗。而且數據會優先保存在內存,直到需要計算的數據在內存已經保存不下的時候才會寫入到磁盤。這些序列化明顯過度耗費資源,reciiver必須反序列化接收到的數據并且重新序列化成spark序列化的方式。
  • Streaming操作產生的持久化的RDD streaming計算產生的RDD會被持久化在內存中,舉個例子,窗口操作會在內存中持久化這些數據以防數據需要多次被處理。當時不同于SparkCore默認的StorageLevel.MEMORY_ONLY,持久化的RDD是默認是按照StorageLevel.MEMORY_ONLY_SER進行持久化的。
    以上兩種情形,使用Kryo序列化會降低CPU和內存的過度使用。
    在某些特殊的情況下,比如spark不需要保持大量的數據,持久化數據使用反序列化后的對象不會導致過度的gc壓力,所以也是一種可行的辦法。舉個例子,如果你在使用一個幾秒的batch并且沒有window的操作,你可以顯示的設置storage的級別從而關閉序列化。這將會減少cpu因為序列化而導致的壓力,從而提升性能。

啟動的Task過多

如果每秒鐘啟動的task的數量非常高(比如,每秒50或者更多),那么分發任務到slave上的壓力將會非常大,并且將會使得要想獲得ms級別的延遲變得很難。這種壓力可以通過如下的改變降低:
執行模式:執行Spark使用standalone 模式或者粗粒度的 Mesos模式task的啟動時間會優于使用細粒度的Mesos的模式 可以參考 Running on Mesos guide
這個改變可以減少每個batch的時間到幾百ms,從而是的亞秒級的batchsize變得可行。

設置正確的batch間隔

為了保證運行在集群上的spark應用穩定,必須保證數據處理的速度要達到數據接收的速度。換句話說,每個batch處理數據的速度必須和產生的速度一致。是否能一致可以通過monitoring的web ui 上的處理時間看到。正常情況下,處理時間要小于間隔時間。
取決于streaming計算的天然特征,對于固定資源的集群,batch的間隔對于數據在應用中的保持率有重大影響。舉個例子,比如 WordCountNetwork,針對于特定的數據速率,系統可以支持每隔2s的單詞統計,但是卻不能支持500ms的。因此,batch的間隔時間需要設置成實際生產中需要保持的的期望的數據速率。
一個好方法就是 計算一個合適的batch的大小 去測試一 保守的batch間隔和一個比較低的數據速率。為了驗證系統是否能跟上數據的速率,你可以查看每個處理過的batch的端到端的處理延遲。如果delay的時間和batch的大小差不很多,那么系統就是穩定。否則的花,如果delay持續增加,意味著系統跟不上數據的速率從而變得不穩定。一旦你有兩個一個固定的配置,你就可以嘗試增加數據的速率或者減少batch的大小。需要注意的是,由于緩存數據增加導致的內存增加是ok的,只要延遲時間降到一個很低的值。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。