Spark-Core性能优化总结

性能优化概览

why

Spark是基于内存的计算,所以集群的CPU、网络带宽、内存等都可能成为性能的瓶颈。

when

Spark应用开发成熟时,满足业务要求后,就可以开展性能优化了。

what

一般来说,Spark应用程序80%的优化集中在内存、磁盘IO、网络IO,即Driver、Executor的内存、shuffle的设置、文件系统的配置,集群的搭建,集群和文件系统的搭建(文件系统的集群在同一个局域网内)。

how

web UI+log是Spark性能优化的倚天剑和屠龙刀。
driver的log信息大致如“INFO BlockManagerMasterActor: Added rdd_0_1 in memory on mbk.local:50311 (size: 717.5 KB, free: 332.3 MB)”的日志信息。这就显示了每个partition占用了多少内存。

内存都去哪了

Java对象头

每个Java对象,都有一个对象头,会占用16个字节,主要是包括了一些对象的元信息,比如指向它的类的指针。如果一个对象本身很小,比如就包括了一个int类型的field,那么它的对象头实际上比对象自己还要大。

String对象

Java的String对象会比它内部的原始数据多出40个字节。因为它内部使用char数组来保存内部的字符序列的,并且还得保存诸如数组长度之类的信息;而且String使用的是UTF-16编码,每个字符会占用2个字节。比如,包含10个字符的String,会占用60个字节。

集合类型

Java中的集合类型,比如HashMap和LinkedList,内部使用的是链表数据结构,所以对链表中的每一个数据,都使用了Entry对象来包装。Entry对象不光有对象头,还有指向下一个Entry的指针,通常占用8个字节。

其他

元素类型为原始数据类型(比如int)的集合,内部通常会使用原始数据类型的包装类型,比如Integer,来存储元素。
List<Integer> list = new ArrayList<Integer>()

性能优化方法

数据序列化

Spark默认序列化机制

Spark自身对于序列化的便捷性和性能进行了一个取舍和权衡。默认,Spark倾向于序列化的便捷性,使用了Java自身提供的序列化机制——基于ObjectInputStream和ObjectOutputStream的序列化机制。

Java序列化机制的缺陷

Java序列化机制的性能并不高,序列化的速度相对较慢;而且序列化以后的数据,还是相对来说比较大,还是比较占用内存空间。

Kryo序列化机制

Spark也支持使用Kryo类库来进行序列化。Kryo序列化机制比Java序列化机制更快,而且序列化后的数据占用的空间更小,通常比Java序列化的数据占用的空间要小10倍。SparkConf().set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")

Kryo使用场景

算子函数使用到了外部的大数据的情况。
比如自定义了一个MyConfiguration对象,里面包含了100m的数据。然后,在算子函数里面,使用到了这个外部的大对象。
conf.registerKryoClasses(XXX.class)

优化Kryo缓存大小

如果注册的要序列化的自定义的类型,本身特别大,就需要调整Kryo缓存的大小,默认值是2M。SparkConf.set(“spark.kryoserializer.buffer.mb”,nM)。

数据结构优化

场景

算子中用到的内部和外部的数据,优化之后,会减少内存的消耗和占用。

优先使用数组以及字符串而不是集合类

比如将

List<Integer> list = new ArrayList<Integer>()

替换为

int[] arr = new int[]

这样array既比List少了额外信息的存储开销,还能使用原始数据类型(int)来存储数据,要节省内存的多。

Map<Integer, Person> persons = new HashMap<Integer, Person>()

优化为特殊的字符串格式

id:name,address|id:name,address...。

避免使用多层嵌套的对象结构

public class Teacher { 
  private List<Student> students = new ArrayList<Student>() 
}

就是非常不好的例子。因为Teacher类的内部又嵌套了大量的小Student对象。优化为json字符串来存储数据

{
    "teacherId": 1, 
    "teacherName": "leo", 
    students:[
            {"studentId": 1, "studentName":"tom"},
            {"studentId":2, "studentName":"marry"}
        ]
}

尽量使用int替代String

如用int行ID替代UUID等。

RDD持久化

持久化的场景

对RDD反复使用和重要的、关键的、耗时长的RDD。

持久化方法

使用cache()|persist()方法进行持久化,使用unpersist()方法取消持久化。

持久化策略

Spark提供的多种持久化级别,主要是为了在CPU和内存消耗之间进行取舍。优先使用MEMORY_ONLY,内存不足时使用MEMORY_ONLY_SER。

注意事项

JavaRDD<String> targetwords = words.filter(new Function<String, Boolean>() {}).cache();

不应该是

JavaRDD<String> targetwords = words.filter(new Function<String, Boolean>() {});
targetwords.cache();

Spark自己也会在shuffle操作时进行数的持久化,主要是为了在节点失败时避免重算整个过程。

提高并行度

Spark集群的资源并不一定会被充分利用到,所以要尽量设置合理的并行度,来充分地利用集群的资源,以充分提高Spark应用程序的性能。

Spark会自动设置以文件作为输入源的RDD的并行度,依据其大小,比如HDFS,就会给每一个block创建一个partition,也依据这个设置并行度。对于reduceByKey等会发生shuffle的操作,就使用并行度最大的父RDD的并行度即可。

手动使用textFile()、parallelize()等方法的第二个参数来设置并行度;

使用spark.default.parallelism参数来设置统一的并行度
Spark官方的推荐是,给集群中的每个cpu core设置2~3个task。
比如说,spark-submit设置了executor数量是10个,每个executor要求分配2个core,那么application总共会有20个core。此时可以设置new SparkConf().set("spark.default.parallelism", "60")
来设置合理的并行度,从而充分利用资源。

广播共享数据

优化前

默认情况下,算子函数使用到的外部数据,会被拷贝到每个task中,如果使用到的外部数据很大,那么就会占用大量的内存空间和网络传输。

Paste_Image.png

优化后

外部数据在每个节点上只保留一份副本,大大节省了内存和网络传输。

Paste_Image.png

广播共享数据的用户

创建广播变量

...
Broadcast<T> broadcast = sc.broadcast(T);
...

使用广播变量

...
broadcast.value();
...

数据本地化

数据本地化对性能的影响

数据本地化对于Spark Job性能有着巨大的影响,如果数据与要计算它的代码是在一起的,那么性能当然会非常高。Spark倾向于使用最好的本地化级别来调度task,如果没有任何未处理的数据在空闲的executor上,那么Spark就会放低本地化级别。这时有两个选择:等待直到executor上的cpu释放出来,那么就分配task过去或者立即在任意一个executor上启动一个task。

数据本地化级别

PROCESS_LOCAL:数据和计算它的代码在同一个JVM进程中。

NODE_LOCAL:数据和计算它的代码在一个节点上,但是不在一个进程中;

NO_PREF:数据从哪里过来,性能都是一样的。

RACK_LOCAL:数据和计算它的代码在一个机架上。

ANY:数据可能在任意地方,比如其他网络环境内,或者其他机架上。

优化参数

spark.locality.wait(3000毫秒)

spark.locality.wait.node

spark.locality.wait.process

spark.locality.wait.rack

reduceByKey和groupByKey优化

如果能用reduceByKey,那就用reduceByKey,因为它会在map端,先进行本地combine,可以大大减少要传输到reduce端的数据量,减小网络传输的开销。
只有在reduceByKey处理不了时,才用groupByKey().map()来替代。

JVN垃圾回收调优

GC对性能的影响

默认情况下,Executor的内存空间60%用于RDD的缓存,40%分配给Task用于运行。Task很可能很快就耗光了内存而触发GC。GC发生时将停止一切工作线程,GC本身需要花费时间,如果再频繁发生GC,将严重影响Spark应用程序的性能。

Paste_Image.png

GC 优化

可通过调整比例达到优化GC的目的。

SparkConf().set(“spark.storage.memoryFraction”, “0.5”)

比值在0.6~0.1之间调整。

若配合使用序列化持久化级别如MEMORY_ONLY_SER何kryo等手段,将会有更好的性能优化。

shuffle优化

spark.shuffle.consolidateFiles:是否开启shuffle block file的合并,默认为false

spark.reducer.maxSizeInFlight:reduce task的拉取缓存,默认48m

spark.shuffle.file.buffer:map task的写磁盘缓存,默认32k

spark.shuffle.io.maxRetries:拉取失败的最大重试次数,默认3次

spark.shuffle.io.retryWait:拉取失败的重试间隔,默认5s

spark.shuffle.memoryFraction:用于reduce端聚合的内存比例,默认0.2,超过比例就会溢出到磁盘上

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容

  • 1.1、 分配更多资源 1.1.1、分配哪些资源? Executor的数量 每个Executor所能分配的CPU数...
    miss幸运阅读 3,139评论 3 15
  • 1、 性能调优 1.1、 分配更多资源 1.1.1、分配哪些资源? Executor的数量 每个Executor所...
    Frank_8942阅读 4,465评论 2 36
  • 前言 在大数据计算领域,Spark已经成为了越来越流行、越来越受欢迎的计算平台之一。Spark的功能涵盖了大数据领...
    Alukar阅读 542评论 0 6
  • 原文:https://tech.meituan.com/spark-tuning-basic.html Spark...
    code_solve阅读 1,193评论 0 10
  • 明天早上有一个非正式电话会议 午餐前和朋友有个约会 可是我很累却不想睡。 我没有好好吃饭 也没有好好睡觉 更没有好...
    残破的新阅读 402评论 0 0