流处理和批处理很多算子基本都是一样的,比如reduce,map,flatMap等等。但是有些时候流处理和批处理同样的算子输出结果是不同的,这一点对于新手有时候难以理解,这篇文将就来谈谈这个问题,我们以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();
}
}
输出结果为:
(a,3)
(b,4)
(c,100)
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)
上面的两个代码逻辑是一模一样的,都是根据第一个元素进行分区分组,根据第二个元素做求和。批处理的结果我们很容易接收,而结果也是我们想的样子。
(a,3)
(b,4)
(c,100)
流处理结果:
(a,1)
(a,3)
(b,1)
(b,4)
(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)这样看下来,在输入流保持不变的时候,其实批处理和流处理最终的处理结果是一致的。
综上所述,同样的算子,在批处理和流处理的行为本质上是一样的,产生的结果是不同的。 这里读者一定要理解流处理,流处理从source-etl-sink这整个流程中结果是不断发出的,落地库中的结果也是在不断被更新的(需要唯一主键保证),这是和批处理最大的区别,批处理往落地库输出结果只有一次,而流处理是在不断的输出处理结果。 重点要理解六处理中:不断产生 和 不断更新结果 这两个词。