提出问题
有一个 变量 是 大数组,名字是: BigArr ,数据量很大,需要占用 1G 内存。
如果每个节点有 两个task,那么 每个task 就有一个 BigArr,那么 每个节点 就会有 2个 BigArr,占用 2G内存
如下图:
分析
如果程序 只是对 BigArr 进行 读操作,而 不进行修改操作,那么 一个 节点 的 多个 task 可以共用 一个BigArr
否则:占用内存太大了,而且是没有必要的
解决
使用 broadcast() 广播
broadcast() 广播
上游 每一个数据,都会分发给下游 所有分区
一句话理解
公共的共享变量,把数据集广播出去,在不同的 task 上都能够获取到,每个节点上只会存在一份。
注意:不应该修改广播变量,这样才能确保每个节点获取到的值都是一致的。
解决上面问题
应用场景
规则或配置更新:当有新的业务规则或配置需要实时推送到所有计算节点时,可以使用广播流来高效地分发这些变化。
维表关联:在流处理中,有时需要将流数据与维度表(通常是相对静态的大表)进行关联。广播流可以用来广播维度表数据到所有任务,实现类似于数据库join的操作,而无需每个事件都查询外部系统。
事件驱动的应用:在事件驱动架构中,全局事件(如系统状态变更通知)可以通过广播流发送,确保所有相关组件都能及时响应。
案例
数据流,经过下面处理:
执行
map()算子,传入RichMapFunction对象,将 任务索引 和 原数据 组装,然后打印结果。
通过结果看出:同一个数据只会进入下游的某一个任务中执行
broadcast()广播后,在执行map()算子,传入RichMapFunction对象,将 任务索引 和 原数据 组装,然后打印结果。
通过结果看出:广播后,同一个数据会进入下游的每一个任务中
生成可视化图
访问:https://flink.apache.org/visualizer/
package chongfenqu;
import org.apache.flink.api.common.functions.RichMapFunction;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
public class F11broadcast {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// 设置并行度是2
env.setParallelism(2);
DataStreamSource<String> dss = env.fromElements("lilei", "lili", "lucy", "hanmeimei");
// 普通算子,与下面广播做对比
DataStream<Tuple2<Integer,String>> mapDS = dss.map(new RichMapFunction<String, Tuple2<Integer,String>>() {
@Override
public Tuple2<Integer, String> map(String s) throws Exception {
return Tuple2.of(getRuntimeContext().getIndexOfThisSubtask(),s);
}
});
mapDS.print("mapDS::");
DataStream<Tuple2<Integer,String>> broadcastDS = dss
.broadcast()// 广播
.map(new RichMapFunction<String, Tuple2<Integer,String>>() {
@Override
public Tuple2<Integer, String> map(String s) throws Exception {
return Tuple2.of(getRuntimeContext().getIndexOfThisSubtask(),s);
}
});
broadcastDS.print("broadcastDS::");
System.out.println(env.getExecutionPlan());
env.execute();
}
}
执行结果
mapDS:::1> (0,lilei)
broadcastDS:::1> (0,lilei)
mapDS:::1> (0,lucy)
mapDS:::2> (1,lili)
broadcastDS:::2> (1,lilei)
mapDS:::2> (1,hanmeimei)
broadcastDS:::2> (1,lili)
broadcastDS:::1> (0,lili)
broadcastDS:::2> (1,lucy)
broadcastDS:::1> (0,lucy)
broadcastDS:::2> (1,hanmeimei)
broadcastDS:::1> (0,hanmeimei)
可以看到:
普通算子 mapDS::::
将 数据
lilei、lucy发送到 0号分区将 数据
lili、hanmeimei发送到 1号分区
广播算子 broadcastDS::::
将 所有数据,发送到 所有分区
参考
https://blog.51cto.com/u_9928699/5670559
https://juejin.cn/post/7386873708600180786



