spark streaming参数调优

应用spark streaming的时候,可以在spark UI页面监控spark streaming的运行,UI页面有一个Streaming选项卡,展示如下:
spark streaming参数调优_第1张图片

里面有四个选项,分别是input rate,,scheduling delay,processing time和total delay,其中input rate下有一个该应用所使用的输入流的方法,这里是使用的kafkaUtil的direct stream。

  • input rate:即从数据源中接收数据的速率。
  • scheduling delay:即一个batch在等待前一个batch处理完成前在队列中所等待的时间。
  • processing time:数据的处理时间,即从接收到数据开始并进行数据转换存储操作的整个过程所使用的的时间
  • total delay:即schedule delay + processing time所使用的的时间

1.1 input rate参数调整

如果kafka中含有大量未被消费的数据,在刚启动spark streaming的时候会有大量数据涌入(特别在使用kafkaUtilcreateStream方法的时候,createStream中的receiver会直接把数据接收过来放入内存),如果不限制接受速率,内存可能无法放下所有数据从而造成OOM。在streaming窗口中数据的处理用时超过窗口的区间时间,可能会造成任务的积压,对集群资源带来一定的压力,spark1.5之后引入了一种反压机制,可以动态调整数据的接受速率。

从spark dstreaming中使用kafka中读取数据时一般分两种情况,一种是使用带有receiver进行数据的读取,典型方法为kafkaUtil.createStream,另一种是直接使用direct stream读取,典型方法为kafkaUtil.createDirectStream,有receiver和没有receiver接受数据的区别是:有receiver的应用在创建rdd的时候,源头数据是从receiver直接接受过来的,说明数据已经在receiver中了,而没有receiver的应用,在创建rdd时,数据还没有过来,只不过记录了一些元信息,等到task真正运行的时候才会获取数据,下面主要从这两方面进行参数配置。

(1) 反压机制

  • spark.streaming.backpressure.enabled,是否启用反压机制,默认false,根据官方文档显示,它会动态调整接收器的最大接受速率(Internally, this dynamically sets the maximum receiving rate of receivers.),因此它可能用于带有receivers的的数据获取,例如kafkaUtilcreateStream方法,不过它还受限于spark.streaming.receiver.maxRate和spark.streaming.kafka.maxRatePerPartition的设置

(2) 控制数据接收速率

对于使用带有receiver接受数据的参数配置

  • spark.streaming.backpressure.initialRate,receiver初始接受数据的最大速率
  • spark.streaming.receiver.maxRate,每个receiver接受数据的最大速率(每秒记录数),0或负值为不限制速率

对于没有receiver接受数据的参数配置

  • spark.streaming.kafka.maxRatePerPartition,从每个kafka partition读取数据的最大速率(每秒记录数),可以防止第一次访问时大量未处理数据的堵塞;防止高峰数据压力增大的情况
  • spark.streaming.kafka.minRatePerPartition,从每个kafka partition读取数据的最小速率(每秒记录数),默认1
  • spark.streaming.kafka.maxRetries,获取最新offsets的尝试此时,默认为1

速率估计器

  • spark.streaming.backpressure.pid.proportional (default: 1.0) can be 0 or greater.
  • spark.streaming.backpressure.pid.integral (default: 0.2) can be 0 or greater.
  • spark.streaming.backpressure.pid.derived (default: 0.0) can be 0 or greater.
  • spark.streaming.backpressure.pid.minRate (default: 100) must be greater than 0.,每秒每个partition100条信息可能太大,可以向下调整

1.2 processing time参数调整

(1) repartition

从多个流中接收数据的时候,可以对inputStream进行repartition(inputStream.repartition()),合理调整partition的个数,这样充分利用机器的多核。

(2) 提高数据处理的并行度

如果并行的任务数量不多的话,集群的资源可能得不到充分利用,因此可以通过spark.default.parallelism设置并行的任务数量。默认地,对于像reduceByKeyreduceByKeyAndWindow这样的聚合操作由parent RDD的partition最大数量控制;而对于像parallelize这样没有parent RDD的操作则依赖于集群的管理:

  • local model: 本地机器的核的个数
  • Mesos: 8
  • 其他:max(2, 所有executor的核的总个数)

(3) 数据序列化

在流处理中,有两种数据累了需要序列化:

  • 输入数据:这个主要是在使用reveiver接收数据的时候才会序列化

  • 由streaming操作产生的persisted RDDs:默认的是StorageLevel.MEMORY_ONLY_SER以减小GC的瓶颈,在spark UI的storage选项卡中可以看到序列化的RDDs。如果一个RDD不需要重复多次使用,不要使用persis方法,因为它会增加内存的消耗,在系统的默认设置中spark.streaming.unpersisttrue,即数据处理完成后就会清理数据

对于上述两种数据,官方建议使用kryo序列化以降低CPU和内存瓶颈,具体做法参考官网。

1.4 设置合适的batch interval

正常来说,数据的处理速度应该跟上数据的产生速度,可以通过spark UI来查看数据的processing time与scheduling delay,如果scheduling delay一直处于上升的趋势,则说明数据出现了积压。可以通过观察spark UI来调节batch interval的大小,一般尝试batch interval的大小在5s~10s。一般在初始接入kafka数据时,由于数据的接受速率增大而导致scheduling delay的上升,如果等待一段时间scheduling delay逐渐下降到batch interval以下这是没有问题的。

1.5 内存优化

spark streaming需要内存的大小取决于你如何对数据进行操作,另一方面对垃圾收集也有必要的优化。

  • DStream的持久化级别:如果对数据进行序列化,这会减少内存使用和GC瓶颈;也可以使用压缩算法(spark.rdd.compress=true)以减少内存的使用,但这是以降低CPU的性能为代价的,spark提供的压缩编码为lz4, lzf, snappyzstd,默认lz4
  • CMS垃圾收集器:官方强烈建议使用CMS垃圾收集器以减少系统停顿时间,但这可能降低系统处理的吞吐量,如果使用的话需要在driver和executor都设置CMS GC,参数分别为--driver-java-optionsspark.executor.extraJavaOptions,例如--driver-java-options=-XX:+UseConcMarkSweepGC,其中一些需要注意的问题参见官网spark-streaming conf配置。Introduction to Spark and Garbage Collection中介绍了几种GC在spark中应用,可以作为参考。我分别对CMS GC、G1和parallel GC进行测试,CMS和G1测试结果基本相同,在运行5min内GC 3s,而parallel GC + parallelOld GC运行25min GC 10s,因此需要根据具体的应用程序设置GC。
  • 其他技巧:
    • 持久化RDDs使用OFF_HEAP存储级别,这个在spark2.4.3还处于experimental状态,使用它需要提前开启off-heap内存
    • 使用更小的堆内存和更多的executor以减少GC的压力

你可能感兴趣的:(pyspark)