spark 序列化错误 集群提交时_spark 调优

本文详细介绍了Spark集群的资源优化,包括设置默认参数、动态资源分配及并行度调优。此外,文章还探讨了代码优化策略,如避免创建重复RDD、使用广播变量和优化shuffle操作。在序列化方面,建议使用Kryo优化性能。最后,文章提到了数据本地化、内存管理和解决数据倾斜问题的方法,以及应对Spark序列化错误和集群提交时的故障处理策略。
摘要由CSDN通过智能技术生成

一、资源优化1.在部署spark集群中指定资源分配的默认参数

在spark安装包的conf下spark-env.sh:

SPARK_WORKER_CORES :worker分配的核数

SPARK_WORKER_MEMORY:worker分配的内存

SPARK_WORKER_INSTANCES:每台机器启动worker数2.提交命令

--executor-cores :每个进程的核数(没有配置,默认把所有核数都分配给它)

--executor-memory:每个进程的内存(默认1G)

--total-executor-cores:所有进程分配的核数

配置信息:(Application的代码中设置或在Spark-default.conf中设置)

spark.executor.cores

spark. executor.memory

spark.max.cores

动态分配资源

spark.shuffle.service.enabled true //启用External shuffle Service服务

spark.shuffle.service.port 7337 //Shuffle Service服务端口,必须和yarn-site中的一致

spark.dynamicAllocation.enabled true //开启动态资源分配

spark.dynamicAllocation.minExecutors 1 //每个Application最小分配的executor数

spark.dynamicAllocation.maxExecutors 30 //每个Application最大并发分配的executor数

spark.dynamicAllocation.schedulerBacklogTimeout 1s

spark.dynamicAllocation.sustainedSchedulerBacklogTimeout 5s二、并行度调优

1) 如果读取的数据在HDFS中,降低block大小,相当于提高了RDD中partition个数

sc.textFile(xx,numPartitions)

2) sc.parallelize(xxx, numPartitions)

3) sc.makeRDD(xxx, numPartitions)

4) sc.parallelizePairs(xxx, numPartitions)

5) repartions/coalesce

6) redecByKey/groupByKey/join ---(xxx, numPartitions)

7) spark.default.parallelism net set

8) spark.sql.shuffle.partitions---200

9) 自定义分区器

10) 如果读取数据是在SparkStreaming中Receiver:

spark.streaming.blockInterval—200ms

Direct:读取的topic的分区数

自定义分区代码:

public class ParTionerTest {

public static void main(String[] args) {

SparkConf sparkConf = new SparkConf().setMaster("local").setAppName("partioner");

JavaSparkContext sc = new JavaSparkContext(sparkConf);

JavaRDD parallelize = sc.parallelize(Arrays.asList(

"a", "a", "b", "c",

"a", "a", "b", "c"),2);

parallelize.mapToPair(new PairFunction() {

@Override

public Tuple2 call(String s) throws Exception {

return new Tuple2<>(s,1);

}

}).reduceByKey(new Partitioner() {

@Override

public int getPartition(Object key) {

if("a".equals(key)){

return 0;

}else if("b".equals(key)){

return 1;

}else{

return 2;

}

}

@Override

public int numPartitions() {

return 3;

}

}, new Function2() {

@Override

public Integer call(Integer v1, Integer v2) throws Exception {

return v1 + v2;

}

}).foreach(new VoidFunction>() {

@Override

public void call(Tuple2 tuple2) throws Exception {

System.out.println(tuple2);

}

});

}

}

结果演示:【由数据读取的2分区更改为3分区】

(a,4)

(b,2)

(c,2)三、代码调优1.避免创建重复的rdd

对于同一份文件,一次读取创建rdd,多次使用。2.对多次使用的rdd进行持久化:

1.memory_only:

默认情况下,性能最高memory_only。前提是内存必须足够大,可以存放下整个rdd所有数据。

因为不进行序列化与反序列化操作,就避免了这部分的性能开销;对这个RDD的后续算子操作,都

是基于纯内存中的数据的操作,不需要从磁盘文件中读取数据,性能也很高;而且不需要复制一份数据

副本,并远程传送到其他节点上。

如果RDD中数据比较多时(比如几十亿),直接用这种持久化级别,会导致JVM的OOM内存溢出异常,

如果使用MEMORY_ONLY级别时发生了内存溢出,那么建议尝试使用MEMORY_ONLY_SER级别。

2.MEMORY_ONLY_SER:

该级别会将RDD数据序列化后再保存在内存中,此时每个partition仅仅是一个字节数组而已,大大

减少了对象数量,并降低了内存占用。

这种级别比MEMORY_ONLY多出来的性能开销,主要就是序列化与反序列化的开销。但是后续算子可以

基于纯内存进行操作,因此性能总体还是比较高的。

如果RDD中的数据量过多的话,还是可能会导致OOM内存溢出的异常。

如果纯内存的级别都无法使用,那么建议使用MEMORY_AND_DISK_SER策略,而不是MEMORY_AND_DISK策略

3.MEMORY_AND_DISK_SER:

RDD的数据量很大,内存无法完全放下。序列化后的数据比较少,可以节省内存和磁盘的空间开销。

同时该策略会优先尽量尝试将数据缓存在内存中,内存缓存不下才会写入磁盘。

4.DISK_ONLY:

因为完全基于磁盘文件进行数据的读写,会导致性能急剧降低,有时还不如重新计算一次所有RDD。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值