一、並行化數據接收
這個 方法在處理多個topic的數據是比較有效。
int numStreams = 5; List<JavaPairDStream<String, String>> kafkaStreams = new ArrayList<JavaPairDStream<String, String>>(numStreams); for (int i = 0; i < numStreams; i++) { kafkaStreams.add(KafkaUtils.createStream(...)); } JavaPairDStream<String, String> unifiedStream = streamingContext.union(kafkaStreams.get(0), kafkaStreams.subList(1, kafkaStreams.size())); unifiedStream.print() |
二、調節blockInterval參數
主旨:增加block數量,增加每個batch rdd的partition的數量,增加處理的並行度。
receiver從數據源源源不斷地獲取到數據,首先會按照block interval,將指定時間間隔的數據收集到一個block;默認時間是200ms,官方推薦不要小於50ms;然後會將指定batch interval時間間隔內的block合併爲一個batch,創建爲一個rdd,然後啓動一個job去處理這個batch rdd中的數據。
batch rdd的partition數量的確定:一個batch有多少個block,就有多少個partition,就意味着並行度是多少,意味着每個batch rdd有多少個task會並行計算和處理。
我們希望可以閉默認的task數量和並行度再多一些,可以手動調節block interval,減少block interval的數值,讓每個batch可以包含更多的block,有更多的partition,也就有更多的task並行處理每個batch rdd。
三、重分區
InputStream.repartition(<number of partitions>),增加每個batch rdd的partition數量,這樣可以提高指定的dstream的rdd的計算並行度。
四、調節並行度
調節參數:
spark.default.parallelism reduceByKey(numPartitions) |
五、使用Kryo序列化機制
提高序列化task發送到executor上執行的性能,如果task很多的時候,task序列化和反序列化的性能開銷會比較可觀。
默認輸入數據的存儲級別是StorageLevel.MEMORY_AND_DISK_SER_2,receiver接收到數據,默認就會進行持久化操作。首先持久化數據,存儲到內存中;如果內存資源不夠大,那麼就寫入磁盤;而且還會有一份冗餘副本寫到其他executor的block manager中。
六、設置batch interval
設置該參數,使每個batch的運行時間小於該參數。batch的運行時間可以通過spark ui進行查看。
如果發現batch的處理時間大於batch interval,必須調節batch interval,不要讓batch的處理時間大於batch interval。
比如batch每隔5秒生成一次,batch的處理時間要達到6秒。這個時候,batch在內存中日積月累,一直囤積着,沒法及時計算掉,釋放資源;而且對內存空間的佔用越來越大,導致內存空間快速消耗。
如果發現batch處理時間比batch interval大,儘量將batch interval調大一些。