Spark性能调优

算子级别的优化:coalesce和repartition都能增加或减少分区的数量,repartition会发生shuffle

1、浪费资源、数据倾斜:filter+coalesce(+repartition)
业务测试local,不需要去设置分区和并行度的数量
2、foreachpartition:大部分的内存:计算 、 shuffle,设法减少每个partition的数据量
3、mapPartitions:oom内存溢出——数据量的问题
4、reduceByKey:自带combiner,不能先执行groupByKey,然后执行MaptoPair(思考
题,怎么改成reduceByKey)——自带combiner,减少shuffle的数据量,降低spark作业90%以上的性能消耗
5、repartition:解决SparkSQL低并行度的性能问题
textFile()传入第二个参数,修改partition的数量,小于一个block块(数据量很小)——local[]匹配当前电脑线程数
第二参数不用传:,从HDFS中读取文件进行处理,有几个block就对应几个partition,只要有shuffle操作,那么,spark.default.parallelism设置的参数会生效,相当于设置reduce的数量 *ByKey()除了countByKey外的第二个参数是设置新产生的分区的数量,设置executor的cpu core,一般情况下,指定parallelism的参数是cpu core总数的2~3倍

性能调优:
1、分配更多的资源(性能调优的王道)——机器更多了,CPU更多了,内存更多了——分配executor num 、CPU core per executor、memory per executor、Driver Memory资源
提交作业时,用spark-submit提交脚本;
增加executor的数量,并行处理能力(task数量)增强
executor cpu core:线程级别的并行能力,一般3——5个,内存3——5g,避免过多,竞争资源,容易饿死
增加每个executor的内存量,可以有更多的cache进行缓存,减少重算,对于shuffle的操作,落地磁盘的数据量减少;对于task的执行,避免了频繁的进行垃圾回收
2、并行度的设置——将分配的硬件资源尽可能的使用起来
“重剑无锋”
3、RDD的持久化:一旦一个RDD重新计算,性能会大幅度下降
RDD架构与优化、公共的RDD一定要实现持久化、持久化是可以进行序列化——RDD是由(BlockManagerMaster)BlockManager(MemoryStore、DiskBlockStore)管理的
4广播大变量:共享变量中的Broadcast(小的技术点)——lazy类型,如果节点上没有的话,去Driver的BlockMangerMaster,然后选择近的BlockManager去找,每个节点(executor)一个广播变量,均衡IO负载
5、kryo的序列化:对于shuffle的优化,reduce处理的数量减少了,在算子函数使用到的外部变量,肯定在传输的时候需要序列化,持久化RDD时进行序列化、StorgeLevel.memory_only_ser、shuffle需要用到序列化
6、数据本地性:进程本地化、节点本地化、No_pref(从那里获取数据都一样,没有好坏)、机架本地化、any(调节数据本地化的等待时长(反复调试))——运行界别提高了,不代表整体作业运行时间变短了(等待时间变长了)spark.locality.wait.process(3s)
7、使用高性能的库-fastutil——快速存取及低内存占用,同时也提供一组快速的API用来读写文本和二进制文件
8、JVM调优(java虚拟机):如果硬件配置、基础的JVM配没问题,JVM不会造成太严重的性能问题,减低cache占比,scala也是运行在Java虚拟机中,堆内存分为年轻带和老年带(old generation),年轻带分为Eden(区域比较大)、survivor两个(占比8:1:1),int i=3(栈内存),new(堆内存),每次放对象,都放入eden和survivor一个,然后进行gc垃圾回收,存活下来的放入s2,放不下,放入old generation(或者JVM内存不够大,频繁的导致年轻带内存满溢,频繁的进行minor gc,导致短时间内有些存活的对象,对此垃圾回收没有回收掉,反复调用,调用一次就增加一次放入老年代,同时gc不会负责老年代的垃圾回收),如果老年代囤积大量活跃对象,频繁满溢的话,会触发minor gc,频繁的full gc,会频繁的卡机——Stop the world——Spark中堆内存分为两块,一块是专门用来给RDD的cache和persist进行RDD数据缓存,另一个快是给SPark的算子函数的运行使用的——给RDD cache操作的内存占比是0.6,在某些情况下,cache不是那么紧张,问题在于task算子函数中创建的对象过多,然后内存又不太大,导致了频繁的minor gc,甚至频繁的full gc,导致spark频繁停止工作,性能影响很大,如果不需要创建许多对象的话就需要将cache的占比调小
9、shuffle调优:任何关于shuffle的调优,都很重要,reduce端使用HashMap进行内存缓冲,控制内存缓冲,map端内存缓冲,reduce端内存占比,缓冲区大小32KB,一个reduceTask一个32KB的缓冲区,溢写次数变多,所以应该将缓冲区的大小成倍的增加调试,reduce端需要不断地拉取数据,进行汇总,cache占比0.6,shuffleReduce端占比0.2,计算占用0.2,map:buffer reducer:memoryFraction——合并map端输出文件
spark中的shuffle:基于Hash、基于sort(自带consolidateFiles-默认的shufflemanager)、第三种与sort的逻辑一样 (tungstenh-sort底层进行了优化,自己的一套内存管理机制,性能有了很大的提升)reduce task 数量小于等于200,默认是200,不会发生排序,大于200则发生排序
10、算子调优:——比较重要
11、堆外内存:executor堆外内存,spark底层shuffle使用netty传输,使用了堆外内存,堆外内存不足,会导致executor挂掉,整个spark作业崩溃(或者内存溢出),默认情况下,堆外内存上限是384MB,调节等待时长,spark里面默认的网络连接的常识等待时长:60s

你可能感兴趣的:(Big,Data)