• 20.flink流处理和批处理的一些思考(对新手来说很重要)


    摘要

    流处理和批处理很多算子基本都是一样的,比如reduce,map,flatMap等等。但是有些时候流处理和批处理同样的算子输出结果是不同的,这一点对于新手有时候难以理解,这篇文将就来谈谈这个问题,我们以reduce这个算了为例子来做展示。

    1.批处理reduce

    import org.apache.flink.api.java.DataSet;
    import org.apache.flink.api.java.ExecutionEnvironment;
    import org.apache.flink.api.java.tuple.Tuple2;

    public class reduceDemo {
    public static void main(String[] args) throws Exception {
    final ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();

        DataSet> text = env.fromElements(
                Tuple2.of("a", 1L),
                Tuple2.of("a", 2L),
                Tuple2.of("b", 1L),
                Tuple2.of("b", 3L),
                Tuple2.of("c", 100L)
        );
     text.groupBy(0).reduce((x1,x2)-> Tuple2.of(x1.f0,x1.f1+x2.f1)).print();
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    }

    输出结果为:
    (a,3)
    (b,4)
    (c,100)

    2.流处理reduce

    import org.apache.flink.api.java.tuple.Tuple2;
    import org.apache.flink.streaming.api.datastream.DataStream;
    import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
    
    public class reduceDemo {
    //reduce和我们想的还是有些不同
        public static void main(String[] args) throws Exception {
            StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
            //定义两条流
            DataStream> stream1 = env.fromElements(
                    Tuple2.of("a", 1L),
                    Tuple2.of("a", 2L),
                    Tuple2.of("b", 1L),
                    Tuple2.of("b", 3L),
                    Tuple2.of("c", 100L)
            );
         stream1.keyBy(0).reduce((x0,x1)-> Tuple2.of(x0.f0,x0.f1+x1.f1)).print();
            env.execute();
        }
    
    }
    输出结果为:
     (a,1)
     (a,3)
     (b,1)
     (b,4)
     (c,100)
    
    • 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

    3.分析结果

    上面的两个代码逻辑是一模一样的,都是根据第一个元素进行分区分组,根据第二个元素做求和。批处理的结果我们很容易接收,而结果也是我们想的样子。

    (a,3)
    (b,4)
    (c,100)
    流处理结果:
    (a,1)
    (a,3)
    (b,1)
    (b,4)
    (c,100)
    这个样子对很多新手来说很难接受,为什么不是我想要的样子,你只所以有这个疑问是因为你还没有理解批处理和流出的重大区别, 对批处理来说在输入数据一样的情况下,结果也一定只有一种。 而对于流处理来说,流处理是无解的,你不知道什么时候结束,换句话说我们也不关心什么时候结束,我们只关心中间的结果,流处理是每来一个数据进行一次逻辑运算,而这个结果就是实实在在的当前的结果,你不要总是想着最终结果,流处理没有最终结果的概念。

    4.我们重点来分析流处理:

    1. 对a来说: 第一次来了个(a,1)不进行计算即当前结果就是(a,1),第二次来了个(a,2)则计算结果为(a,3)–>产生的中间结果就是**(a,1)和(a,3)**
    2. 对b来说:第一次来了个(b,1)不进行计算即当前结果就是(b,1),第二次来了个(b,3)则计算结果为(b,4)–>产生的中间结果就是(b,1)和(b,4)
    3. 对c来说: 第一次来了个(c,100)不进行计算即当前结果就是**(c,100)**

    所以流处理最终的结果就是:(a,1)(a,3) (b,1)(b,4) (c,100)

    所以对a来说计算结果从a,1到a,3这两个都是真正的结果,只不过随着流数据的到来这个结果会不断往前推进,故而落库的时候这个数据的Key一般用作唯一主键来进行对数据的更新,假设我们将计算结果存入mysql, 那么其实对流数据来说最后的结果也是:(a,3), (b,4) (c,100)这样看下来,在输入流保持不变的时候,其实批处理和流处理最终的处理结果是一致的。

    5.总结

    综上所述,同样的算子,在批处理和流处理的行为本质上是一样的,产生的结果是不同的。 这里读者一定要理解流处理,流处理从source-etl-sink这整个流程中结果是不断发出的,落地库中的结果也是在不断被更新的(需要唯一主键保证),这是和批处理最大的区别,批处理往落地库输出结果只有一次,而流处理是在不断的输出处理结果。 重点要理解六处理中:不断产生不断更新结果 这两个词。

  • 相关阅读:
    PHP笔记-解决网站CDN加速后图片出现跨越问题
    产品经理进阶:如何写商业计划书?
    在职场上有多少人输在了不会用Python数据分析
    Matlab:函数调用中的 name=value
    ConstraintTools...
    读取jsonArray文件并转换为java对象工具类
    7、Netty核心模块API
    Linux 完整 Redis 安装配置教程(可用远程连接)
    C语言找出一个二维数组中的鞍点,即该位置上的元素在该行上最大,在该列上最小,也可能没有鞍点
    机器学习课后习题 --- 朴素贝叶斯
  • 原文地址:https://blog.csdn.net/qq_36066039/article/details/126333466