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 从集合中创建数据源 DataStreamSourcedataStreamSource = streamExecutionEnvironment.fromElements("hello word", "hello flink"); //TODO 方式一 匿名实现类 SingleOutputStreamOperator > outputStreamOperator1 = dataStreamSource .flatMap(new FlatMapFunction () { @Override public void flatMap(String s, Collector collector) throws Exception { String[] s1 = s.split(" "); for (String word : s1) { collector.collect(word); } } }) .map(new MapFunction >() { @Override public Tuple2 map(String s) throws Exception { Tuple2 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 , String>() { @Override public String getKey(Tuple2 stringIntegerTuple2) throws Exception { return stringIntegerTuple2.f0; } }) .sum(1); //TODO 方式二 Lamda表达式实现 SingleOutputStreamOperator > outputStreamOperator2 = dataStreamSource .flatMap((String s, Collector 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 s) -> { return s.f0; }) .sum(1); //TODO sink outputStreamOperator1.print("方式一"); outputStreamOperator2.print("方式二"); //TODO 执行 streamExecutionEnvironment.execute("Flink KeyBy Demo"); } }
猜你喜欢
- 10小时前前端大屏适配几种方案
- 10小时前若依框架详细使用
- 10小时前thinkphp 命令行执行
- 10小时前linux搭建LAMP服务
- 10小时前rust跟我学二:模块编写与使用
- 10小时前Java 栈和队列的交互实现
- 8小时前空调模式图标含义图解(格力空调模式图标含义图解)
- 5小时前美赞臣亲舒(美赞臣亲舒水解奶粉可以长期吃吗)
- 5小时前manage是什么意思(manage是什么意思翻译)
- 1小时前沈阳辉山乳业(沈阳辉山乳业是国企吗)
网友评论
- 搜索
- 最新文章
- 热门文章