• Flink中KeyBy、分区、分组的正确理解


    1.Flink中的KeyBy

    在Flink中,KeyBy作为我们常用的一个聚合类型算子,它可以按照相同的Key对数据进行重新分区,分区之后分配到对应的子任务当中去。
    源码解析
    keyBy 得到的结果将不再是 DataStream,而是会将 DataStream 转换为 KeyedStream(键控流),KeyedStream 可以认为是“分区流”或者“键控流”,它是对 DataStream 按照 key 的一个逻辑分区
    所以泛型有两个类型:除去当前流中的元素类型外,还需要指定 key 的类型。
    在这里插入图片描述
    KeyBy是如何实现分区的呢

    Flink中的KeyBy底层其实就是通过Hash实现的,通过对Key的值进行Hash,再做一次murmurHash,取模运算。
    再通过Job的并行度,就能获取每个Key应该分配到那个子任务中了。

    在这里插入图片描述

    2.分组和分区在Flink中的区别

    分区:分区(Partitioning)是将数据流划分为多个子集,这些子集可以在不同的任务实例上进行处理,以实现数据的并行处理。
    数据具体去往哪个分区,是通过指定的 key 值先进行一次 hash 再进行一次 murmurHash,通过上述计算得到的值再与并行度进行相应的计算得到。
    分组:分组(Grouping)是将具有相同键值的数据元素归类到一起,以便进行后续操作(如聚合、窗口计算等)。
    key值相同的数据将进入同一个分组中。
    注意:数据如果具有相同的key将一定去往同一个分组和分区,但是同一分区中的数据不一定属于同一组。

    3.代码示例

    package com.flink.DataStream.Aggregation;
    
    import org.apache.flink.api.common.RuntimeExecutionMode;
    import org.apache.flink.api.common.functions.FlatMapFunction;
    import org.apache.flink.api.common.functions.MapFunction;
    import org.apache.flink.api.common.typeinfo.Types;
    import org.apache.flink.api.java.functions.KeySelector;
    import org.apache.flink.api.java.tuple.Tuple2;
    import org.apache.flink.streaming.api.datastream.DataStreamSource;
    import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
    import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
    import org.apache.flink.util.Collector;
    
    public class FlinkKeyByDemo {
        public static void main(String[] args) throws Exception {
            //TODO 创建Flink上下文执行环境
            StreamExecutionEnvironment streamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment();
            //设置并行度为1
            streamExecutionEnvironment.setParallelism(1);
            //设置执行模式为批处理
            streamExecutionEnvironment.setRuntimeMode(RuntimeExecutionMode.BATCH);
            //TODO source 从集合中创建数据源
            DataStreamSource<String> dataStreamSource = streamExecutionEnvironment.fromElements("hello word", "hello flink");
            //TODO 方式一 匿名实现类
            SingleOutputStreamOperator<Tuple2<String, Integer>> outputStreamOperator1 = dataStreamSource
                    .flatMap(new FlatMapFunction<String, String>() {
                        @Override
                        public void flatMap(String s, Collector<String> collector) throws Exception {
                            String[] s1 = s.split(" ");
                            for (String word : s1) {
                                collector.collect(word);
                            }
                        }
                    })
                    .map(new MapFunction<String, Tuple2<String, Integer>>() {
                        @Override
                        public Tuple2<String, Integer> map(String s) throws Exception {
                            Tuple2<String, Integer> aa = Tuple2.of(s, 1);
                            return aa;
                        }
                    })
                    /**
                     * keyBy 得到的结果将不再是 DataStream,而是会将 DataStream 转换为 KeyedStream(键控流)
                     * KeyedStream 可以认为是“分区流”或者“键控流”,它是对 DataStream 按照 key 的一个逻辑分区
                     * 所以泛型有两个类型:除去当前流中的元素类型外,还需要指定 key 的类型。
                     * */
    
                    /**
                     * 分组和分区在Flink 中具有不同的含义和作用:
                     * 分区:分区(Partitioning)是将数据流划分为多个子集,这些子集可以在不同的任务实例上进行处理,以实现数据的并行处理。
                     *      数据具体去往哪个分区,是通过指定的 key 值先进行一次 hash 再进行一次 murmurHash,通过上述计算得到的值再与并行度进行相应的计算得到。
                     * 分组:分组(Grouping)是将具有相同键值的数据元素归类到一起,以便进行后续操作 (如聚合、窗口计算等)。
                     *      key 值相同的数据将进入同一个分组中。
                     * 注意:数据如果具有相同的key将一定去往同一个分组和分区,但是同一分区中的数据不一定属于同一组。
                     * */
    
                    .keyBy(new KeySelector<Tuple2<String, Integer>, String>() {
                        @Override
                        public String getKey(Tuple2<String, Integer> stringIntegerTuple2) throws Exception {
                            return stringIntegerTuple2.f0;
                        }
                    })
                    .sum(1);
            //TODO 方式二 Lamda表达式实现
            SingleOutputStreamOperator<Tuple2<String, Integer>> outputStreamOperator2 = dataStreamSource
                    .flatMap((String s, Collector<String> collector) -> {
                        String[] s1 = s.split(" ");
                        for (String word : s1) {
                            collector.collect(word);
                        }
                    })
                    .returns(Types.STRING)
                    .map((String word) -> {
                        return Tuple2.of(word, 1);
                    })
                    //Java中lamda表达式存在类型擦除
                    .returns(Types.TUPLE(Types.STRING, Types.INT))
                    .keyBy((Tuple2<String, Integer> s) -> {
                        return s.f0;
                    })
                    .sum(1);
            //TODO sink
            outputStreamOperator1.print("方式一");
            outputStreamOperator2.print("方式二");
            //TODO 执行
            streamExecutionEnvironment.execute("Flink KeyBy Demo");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
  • 相关阅读:
    机器学习 线性回归:正规方程与梯度下降
    接口自动化测试思路和实战(2):模块化测试脚本框架
    Android 13 - Media框架(12)- MediaCodec(二)
    【vue+elementUI】输入框样式、选择器样式、树形选择器和下拉框样式修改
    AI 正在攻克难题——赋予计算机嗅觉
    如何在BI中增加“路线地图”并进行数据分析?
    浅析Open vSwitch数据结构:哈希表hmap/smap/shash
    Python和Java二选一该学啥?
    1. HelmTemplate 3分钟将项目部署至k8s
    滨海新区副区长张桂华一行调研考察GBASE南大通用
  • 原文地址:https://blog.csdn.net/dgssd/article/details/133813466