重分区算子(物理分区算子):(keyBy、随机分区(shuffle)、轮询分区Round-Robin(rebalance)、重缩放分区(rescale)、广播(broadcast)、全局分区(global)、forward、自定义分区(Custom))
keyBy和shuffle(经过随机分区之后,得到的依然是一个DataStream)不必多说。

轮询分区算子rebalance(通过DataStream来调用):
简单来说就是发牌。rebalance使用的是Round-Robin负载均衡算法,可以将输入流数据平均分配到下游的并行任务中去.

重缩放分区(rescale)
重缩放分区和轮询分区非常相似。当调用rescale()方法时,其实底层也是使用Round-Robin算法进行轮询,但是只会将数据轮询发送到下游并行任务的一部分中。rescale的做法是分成小团体,发牌人只给自己团体内的所有人轮流发牌。假设上游2个分区,下游4个分区,rescale会先分组(不是keyBy,而是普通含义上的分组,比如上游1分区分配下游1、2号分区,2号分区分配下游3、4号分区,然后在组内轮询发送)

广播(broadcast):
这种方式其实不应该叫做“重分区”,因为经过广播之后,数据会在不同的分区都保留一份,可能进行重复处理。可以通过调用DataStream的broadcast()方法,将输入数据复制并发送到下游算子的所有并行任务中去。

全局分区(global):
全局分区也是一种特殊的分区方式。这种做法非常极端,通过调用.global()方法,会将所有的输入流数据都发送到下游算子的第一个并行子任务中去。这就相当于强行让下游任务并行度变成了1,所以使用这个操作需要非常谨慎,可能对程序造成很大的压力。

forward:一对一,要求上下游的并行度得相同 :

自定义分区(Custom):
当Flink提供的所有分区策略都不能满足用户的需求时,我们可以通过使用partitionCustom()方法来自定义分区策略。
代码测试:
import com.sandra.bean.WaterSensor;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.java.functions.KeySelector;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.KeyedStream;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
public class Flink10_Transform_Repartition {
public static void main(String[] args) throws Exception {
//todo 1.获取流的执行环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(4);
//todo 2.从端口读取数据
DataStreamSource<String> streamSource = env.socketTextStream("hadoop102", 9999);
//todo 3.使用map将读取的数据转为WaterSensor
SingleOutputStreamOperator<WaterSensor> result = streamSource.map(new MapFunction<String, WaterSensor>() {
@Override
public WaterSensor map(String line) throws Exception {
String[] waterSensorWords = line.split(" ");
return new WaterSensor(waterSensorWords[0], Long.parseLong(waterSensorWords[1]), Integer.parseInt(waterSensorWords[2]));
}
}).setParallelism(2);
//将上游数据打印,看看数据去往上游数据的哪个分区(上游有2个分区)
result.print("原始数据").setParallelism(2);//map和print的并行度都设置为2,目的是将它们串到一起
//todo 4.使用keyby将相同的id的数据放到一块
KeyedStream<WaterSensor, String> keyedStream = result.keyBy(new KeySelector<WaterSensor, String>() {
@Override
public String getKey(WaterSensor value) throws Exception {
return value.getId();
}
});
DataStream<WaterSensor> shuffle = result.shuffle();//并行度为4
DataStream<WaterSensor> rebalance = result.rebalance();//并行度为4
DataStream<WaterSensor> rescale = result.rescale();//并行度为4
// KeyedStream<WaterSensor, Tuple> keyedStream1 = result.keyBy("id");
//将下游的数据打印出来,看看上游两个分区的数据分别去往下游的哪个分区
keyedStream.print("keyBy");//并行度为4
shuffle.print("shuffle");//并行度为4
rebalance.print("rebalance");//并行度为4
rescale.print("rescale");//并行度为4
env.execute();
}
}
测试结果为:




本文介绍了Flink数据流处理中的几种重分区算子,包括shuffle、rebalance、rescale、广播、全局分区等,详细解释了它们的工作原理和应用场景,并提供了一个代码示例来展示这些分区策略的使用。
1278

被折叠的 条评论
为什么被折叠?



