Spark性能优化-------开发调优
Spark源码解析
转载:
http://blog.sina.com.cn/s/articlelist\_2628346427\_2\_1.html
http://blog.sina.com.cn/s/blog\_9ca9623b0102webd.html
Spark性能优化———-开发调优
转载 2016-05-15 12:58:17
开发调优,知道Spark基本开发原则,包括:RDD lineage设计,算子的合理使用,特殊操作的优化等。
原则一:不要对同一份数据重复创建RDD。
原则二:尽量复用同一个RDD。
原则三:对多次使用的RDD进行持久化
对多次使用的RDD进行持久化,此时Spark就会根据你的持久化测量,将RDD的数据保存到内存或磁盘中。
Spark的持久化级别:MEMORY_ONLY、MEMORY_AND_DISK、MEMORY_ONLY_SER、MEMORY_AND_DISK_SER、DISK_ONLY、MEMORY_ONLY_2、MEORY_AND_DISK_2,…
后缀为2的级别,必须将所有数据都复制一份副本,并发送到其他节点,数据复制和网络传输会导致较大的性能开销。除非作业的高可用性的要求,否则不要使用这个级别。
原则四:尽量避免使用shuffle类算子
原则五:使用map-side预聚合的shuffle操作
所谓的map-size预聚合,在每个节点本地对相同的key进行一次聚合操作,类似于MapReduce中的本地combiner。在可能的情况下,使用reduceByKey或者aggregateByKey算子来替代groupByKey算子。groupByKey算子不会进行预聚合。
原则六:使用高性能的算子
使用reduceByKey/aggregateByKey替代groupByKey
使用mapPartitions替代普通map:在函数单次处理一个parition所有的数据,不会出现OOM的情况下,性能要高。
使用foreachPartitions替代foreach:比如写入MySQL,foreachPartitions对于连接池的开销是有益的。
使用filter之后进行coalesce操作:使用coalesce算子,手动减少RDD的partition数量。
使用repartitionAndSortWithinPartitions替代repartition与sort类操作:如果在repartition重分区之后,还要进行排序,建议直接使用repartitionAndSortWithinPartitions算子,可以一边进行重分区的shuffle操作,一边进行排序,shuffle与sort两个操作同时进行。
原则七:广播大变量
算子函数中使用外部变量时,默认情况下,Spark会将变量复制多个副本,通过网络传输到task中,此时每个task都有一个变量副本,大量的变量副本在网络中传输的性能开销,以及在各个节点的Executor中占用过多内存导致的频繁GC,都会极大地影响性能。
对该变量进行广播,保证每个Executor的内存中,只驻留一份变量副本,而Executor中的task执行时共享该Executor中的那份副本。
原则八:使用Kryo优化序列化性能
在Spark中,主要有三个地方涉及到了序列化:
1.在算子函数中使用到外部变量时,该变量会被序列化后进行网络传输。
2.将自定义的类型作为RDD的泛型类型时(比如JavaRDD),所有自定义类型对象,都会进行序列化,因为要求自定义的类必须实现Serializable接口。
3.使用可序列化的持久化策略时(比如MEMORY_ONLY_SER),Spark会将RDD中的每个partition都序列化成一个大的字节数组。
//设置序列化器为KryoSerializero
Conf.set(“spark.serializer”,”org.apache.spark.serializer.KryoSerializer”)
//注册要序列化的自定义类型
conf.registerKryoClasses(Array(classOf[MyClass1],classOf[MyClass2]))
原则九:优化数据结构
Java中,有三种类型比较耗费内存:
1.对象,每个Java对象都有对象头、引用等额外的信息,因此比较占用内存空间。
2.字符串,每个字符串内部都有一个字符数组以及长度等额外信息。
3.集合类型,比如HashMap、LinkedList等,因为集合类型内部通常会使用一些内部类来封装集合元素,比如Map.Entry。
在Spark编码实现中,尽量不要使用上面三种数据结构,尽量使用字符串替代对象,使用原始类型(比如Int,Long)替代字符串,使用数组替代集合类型。
还没有评论,来说两句吧...