l把元素广播给所有的分区,数据会被重复处理
•类似于storm中的allGrouping
•dataStream.broadcast()
l广播变量允许编程人员在每台机器上保持1个只读的缓存变量,而不是传送变量的副本给tasks
l广播变量创建后,它可以运行在集群中的任何function上,而不需要多次传递给集群节点。另外需要记住,不应该修改广播变量,这样才能确保每个节点获取到的值都是一致的
l一句话解释,可以理解为是一个公共的共享变量,我们可以把一个dataset 数据集广播出去,然后不同的task在节点上都能够获取到,这个数据在每个节点上只会存在一份。如果不使用broadcast,则在每个节点中的每个task中都需要拷贝一份dataset数据集,比较浪费内存(也就是一个节点中可能会存在多份dataset数据)。
l用法
•1:初始化数据
•DataSet<Integer> toBroadcast = env.fromElements(1, 2, 3)
•2:广播数据
•.withBroadcastSet(toBroadcast, "broadcastSetName");
•3:获取数据
•Collection<Integer> broadcastSet = getRuntimeContext().getBroadcastVariable("broadcastSetName");
l注意:
•1:广播出去的变量存在于每个节点的内存中,所以这个数据集不能太大。因为广播出去的数据,会常驻内存,除非程序执行结束
•2:广播变量在初始化广播出去以后不支持修改,这样才能保证每个节点的数据都是一致的。
demo:
public class BatchBroadCaseDemo {
public static void main(String[] args) throws Exception {
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
//1.准备需要广播的数据
List<Tuple2<String,Integer>> boradcast = new ArrayList<>();
boradcast.add(new Tuple2<>("zs",18));
boradcast.add(new Tuple2<>("ls",20));
boradcast.add(new Tuple2<>("ww",16));
DataSet<Tuple2<String,Integer>> tupleData = env.fromCollection(boradcast);
DataSet<HashMap<String, Integer>> map = tupleData.map(
new MapFunction<Tuple2<String, Integer>, HashMap<String, Integer>>() {
@Override
public HashMap<String, Integer> map(Tuple2<String, Integer> stringIntegerTuple2) throws Exception {
HashMap<String, Integer> map2 = new HashMap<String, Integer>();
map2.put(stringIntegerTuple2.f0, stringIntegerTuple2.f1);
return map2;
}
});
//源数据
DataSource<String> data = env.fromElements("zs","ls","ww");
final DataSet<String> stringStringMapOperator = data.map(new RichMapFunction<String, String>() {
List<HashMap<String, Integer>> broadcastmap = new ArrayList<>();
HashMap<String, Integer> allMap = new HashMap<>();
/**
* 此方法只会执行一次
* @param parameters
* @throws Exception
*/
@Override
public void open(Configuration parameters) throws Exception {
super.open(parameters);
this.broadcastmap = getRuntimeContext().getBroadcastVariable("boardCaseName");
for (HashMap map1 : broadcastmap) {
allMap.putAll(map1);
}
}
@Override
public String map(String s) throws Exception {
return s + ":" + allMap.get(s);
}
}).withBroadcastSet(map, "boardCaseName").setParallelism(4);
stringStringMapOperator.print();//每个算子都需要一个广播变量
}
}
Flink Accumulators & Counters
lAccumulator即累加器,与Mapreduce counter的应用场景差不多,都能很好地观察task在运行期间的数据变化
l可以在Flink job任务中的算子函数中操作累加器,但是只能在任务执行结束之后才能获得累加器的最终结果。
lCounter是一个具体的累加器(Accumulator)实现
•IntCounter, LongCounter 和 DoubleCounter
l用法
•1:创建累加器
•private IntCounter numLines = new IntCounter();
•2:注册累加器
•getRuntimeContext().addAccumulator("num-lines", this.numLines);
•3:使用累加器
•this.numLines.add(1);
•4:获取累加器的结果
•myJobExecutionResult.getAccumulatorResult("num-lines")
demo:
public class CounterDemo {
public static void main(String[] args) throws Exception {
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
//1.准备需要广播的数据
DataSet<String> tupleData = env.fromElements("a", "b", "c");
DataSet<String> result = tupleData.map(new RichMapFunction<String, String>() {
//int num=0;
//定义累加器
private IntCounter numLines = new IntCounter();
@Override
public void open(Configuration parameters) throws Exception {
super.open(parameters);
//注册累加器
getRuntimeContext().addAccumulator("num-lines",this.numLines);
}
@Override
public String map(String s) throws Exception {
//如果并行度为1这种实现方式没问题 ----1
// num++;
// System.out.println("num=" + num);
//累加
this.numLines.add(1);
return s;
}
}).setParallelism(4);
result.writeAsText("txt1.txt");
JobExecutionResult conuter = env.execute("counter");
final int accumulatorResult = conuter.getAccumulatorResult("num-lines");
System.out.println(accumulatorResult);
}
}
lBroadcast(广播变量)允许程序员将一个只读的变量缓存在每台机器上,而不用在任务之间传递变量。广播变量可以进行共享,但是不可以进行修改
lAccumulators(累加器)是可以在不同任务中对同一个变量进行累加操作。
Flink Distributed Cache(分布式缓存)
lFlink提供了一个分布式缓存,类似于hadoop,可以使用户在并行函数中很方便的读取本地文件
l此缓存的工作机制如下:程序注册一个文件或者目录(本地或者远程文件系统,例如hdfs或者s3),通过ExecutionEnvironment注册缓存文件并为它起一个名称。当程序执行,Flink自动将文件或者目录复制到所有taskmanager节点的本地文件系统,用户可以通过这个指定的名称查找文件或者目录,然后从taskmanager节点的本地文件系统访问它
l用法
•1:注册一个文件
•env.registerCachedFile("hdfs:///path/to/your/file", "hdfsFile")
•2:访问数据
•File myFile = getRuntimeContext().getDistributedCache().getFile("hdfsFile");
demo:
ublic class DistrbuteCacheDemo {
public static void main(String[] args) throws Exception {
ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
//注册文件
env.registerCachedFile("text.txt","a");
DataSource<String> data = env.fromElements("b","c","d");
data.map(new RichMapFunction<String, String>() {
private ArrayList<String> arrayList = new ArrayList<>();
@Override
public void open(Configuration parameters) throws Exception {
super.open(parameters);
//使用文件
//不用再从磁盘上取了,会缓存在每个taskMananer上
arrayList.addAll(FileUtils.readLines(getRuntimeContext().getDistributedCache().getFile("a")));
}
@Override
public String map(String s) throws Exception {
return s;
}
}).print();
}
}