赞
踩
一、知识铺垫
a. Flink数据传输分类
Flink数据传输分为 组件之间的通信消息传输 和 算子之间的流数据传输。
(1)组件之间
组件(即Client、JobManager、TaskManager)之间的通信消息传输采用Akka框架。常见的通信包括心跳检测、状态上报、指标统计、作业提交和部署等。
(2)算子之间
(2.1)本地线程内(同一个SubTask内的两个Operator):数据传输通过方法调用进行,即上游算子处理完数据后,直接调用下游算子的processElement方法。
(2.2)本地线程间(同一个TaskManager的不同SubTask中):数据传输通过本地内存进行,需要进行数据的序列化和反序列化。
(2.3)跨网络(不同TaskManager的SubTask中):采用Netty框架,通过Socket进行数据传输,也需要进行数据的序列化和反序列化。
Flink中为上下游subtask之间数据传输(即上述2.2&2.3)提供了九种传输策略。
其中BinaryHashPartitioner位于Blink的Table API的org.apache.flink.table.runtime.partitioner包中,是一种针对BinaryRowData的哈希分区器。
本文讨论上图中绿色框圈中的八种策略。
在Flink WebUI中,可看到算子之间的传输策略会在箭头上标注出来。
b. Flink中分发模式(Distribution Pattern)
Flink 中的执行图可以分成四层:StreamGraph -> JobGraph -> ExecutionGraph -> 物理执行图。
在StreamGraph -> JobGraph的过程中,上下游subtask之间的数据传输涉及分发模式。
分发模式描述了上游节点与下游节点连接的方式,Flink 中有两种分发模式:点对点 (Pointwise) 和全连接 (All-to-all)。
All-to-all模式: 简单的全连接。
Pointwise模式:上下游节点的并行度会影响连接方式。当上下游并行度相同时会一对一连接;当上游并行度小于下游时,下游subTask只会连接一个上游分区;当上游并行度大于下游时,下游subTask会连接多个上游分区。
RescalePartitioner和ForwardPartitioner 采用了 Pointwise模式。
在RescalePartitioner&RebalancePartitioner,ForwardPartitioner&GlobalPartitioner 这两组策略中,由于分发模式的不同,每组的两种分区策略会产生不同的效果。
二、八种传输策略
StreamPartitioner继承自ChannelSelector接口。这里的Channel可以认为它就是下游算子的并发实例(即物理分区)。所有StreamPartitioner的子类都要实现selectChannel()方法,用来选择分区号。
1. ForwardPartitioner
ForwardPartitioner是Flink默认的传输策略。
这种策略的前提是上下游并行度相同。
ForwardPartitioner会将数据发到下游的对应分区(在pointwise模式下下游的0号分区也对应着上游相关分区)。
2. RebalancePartitioner
当上下游算子不符合ForwardPartitioner使用条件时,Flink会默认选择RebalancePartitioner。
(ForwardPartitioner & RebalancePartitioner 是Flink根据上下游并行度设置等因素设置的默认策略,其他几类传输策略则需要用户代码指定 )。
RebalancePartitioner会先随机选一个下游分区,之后轮询(round-robin)遍历下游所有分区进行数据传输。
3. RescalePartitioner
RescalePartitioner在pointwise模式下会先根据上下游并行度进行匹配,再从匹配后的下游中从0号分区轮询传输数据。
4. ShufflePartitioner
ShufflePartitioner会随机选取下游分区进行数据传输。由于Random生成的随机数符合均匀分布,因此能够大致保证下发的平均效果,类似于RebalancePartitioner。
5. KeyGroupStreamPartitioner
KeyGroupStreamPartitioner的分区是根据消息的key值经过两层hash处理后获得的,具体值如下
MathUtils.murmurHash(key.hashCode()) % maxParallelism * numberOfChannels / maxParallelism
6. GlobalPartitioner
GlobalPartitioner和ForwardPartitioner的代码类似。但是GlobalPartitioner基于All-to-all的分发模式,能获得下游算子的全局分区号。所以保证了只下发给下游算子的第一个分区。
7. BroadcastPartitioner
BroadcastPartitioner会下发给下游的每个分区,不需要选择。
8.CustomPartitionerWrapper
CustomPartitionerWrapper需要用户指定为消息的每个key设置下游分区的选择规则。
三、参考资料
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。