一、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();
企业级Spark调优解决方案(三)之广播大变量
猜你喜欢
转载自blog.csdn.net/xcvbxv01/article/details/86555227
今日推荐
周排行