天天看点

spark性能调优 广播大变量

这种默认的,task执行的算子中,使用了外部的变量,每个task都会获取一份变量的副本,有什么缺点呢?在什么情况下,会出现性能上的恶略的影响呢?

 map本身是不小的,map中存放数据的单位是entry,还有可能会用链表的格式来存放Entry链条,所以map是比较消耗内存的数据格式,

比如map是1M,总共,你前面调优调的都特好,资源给的到位,配合着资源,并行度调节到位,1000个task。大量task的确都在并行运行。

这些task里面都用到了占用1M内存的map,那么首先,map会拷贝1000份副本,通过网络传输到各个task中去,给task使用,总计有1G的数据会通过网络传输,网络传输开销很大

map副本,传输到各个task后是要占用内存的,1个map的确不大,1M;1000个map分布在你的集群中,一下子就耗费掉了1G的内存,对性能有什么影响,不必要的内存消耗和占用,就导致了,你在进行RDD持久化到内存,也许就没法完全在内存中放下,就只能写入磁盘,最后导致后续操作在磁盘IO上消耗性能

你的task在创建的时候,也许会发现堆内存放不下对象,也许就会导致频繁的垃圾回收器的回收,GC。GC的时候,一定会导致工作线程停止,也就是导致spark暂停工作那么一点时间,频繁GC的话,对spark作业的运行的速度会有相当可观的影响。

解决方法:就是用我们的广播变量,将大变量广播

广播变量,在driver上会有一份初始的副本,当task开始跑起来的时候,task从广播变量中拿出这些数据,那么就是一个executor会对应一个BlockManager(负责管理某个Executor对应的内存和磁盘的数据),首先从本地executor中取数据,如果获取不到广播变量,那么BlockManager就到driver中去拉取map的数据,然后存放在自己本地

executor的BlockManager除了从driver上拉取,也可能从其他节点的BlockManager上拉取变量副本,距离越近越好

广播变量的好处:

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

如果用了广播变量,50个executor,50个副本,500M的数据,网络传输,而且不一定都是从Driver传输到每个节点,还可能是就近从最近的节点的executor拉取

广播变量很简单

其实就是sparkContext的broadcast()方法,传入你要广播的变量,即可

使用广播变量的时候,直接使用广播变量的对象的value/getValue()方法都可以

继续阅读