spark调优(六):大家好才是真的好——广播变量 原创 精华
春节不停更,此文正在参加「星光计划-春节更帖活动」
大家好,我是怀瑾握瑜,一只大数据萌新,上能code下能teach的全能奶爸,家有两只吞金兽,嘉与嘉
如果您喜欢我的文章,可以[关注⭐]+[点赞👍]+[评论📃],您的三连是我前进的动力,期待与您共同成长~
1. 起因
在进行数据处理时,会经常用到一些中间表,比如DIM表,比如其他数据源的数据。
如果这些数据量很小,直接与大数据做JOIN,会很影响性能。
如果直接解开数据转成对象,这个对象是放在driver中的,executor端直接使用Driver的变量在Executor有多少task就有多少Driver端的变量副本。
所以这里我们就要使用“广播变量”。
2. 什么是广播变量
广播变量允许程序员在每台计算机上缓存只读变量,而不是将其副本与任务一起发送。例如,它们可以为每个节点提供一个大数据集的副本,而不用给每个 task 来传送一个副本。
广播变量只会被发到各个节点一次,应作为只读值处理(修改广播变量的值不会影响到别的节点)。
Spark会使用高效的广播算法来分配广播变量,以降低通信成本。
3. 广播变量示例
如一个数据,转成Map后,每个子任务都需要使用,工作过程大致为:
如把Map转成广播变量时,工作过程大致为:
可以看到广播变量初始的时候就在Drvier上有一份副本,task在运行的时候,想要使用广播变量中的数据,此时首先会在自己本地的Executor对应的BlockManager中,尝试获取变量副本。如果本地没有,那么就从Driver远程拉取变量副本,并保存在本地的BlockManager中,此后这个executor上的task都会直接使用本地的BlockManager中的副本。executor的BlockManager除了从driver上拉取,也可能从其他节点的BlockManager上拉取变量副本,距离越近越好。
4. 实际应用
将查询到的数据转成Map,然后在driver中广播出去,在子任务执行时可以直接获取。
使用broadcast方法声明广播变量,使用getValue方法获取广播变量。
Map<Long, VehicleInfo> vehicleInfoMap = new HashMap<>();
// 声明广播变量
JavaSparkContext jsc = new JavaSparkContext(sparkSession.sparkContext());
Broadcast<Map<Long, VehicleInfo>> vehicleInfoBroadcast = jsc.broadcast(vehicleInfoMap);
rdd.mapPartitions(x->{
// 获取广播变量
Map<Long, VehicleInfo> vehicleInfoMap = vehicleInfoBroadcast.getValue();
});
5. 注意事项
-
广播变量只能在Driver端定义,不能在Executor端定义。
-
不能将一个RDD广播出去,只能将RDD的结果广播出去。
-
在Driver端可以修改广播变量的值,在Executor端无法修改广播变量的值。
结束语
如果您喜欢我的文章,可以[关注⭐]+[点赞👍]+[评论📃],您的三连是我前进的动力,期待与您共同成长~