Spark优化分析

1. 资源优化

1). 集群搭建: 

master节点的..../conf/spark-env.sh中配置:
SPARK_WORKER_CORES
SPARK_WORKER_MEMORY

 2). 任务提交中设置参数

./spark-submit --master spark://node 001:7077 --class ... jar ...
--executor-cores
--executor-memory
--driver-cores
--driver-memory
--total-executor-cores


2. 并行度调节

1). sc.textFile("filePath" , numparttition)  --java/scala


2). sc.parallelize(list,numparttition) //parallelize()函数将一个List列表转化为了一个RDD对象
--java/scala


3). sc.makeRDD(list , numparttition)  //makeRDD函数实现是依赖了parallelize函数的实现
--scala


4). sc.parallelizePairs(list , nump) //jiang--java


5). rdd.repartition(num)/rdd.coalesce(num)


6). rdd.reduceByKey(xx , num)/rdd.groupByKey(xx,num)


7).spark.default.parallelism


8).自定义分区器


9).spark.sql.shuffle.partitions = 200


10).SparkStreaming:
     Direct:topic中partiton个数一致,增大topic的分区数|读取dstream 进行重新分区

3. 代码优化


1). 尽量避免创建重复的RDD
RDD根本是一个数据集,需要从外部数据源中获取,创建多个RDD就会从相同的数据源中进行 , 多次读取,这对集群来说是一种资源的浪费, 在编程中应该尽可能服用一个RDD. 

 

2).  对多次使用的RDD进行持久化
对多次使用的RDD进行一个持久化的操作(persist()), 这样减少对RDD的重复计算,提高效率 . Saprk对于执行多算子默认原理为,每次多一个RDD执行一个算子操作时, 都会从源头处计算一遍, 计算出那个RDD来,然后再对这个RDD执行你的算子操作。这种方式的性能是很差的。我们可以保留一个中间状态,使得RDD不必做一些重复而无用的操作。
cache() -- MEMORY_ONLY  = persist() = persist(MEMORY_ONLY)
persist() -- MEMORY_ONLY | MEMORY_ONLY_SER | MEMORY_AND_DISK | MEMORY_AND_DISK_SER


3). 广播大变量
当Executor端使用到Driver端的大变量时, 是将这个大变量的副本通过网路I/O传输 到每一个运行这个程序上的task上.如果这个变量足够大, 在网络I/O上消耗的时间也是十分可观的, 而且还需要占用很多的储存空间. 针对这种“大”的外部变量(100M,甚至1G),我们可以将变量广播,使这个变量的副本只存在于每个Executer中,这样就大大减少了变量的副本数,大大的提升了效率。
val list1 = ...
val list1Broadcast = sc.broadcast(list1)
rdd1.map(list1Broadcast...)


4). 尽量少用collect() 数据量比较大的时候,尽量不要使用collect函数,因为这可能导致Driver端内存溢出问题。

 

5). Map join代替 reduce join 
mapjoin的并行度高 , 可以有效的避免数据倾斜 , 就相当于使用广播变量+filter 代替join ;
mapjoin需要一个表所有数据加载到缓存中,不能太大

 

6). 尽量使用map端有预聚合的的算子
好处: 减少shuffle的数据量 , 减少数据拉取量 , 减少reduce端的聚合次数 . 
预聚合算子: reduceByKey() , combineByKey() , aggregateByKey() 


7). 使用高性能算子
使用reduceByKey代替groupByKey
使用mapPartitions代替map
使用foreachPartition代替foreach
对RDD使用filter进行大量数据过滤后 , 使用coalesce减少分区
使用map端与聚合和算子

 

8). 数据结构
(1). 尽量使用原生数据类型代替字符串类型,每个java对象都有对象头 , 引用等额外信息 , 因此比较占用内存空间 . 
(2). 尽量使用字符串代替对象 , 每个字符串内部都有一个字符串数组以及长度等额外信息 . 
(3). 尽量用数组代替集合 . 集合类型,比如HashMap、LinkedList等,因为集合类型内部通常会使用一些内部类来封装集合元素,比如Map.Entry。


9). 使用kryo 序列化: 节省内存资源
 SparkSession.config("spark.serializer" , "org.apache.spark.serializer.KryoSerializer")
或者 Sparkconf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
                .registerKryoClasses(new Class[]{SpeedSortKey.class})

4. 数据本地化: 
 

PROCESS_LOCAL        进程本地化
NODE_LOCAL            节点本地化
NO_PREF             数据从哪里获取都一样
RACK_LOCAL        机架本地化
ANY                    出机架

数据本地化调节:
    spark.locality.wait.node 3s
    spark.locality.wait.process 3s
    spark.locality.wait.rack 3s

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值