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();
    }
}