flink datastream调用8种分区策略实例

在Apache Flink中,处理数据流并将其分配到不同的分区(partition)是实现并行处理的关键手段之一。Flink提供了灵活的机制来控制数据如何分配到不同的并行任务(subtasks)上。下面是一些使用Flink DataStream API调用8种分区策略的实例,这些策略可以帮助你根据不同的需求来控制数据的分区。

1. 默认分区(Global Partitioning)

默认情况下,当你使用DataStream的keyBy方法但没有指定特定的分区器时,Flink会使用全局(Global)分区策略,即所有的数据都会被发送到同一个并行任务上。

复制代码
DataStream<Tuple2<String, Integer>> stream = ...; 
stream.keyBy(value -> value.f0) 
        .map(value -> value) // 示例操作 
        .setParallelism(8); // 设置并行度为8

2. 哈希分区(Hash Partitioning)

通过keyBy方法可以实现哈希分区,这是最常用的分区方式之一。

复制代码
DataStream<Tuple2<String, Integer>> stream = ...; 
stream.keyBy(value -> value.f0) 
        .map(value -> value) // 示例操作 
        .setParallelism(8); // 设置并行度为8

3. 重新平衡分区(Rebalance Partitioning)

使用rebalance()方法可以将数据均匀地重新分配到下游的所有并行任务中。

复制代码
DataStream<Tuple2<String, Integer>> stream = ...; 
stream.rebalance() 
        .map(value -> value) // 示例操作 
        .setParallelism(8); // 设置并行度为8

4. 重缩放分区(Rescale Partitioning)

与rebalance()类似,但rescale()主要用于上游和下游的并行度相同时。它会尝试最小化网络传输。

复制代码
DataStream<Tuple2<String, Integer>> stream = ...; 
stream.rescale() 
        .map(value -> value) // 示例操作 
        .setParallelism(8); // 设置并行度为8

5. 广播分区(Broadcast Partitioning)

使用broadcast()方法可以将数据流广播到所有下游任务。这在某些类型的全局状态更新场景中很有用。

复制代码
DataStream<Tuple2<String, Integer>> stream = ...; 
stream.broadcast() 
        .map(value -> value) // 示例操作 
        .setParallelism(8); // 设置并行度为8

6. 自定义分区(Custom Partitioning)

你可以实现自定义的分区逻辑,通过partitionCustom()方法。这需要你提供一个自定义的分区器。

复制代码
DataStream<Tuple2<String, Integer>> stream = ...; 
stream.partitionCustom(new MyCustomPartitioner(), keySelector) 
        .map(value -> value) // 示例操作 
        .setParallelism(8); // 设置并行度为8

其中MyCustomPartitioner是一个实现了org.apache.flink.api.common.operators.base.PartitionerDescriptor接口的类。

7. 范围分区(Range Partitioning)

范围分区通常用于有序的数据流,通过keyBy()后跟一个有序的数据类型来实现。例如,使用元组的第一个字段作为键。

复制代码
ataStream<Tuple2<String, Integer>> stream = ...; 
stream.keyBy(0) // 基于元组的第一个字段进行范围分区 
        .map(value -> value) // 示例操作 
        .setParallelism(8); // 设置并行度为8,确保下游并行度与上游一致或更大以充分利用范围分区特性。

8. 随机分区(Random Partitioning)

使用shuffle()方法可以将数据随机分配到下游的各个任务中。这通常用于需要随机打乱数据顺序的场景。

复制代码
DataStream<Tuple2<String, Integer>> stream = ...; 
stream.shuffle() // 随机分区 
        .map(value -> value) // 示例操作 
        .setParallelism(8); // 设置并行度为8

9. Forward分区(Forward Partitioning)

使用shuffle()方法可以将数据随机分配到下游的各个任务中。这通常用于需要随机打乱数据顺序的场景。

DataStream<Tuple2<String, Integer>> stream = ...;

stream.forward() // Forward分区

.map(value -> value) // 示例操作

.setParallelism(8); // 设置并行度为8

Flink 分区是为了解决‌并行计算时的数据重分布与负载均衡 ‌问题;分区后的数据合并并非自动发生,需通过‌Union/Connect/Join/CoGroup ‌等算子显式组合,或依赖‌KeyedStream 的状态聚合‌逻辑 。‌‌

为什么要分区

  • ‌适配并行度变化‌:上下游算子并行度不一致时,必须重分区才能将数据正确路由到所有下游子任务,避免数据丢失或资源浪费 。
  • ‌实现负载均衡‌:防止数据倾斜,通过 Shuffle/Rebalance 等策略将数据均匀分发,提升集群资源利用率 。
  • ‌满足业务逻辑需求 ‌:如 keyBy 按键分组确保相同 Key 进入同一子任务以进行状态计算;广播分区将配置流分发给所有实例;全局分区用于汇总到单点 。
  • ‌跨节点通信基础‌:分布式环境下,数据需通过网络传输到特定 TaskManager 的特定 Slot,分区器定义了具体的路由规则 。‌‌

分区后数据如何"合并"

Flink 中"合并"指逻辑上的流汇聚,不同场景对应不同算子,‌物理分区本身不自动合并数据‌:

  1. ‌**简单拼接(Union)**‌

    • ‌场景 ‌:多条‌数据类型完全相同‌的流直接合并(如多源日志)。
    • ‌机制 ‌:stream.union(otherStreams...),数据按 FIFO 混合,水位线取最小值,‌不进行去重或关联‌。
    • ‌注意‌:仅合并流结构,不改变数据内容 。‌‌
  2. ‌**异构连接(Connect)**‌

    • ‌场景 ‌:两条‌数据类型不同‌的流需关联处理(如订单流 + 用户画像流)。
    • ‌机制 ‌:stream1.connect(stream2) 生成 ConnectedStreams,需配合 CoProcessFunction 自定义逻辑,可‌共享状态‌但流内部独立 。
    • ‌关键 ‌:常先对双流执行 keyBy 将相同 Key 路由到同一子任务,再在函数内匹配处理 。‌‌
  3. ‌**时间窗口关联(Join / Interval Join)**‌

    • ‌场景 ‌:基于‌时间窗口和 Key‌ 匹配两条流中的事件(如点击流 + 转化流)。
    • ‌机制 ‌:stream1.join(stream2).where(...).equalTo(...).window(...).apply(...),仅在窗口内且 Key 匹配的数据对才会输出,‌非匹配数据丢弃‌(Inner Join 逻辑)。
    • ‌前提‌:必须定义 Watermark 以处理事件时间 。‌‌
  4. ‌**分组聚合(KeyedStream + Reduce/Aggregate)**‌

    • ‌场景 ‌:分区(keyBy)后对同一 Key 的数据进行统计(如求和、计数)。
    • ‌机制 ‌:keyBy 将相同 Key 强制路由到同一子任务,后续调用 reduce/aggregate/sum 在该子任务内部‌逻辑合并‌状态,输出单条结果。这是最典型的"分区后合并计算"模式 。‌‌
  5. ‌**全局汇总(Global + Sink)**‌

    • ‌场景‌:将所有数据强制发送到单个子任务进行最终汇总。
    • ‌机制 ‌:使用 .global() 分区算子将所有记录路由到下游第一个子任务(并行度实际失效为 1),随后在该子任务内聚合或写入 Sink。易造成单点瓶颈,慎用 。‌‌

‌核心区别 ‌:Union/Connect 是流的物理拼接,数据量不变;keyBy+ 聚合 是逻辑归并,数据量通常减少;Join 是条件匹配,数据量取决于匹配结果。选择取决于业务是需"拼接数据"、"关联分析"还是"统计聚合"。

相关推荐
starzy19904 天前
Flink Sliding Window 详解及代码实现:从窗口重叠到状态爆炸防控
运维·数据库·flink
Gl�ria4 天前
Yarn NM 常驻Flink任务下线:stop/savepoint 释放容器
flink·yarn
TLA技术4 天前
LogMiner vs 裸日志解析(三):Oracle日志解析中的“前镜像”和“后镜像”,到底怎么用?
数据库·oracle·flink·dba·迁移学习
starzy19904 天前
Flink Session Window 详解及代码实现:从用户会话切割到窗口合并机制
java·flink
starzy19906 天前
Flink Window 详解及代码实现:从滚动窗口到迟到数据处理
大数据·flink
Thomas21436 天前
flink pekko OversizedPayloadException 异常排查记录
flink
平顶山大师7 天前
datalink下载安装
flink·微软
用户3610588626127 天前
从 chroot 到 LXC:四代容器隔离技术演进,Namespace 与 Cgroups 原理拆解
大数据·flink
Msshu1237 天前
什么是PD快充诱骗取电芯片,PD快充取电芯片如何选型
flink·rabbitmq·ambari·mariadb·storm·talkingdata
用户3610588626129 天前
Flink高级之侧输出流Side Output原理及代码实现:从OutputTag到多流分发
大数据·flink