spark优化和故障排除

 

http://spark.apache.org/docs/1.6.2/tuning.html

http://blog.csdn.net/anzhsoft/article/details/42417533

 

1、算子优化、filter  + coalecse

filter不进行重新分区,coalecse是进行重新分区的算子   

数据在经过过滤后在不同的分区上存在数据倾斜问题,需要进行重新分区

repartition 和coalecse的区别

coalecse  是用来减少分区的shuffle= false  ;   repartition是用来增加分区的默认的shuffle= true

 

2、foreachpartation

foreach  和foreachpartation

map  和  mapPartation

map--》一条数据一条数据处理

mapPartation  一个一个分区处理

foreach 和foreachPartation  和上面的类似  ,foreachPartation  是将数据拿到一个节点上计算有可能存在内存溢出的问

 

3、reduce和reduceByKey  reduceByKey  自带map端的combiner

 

并行度、分区 : 从文件中读取数据、创建数据、分区数

 

1、放参数、决定分区数  设置  spark.default.parallelism  默认分区个数:官方推荐默认是cpu个数的2--3倍,这个配置对于读取文件是不生效的,读取的文件是按照文件block分区的,要使用repartation进行重新分区;

sparksql的分区默认是200   不受spark.default.parallelism的设置  spark.sql.shuffle.partations=200

 

可以在spark-submit  后加参数

 

0814、性能调优

第一课、rdd持久化、广播变量持久化、序列化

1、RDD的持久化,用完之后要释放unpersist

2、广播大的变量,Broadcast

 

reduce和reduceByKey  reduceByKey  自带map端的combiner

 

final Broadcast<Map<String, Map<String, IntList>>> dateHourExtractMapBroadcast =

    sc.broadcast(fastutilDateHourExtractMap);

默认情况下,task执行的算子中,使用了外部的变量,每个task都会获取一份变量的副本,要网络通信,或网卡流量积针

广播变量,初始的时候,就在Drvier上有一份副本。

task在运行的时候,想要使用广播变量中的数据,此时首先会在自己本地的Executor对应的BlockManager中,

尝试获取变量副本;如果本地没有,那么就从Driver远程拉取变量副本,并保存在本地的BlockManager中;

此后这个executor上的task,都会直接使用本地的BlockManager中的副本。

executor的BlockManager除了从driver上拉取,也可能从其他节点的BlockManager上拉取变量副本,

距离越近越好。

3、序列化、kryo序列化,spark默认的序列化是java序列化,kryo序列化是java序列化的2-10倍,减少序列化对象的数据量

conf.set(" spark.serializer","org.apache.spark.serializer.KryoSerializer")

或者

.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")

.registerKryoClasses(new Class[]{CategorySortKey.class})

 

第二课、

1、数据本地性,优先计算本节点数据

进程本地化:PROCESS_LOCAL:进程本地化,代码和数据在同一个进程中,也就是在同一个executor中;

节点本地化:NODE_LOCAL:节点本地化,代码和数据在同一个节点中;

机架:RACK_LOCAL:机架本地化,数据和task在一个机架的两个节点上;

ANY:数据和task可能在集群中的任何地方,而且不在一个机架中,性能最差

 

这个东西是调节不了的,和数据分布任务分派有关

配置:spark.locality.wait,默认是3s ,尽量数据本地化时间

new SparkConf()

  .set("spark.locality.wait", "10")

 

2、使用高性能的库fastutil

fastutil是扩展了Java标准集合框架(Map、List、Set;HashMap、ArrayList、HashSet)的类库,

提供了特殊类型的map、set、list和queue;

 

fastutil能够提供更小的内存占用,更快的存取速度;我们使用fastutil提供的集合类,

来替代自己平时使用的JDK的原生的Map、List、Set,好处在于,fastutil集合类,可以减小内存的占用,

并且在进行集合的遍历、根据索引(或者key)获取元素的值和设置元素的值的时候,提供更快的存取速度;

 

3、java虚拟机的调优

spark.storage.memoryFraction,0.6(默认) -> 0.5 -> 0.4 -> 0.2   用来给cache的内存,剩下的spark跑程序的内存和总的内存占比

 

第三课、优化

 

shuffe优化是一对多的优化,而一对一、和多对一是逻辑上数据放在一起了。

 

堆外内存:java虚拟机以外的内存   ----》spark底层shuffle使用netty传输,所以使用了堆外内存!1.2之前是NIO就是socket,之后默认使用netty

 

有时候,如果你的spark作业处理的数据量特别特别大,几亿数据量;然后spark作业一运行,时不时的报错,由于底层通信传输数据的内存不够

shuffle file cannot find,executor、task lost,out of memory(内存溢出);

 

调整堆外内存:

conf spark.yarn.executor.memoryOverhead=2048(两个g)

--conf spark.core.connection.ack.wait.timeout=300  (调整通信等待时长,默认300毫秒)

 

处于垃圾回收过程中,所有的工作线程全部停止;相当于只要一旦进行垃圾回收,

spark / executor停止工作,无法提供响应

 

此时呢,就会没有响应,无法建立网络连接;会卡住;ok,spark默认的网络连接的超时时长,是60s;

如果卡住60s都无法建立连接的话,那么就宣告失败了。

 

碰到一种情况,

uuid(dsfsfd-2342vs--sdf--sdfsd)。not found。file lost。

这种情况下,很有可能是有那份数据的executor在jvm gc。所以拉取数据的时候,建立不了连接。

然后超过默认60s以后,直接宣告失败。

 

报错几次,几次都拉取不到数据的话,可能会导致spark作业的崩溃。也可能会导致DAGScheduler,

反复提交几次stage。TaskScheduler,反复提交几次task。大大延长我们的spark作业的运行时间。

可以考虑调节连接的超时时长。

--conf spark.core.connection.ack.wait.timeout=300

spark-submit脚本,切记,不是在new SparkConf().set()这种方式来设置的。

spark.core.connection.ack.wait.timeout(spark core,connection,连接,ack,wait timeout,

建立不上连接的时候,超时等待时长)

spark中shuffle的种类

hash:HashShuffleManager

sort:SortShuffleManager

tungsten-sort:UnsafeShuffleManager

默认是sort

spark.shuffle.manager hash M*R 个小文件

spark.shuffle.manager sort

conf.set("spark.shuffle.manager","hash");

 

hash-based 的洗牌方式要配置:不进行排序的洗牌

new SparkConf().set("spark.shuffle.consolidateFiles", "true")

开启shuffle map端输出文件合并的机制,按照cpu core合并;默认情况下,是不开启的,就是会发生如上所述的大量map端输出文件的操作,严重影响性能。

注:如果不开启文件合并的功能,就会形成海量数据传输问题,上游task数*  下游task数  例如1000*1000  =1000000,开启了文件合并,一个cup core  产生一个文件

 

sort-based  的洗牌自动进行文件的合并:进行排序的洗白,默认使用

第四课、

1、shuffle map端内存缓冲reduce端内存占比

 

spark.shuffle.file.buffer,默认32k  :map缓存数据的大小

spark.shuffle.memoryFraction,0.2:reduce端的缓存数据占用excutor内存的占比

 

2、解决算子函数返回null导致的问题

对null做特殊标记,之后再进行判断

3、shuffle file  not  found 错误解决

spark.shuffle.io.maxRetries  3  拉去文件的次数

spark.shuffle.io.retryWait   5s  拉取文件间隔时间

 

4、troubleshooting   shuffle  reduce 端缓冲大小以避免OOM(内存溢出 ,不是因为reduce端拉取数据拉多了,而是reduce端在计算的时候还要占内存所有内存溢出了)

 

(MapReduce)reduce端默认buffer大小是48MB,spark的shuffle和MR的shuffle绝对是不一样的!!!

减少reduce的缓存占比大小,可以减小reduce端拉取数据的速度

 

spark.reducer.maxSizeInFlight,48  还可以增大reduce的计算内存大小

 

 

5、troubleshooting 错误的持久化方式以及checkpoint的使用

userrdd=userrdd.cache()   使用这种方式缓存数据

 

第五课、

 

 

1、yarnclient可能会存在网卡流量激增的问题

 

2、troubleshooting   解决yarn-cluster模式的JVM栈内存溢出(永久带内存溢出)

yarn-client默认永久带内存128M;yarn-cluster默认永久带内存82M

在spark-submit的脚步中配置:

永久带内存配置为128M,最大为  256M

--conf   spark.driver.extraJavaOptions="-XX:PermSize=128M -XX:MaxPermSize=256M"

 

3、什么是数据倾斜

任务分配不均匀;

数据倾斜的表现:spark,可以通过页面查看,hive可以看日志,产生时一般伴随shuffe

 

第六课、数据倾斜的解决方案

第一个方案:聚合源数据

通过hive对源数据进行提前处理,保证数据没有倾斜

第二个方案:过滤导致倾斜的key

怎样知道哪些key会导致倾斜呢???  --》随机取一部分看哪些key可以导致数据倾斜

将导致倾斜的key过滤掉,如果不是脏数据,把这个key的数据单独处理

 

第三个方案:提高shuffle操作的reduce的并行度

 

spark_home/conf/spark-default.conf

spark.default.parallelism

 

解决数据倾斜:

A方案:使用随机key实现双重聚合

这个需要进行二次处理的。

步骤一:使用随机key实现双重聚合

步骤二:执行第一轮聚不聚和

步骤三:去掉每个key的前缀

步骤四:最后第二轮全局聚合

 

B方案:将reduce join转换为map join

大文件和小文件进行reduce操作时将小文件广播出去;在mapreduce中使用distrubutedcache

=================================

DistributedCache.addCacheFile(new URI("hdfs://1.1.2.1:9000/user/1M_A/Atest.txt"), comW.getConfiguration());

至此,你已经告诉了hadoop你有个缓存文件叫Atest.txt

然后在map端的setup()函数中:

//从分布式缓存中读取矩阵A

//注意:此处使用的是getCacheFiles(),我不明白网上很多人为什么使用getLocalCacheFile,费解

URI[] caches = DistributedCache.getCacheFiles(con.getConfiguration());

//然后就是正常的输入

FileSystem fs = FileSystem.get(caches[0] , con.getConfiguration());

InputStream in = fs.open(new Path(caches[0]));

Scanner input_A = new Scanner(in);

Atest = input_A.next();

=======================================

spark中使用   broadcast

 

C方案:sample采用倾斜key单独进行join

 

D方案:使用随机数以及扩容表进行join

 

flatmap数据之后,将每条数据的key加上一个随机数

就是将key打撒 和使用随机数差不多

 

 

1、总结spark调优

rdd持久化、广播变量持久化、序列化

数据本地性,优先计算本节点数据

java虚拟机的调优

 

使用高性能的库fastutil

2、总结spark常见的异常处理

3、总结spark总结spark数据倾斜的解决方法

 

 

 

转载于:https://my.oschina.net/captainliu/blog/787070

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值