SparkStreaming性能调优
合理的并行度
减少批处理所消耗时间的常见方式还有提高并行度。有以下三种方式可以提高并行度:
1.增加接收器数目
有时如果记录太多导致单台机器来不及读入并分发的话,接收器会成为系统瓶颈。这时你就需要通过创建多个输入DStream(这样会创建多个接收器)来增加接收器数目,然后使用union 来把数据合并为一个数据源。
2.将收到的数据显式地重新分区
如果接收器数目无法再增加,你可以通过使用DStream.repartition 来显式重新分区输入流(或者合并多个流得到的数据流)来重新分配收到的数据。
3.提高聚合计算的并行度
对于像reduceByKey() 这样的操作,你可以在第二个参数中指定并行度,我们在介绍RDD 时提到过类似的手段。
并行度要合理
控制reduce 数量,太多的reducer, 造成很多的小任务, 以此产生很多启动任务的开销。太少的reducer, 任务执行行慢!
减少任务启动开销
使任务更小(更好的序列化,Kryo序列化)
输入数据序列化
RDD 序列化
TASK 序列化
在Standalone 及coarse-grained 模式下的任务启动要比fine-grained 省时(spark on yarn只支持coarse-grained)
1.粗粒度模式(Coarse-grained Mode):每个应用程序的运行环境由一个Dirver和若干个Executor组成,其中,每个Executor占用若干资源,内部可运行多个Task(对应多少个“slot”)。应用程序的各个任务正式运行之前,需要将运行环境中的资源全部申请好,且运行过程中要一直占用这些资源,即使不用,最后程序运行结束后,回收这些资源。举个例子,比如你提交应用程序时,指定使用5个executor运行你的应用程序,每个executor占用5GB内存和5个CPU,每个executor内部设置了5个slot,则Mesos需要先为executor分配资源并启动它们,之后开始调度任务。另外,在程序运行过程中,mesos的master和slave并不知道executor内部各个task的运行情况,executor直接将任务状态通过内部的通信机制汇报给Driver,从一定程度上可以认为,每个应用程序利用mesos搭建了一个虚拟集群自己使用。
2. 细粒度模式(Fine-grained Mode):鉴于粗粒度模式会造成大量资源浪费,Spark On Mesos还提供了另外一种调度模式:细粒度模式,这种模式类似于现在的云计算,思想是按需分配。与粗粒度模式一样,应用程序启动时,先会启动executor,但每个executor占用资源仅仅是自己运行所需的资源,不需要考虑将来要运行的任务,之后,mesos会为每个executor动态分配资源,每分配一些,便可以运行一个新任务,单个Task运行完之后可以马上释放对应的资源。每个Task会汇报状态给Mesos slave和Mesos Master,便于更加细粒度管理和容错,这种调度模式类似于MapReduce调度模式,每个Task完全独立,优点是便于资源控制和隔离,但缺点也很明显,短作业运行延迟大。
选择合适的batch Duration
没有最好的size,只有最合适的size,一切以系统反馈的数据说话
原则:要来得及消化流进系统的数据
可以从Log4j或者StreamingListener获取反馈
内存调优
默认序列化后放入内存
清理缓存的RDD
在spark.cleaner.ttl之前缓存的RDD都会被清除掉
设置spark.streaming.unpersis,系统为你分忧(自动清理)
CMS (暂停时间短,但吞吐率不高,并且会引起内存碎片)
spark-submit --conf spark.executor.extraJavaOptions=-XX:+UseConcMarkSweepGC App.jar
JVM还有另一个参数:-XX:CMSFullGCsBeforeCompaction
由于并发收集器不对内存空间进行压缩整理,所以运行一段时间以后会产生"碎片",使得运行效率降低.此值设置运行多少次Full GC以后对内存空间进行压缩整理
设置合理的cpu数
很多情况Streaming程序需要的内存不是很多,但是需要更多的cpu。Cpu资源用来做两大类事情:
1.接收数据
2.处理数据
我们需要设置足够的cpu资源,是得有足够的cpu资源用来接收和处理数据,这样才能及时高效的处理数据。