zoukankan      html  css  js  c++  java
  • spark性能优化

    两种序列化机制:

    java和kryo序列化机制;

    那么我们如何优化kryo类库的使用呢?

    1、优化缓存大小

    如果注册的要序列化的自定义的类型,本身就特别大,比如包括了超过100field,那么就会导致要序列化的对象过大,

    此时就需要对kryo本身进行优化,因为kryo内部的缓存可能不够存放那么大的class对象,此时就需要调用SparkConf.set()方法,

    设置spark.kryoserializer.buffer.mb参数的值,将其调大;

    2、预先注册自定义类型

    不进行注册自定义类型,kryo类库也能正常工作,但是,对于它要序列化的每个对象,都会保存一份它的全限定类名,此时反而

    会耗费大量内存,因此通常都建议预先注册好要序列化的自定义的类;

    那么我们在什么场景下使用kryo序列化类库呢?

    在算子函数使用到了外部的大数据的情况,举例就是我们在外部定义了一个封装了应用了所有配置的对象,比如自定义了一个

    MyConfiguration对象,里面包含了100m的数据,之后在算子函数里面使用到了这个外部的大对象;

    那么我们去如何优化数据结构?

    1、优先使用数组以及字符串,而不是集合类,换言之,就是优先用array,而不是

    ArrayList、LinkedList、HashMap集合;

    2、避免使用多层嵌套的对象结构,举例:

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

    3、对于有些能够避免的场景,尽量使用int替代String,因为String虽然比ArrayList、

    HashMap等数据结构高效多了,占用内存量少多了,注意! 在spark应用中,id就不要用

    常用的uuid了,因为无法转成int,就用自增int类型id即可;

    对多次使用的RDD进行持久化或Checkpoint

    若程序中,对某一个RDD,基于它进行了多次transformation或者action操作,那么就有必要对其进行持久化

    操作,从而避免对一个RDD反复进行计算,另外,如果要保证在RDD的持久化数据可能丢失的情况下,

    还要保证高性能,那么可以对RDD进行Checkponit操作;

    接着使用序列化的持久化 :

    除了上一步优化之外,还可以利用序列化的持久化优化其性能,比如MORY_ONLY_SER、MEMORY_AND_SER等;

    使用RDD.persist(StorageLevel.MEMORY_ONLY_SER)这样的语法;如此一来,将数据序列化之后,再持久化,可以大大

    减少对内存的消耗,此外,数据量小了以后,如果要写入磁盘,那么磁盘IO性能消耗也较小;对RDD持久化序列化后,RDD的每个

    parttion的数据,都是序列化为一个巨大的字节数组,这样会减少内存的消耗,但有一个缺点就是,获取RDD数据时,需要对其进行反序列化,

    会增大其性能开销;

    因此,对于序列化的持久化级别,还可以进一步优化,也就是说,使用Kryo序列化类库,这样可以获得更快的序列化速度,并占用更小的内存空间,】

    但是注意,如果RDD的元素(RDD<T>的泛型类型)是自定义类型的话,在Kryo中提前注册自定义类型;

    什么是Java虚拟机垃圾回收调优机制?

     

     如何提高并行度?

    实际上spark集群的资源并不一定会被充分利用,所以要尽量设置合理的并行度,来充分地利用集群的资源;

    才能充分提高spark程序的性能;

    spark会自动设置一文件作为输入源的RDD并行度,依据其大小,例如HDFS,就会给每个block创建一个partition,

    也依据这个设置并行度,对于reduceByKey等会发生的shuffle的操作,就使用并行度最大的父RDD的并行度即可;

    然后也可以手动使用textFile()、parallelize()等方法的第二个参数来设置并行度,也可以使用spark.default.

    parallelism参数,来设置统一的并行度,Spark官方的推荐是,给集群中的每个cpu core设置2-3个task;

    什么是广播共享数据原理?

    若你的算子函数中,使用到了特别大的数据,那么这个时候,推荐将该数据进行广播,这样的话,就不至于

    将一个大数据拷贝到每一个task上去,而是给每一个节点拷贝一份,然后节点的task共享该数据;

    这样就可以减少大数据在节点上的内存消耗,并可以减少数据到节点的网络传输消耗;

    什么是数据本地化?

     spark倾向于使用最好的本地化级别来调度task,但这无可能,如果没有任何未处理的数据在空闲的executor上,

    那么spark就会放低本地化级别,这是有两个选择,第一,等待,直到executor上的cpu释放出来,那么就分配

    task过去,第二,立即在任意一个executor上启动一个task;

    spark默认会等待一会儿,来期望task要处理的数据所在的节点上的executor空闲出一个cpu,从而将task分配过去,

    只要超过了时间,那么spark就会将task分配到其他任意一个空间的executor上;

    原理图:

  • 相关阅读:
    CSS不常见问题汇总
    Android 学习 查询数据库
    c#判断QQ是否在线
    Log图文详解(Log.v,Log.d,Log.i,Log.w,Log.e)的用法
    android之uses-permission
    Android特效 五种Toast详解
    Android用Intent启动Activity的方法
    View的setOnClickListener的添加方法
    Handler
    在Android中使用 Google ZXing 实现二维码、条形码扫描
  • 原文地址:https://www.cnblogs.com/zhzJAVA11/p/10483520.html
Copyright © 2011-2022 走看看