Flink 也提供了在转换后精确控制流分区的底层控制(如果需要的话),主要通过以下函数:
DataStream → DataStream
使用用户定义的Partitioner为每个元素选择目标任务
。
自定义分区允许用户实现自定义的分区逻辑,即控制每个元素发送到哪个下游任务。
要实现自定义分区,需要创建一个实现 Partitioner 接口的类:
data_stream = env.from_collection(collection=[(2, 'a'), (2, 'a'), (3, 'b')])
data_stream.partition_custom(lambda key, num_partition: key % partition, lambda x: x[0])
DataStream → DataStream
根据均匀分布随机将元素分区
。
随机分区可以通过 DataStream 的 shuffle() 方法应用:
data_stream.shuffle()
这会随机将 stream 的元素派发到下游运算符的所有分区上,达到重新均衡分区的效果。
随机分区的特点是:
随机分区适用于数据负载失衡的情况,或者上游分区与业务关系不大时,可以随机打散分区。它有利于更好地平衡下游任务的负载。
但随机分区也有消耗,应该在需要时选择使用。
DataStream → DataStream
以轮询的方式将元素分区到下游运算符的一个子集中。这在一些场景下比较有用,例如您想从每个上游源并行实例扇出到几个下游 mapper 的子集来分配负载,但又不想引入 rebalance() 带来的完全重新均衡。这样可以只需要本地数据传输,而不用通过网络传输数据,这取决于其他配置值如 TaskManager 的 slot 数。
上游操作发送元素到下游操作的子集,取决于上下游运算符的并行度。例如,如果上游运算符并行度为2,下游运算符并行度为6,则一个上游实例会将元素分发到3个下游实例,另一个上游实例分发到其余3个下游实例。如果下游运算符并行度为2,而上游运算符为6,则有3个上游实例分发到一个下游实例,另3个上游实例分发到另一个下游实例。
如果上下游运算符的并行度不是彼此的整数倍,则会有一个或几个下游实例输入数目与其他实例不同。
重新缩放适用于上下游operator并行度不匹配、需要局部调整的场景。它提供了一个介于全局rebalance和forward之间的粒度分区控制。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6C5JKzZQ-1693127699418)(https://files.mdnice.com/user/3948/20094a0a-53a1-4c4f-9733-c90d8657fd19.svg)]
data_stream.rescale()
DataStream → DataStream
将元素广播到每一个分区
。
广播可以通过 DataStream 的 broadcast() 方法来应用:
data_stream.broadcast()
这会将 stream 的每一个元素,广播到下游运算符的所有并行实例上。
广播的特点是:
广播一般适用于下游任务需要访问全局信息的场景,比如字典表、配置表等需要广播到所有下游实例的小规模数据集。
但广播也存在数据复制的消耗,不能滥用,应该在需要时选择使用。