企业级Spark调优解决方案(三)之广播大变量

一、Spark作业分析
---------------------------------------
    1.Spark Application 提交作业,在Driver上运行jar包的进程

    2.比如其中的一个算子是对一个字典表map(100M数据量)中的数据进行过滤操作,划分成10个task[分布式,10个节点上跑]

    3.那么这10个task,都要用到map的数据,只不过会将字典表的数据100M,随机分配到这10个task中进行过滤操作[比如task1分到12M数据,task2分配到20M数据...]

    4.所以,默认情况下,每个task都会拷贝一个map的副本


二、上述每个task都会获取一份变量的副本,有什么缺点呢?
--------------------------------------
    1.首先map是比较消耗内存的出存储方式

    2.其次tasks之间会拷贝副本,100M,拷贝10份,就是1个G的内存,内存的消耗

    3.而且,每个map的拷贝都是通过网络间传输的[不同节点之间],网络传输的消耗

    4.map占用了大量的内存,导致rdd在持久化的时候,内存不够,只能持久化到磁盘中,增大磁盘io的消耗

    5.当JVM发现内存不够用,就会调用GC进行垃圾回收,这样就加大了JVM的开销。而且,GC进行垃圾回收的时候,task线程是停止等待的,频繁的回收,会浪费时间


三、这种大变量,怎么解决呢?
----------------------------------------
    1.广播变量,将大变量广播出去,而不是直接使用

    2.将上述map做成广播变量之后,会在Driver上会存一份初始的副本。

    3.每个Excutor会有一个BlockManager,负责管理改Excutor对应的那部分内存和磁盘上的数据

    4.每个task会去自己的Excutor的BlockManager上去找对应的map,如果发现自己的excutor上没有map数据,那么BlockManager就会去Driver上拉去数据,并缓存下来

    5.当同一个excutor的下一个task也要使用map变量,发现blockmanager上已经有map数据了,就不再去拉去map数据了


四、注意
-------------------------------------------
    1.BlockManager,也许会从远程的Driver上面去获取变量副本;也有可能从距离比较近的其他节点的Executor的BlockManager上去获取。就近原则

    2.广播变量的好处,不是每个task一份变量副本,而是变成每个节点的executor才一份副本。这样的话,就可以让变量产生的副本大大减少。


五、如何设置?
---------------------------------------------
    1.生成广播变量
        //dateHourExtractMap数据生成完毕,开始广播sc = JavaSparkContext
        final Broadcast<Map<String, Map<String, List<Integer>>>> dateHourCountMapBroadcast =
                sc.broadcast(dateHourExtractMap);

    2.使用广播变量
        //通过广播变量获取map的值
        Map<String, Map<String, List<Integer>>> dateHourExtractMap
                = dateHourCountMapBroadcast.value();




猜你喜欢

转载自blog.csdn.net/xcvbxv01/article/details/86555227
今日推荐