![Flink内核原理与实现](https://wfqqreader-1252317822.image.myqcloud.com/cover/481/37323481/b_37323481.jpg)
3.6 数据分区
数据分区在Flink中叫作Partition。本质上来说,分布式计算就是把一个作业切分成子任务Task,将不同的数据交给不同的Task计算。在分布式存储中,Partition分区的概念就是把数据集切分成块,每一块数据存储在不同的机器上。同样,对于分布式计算引擎,也需要将数据切分,交给位于不同物理节点上的Task计算。
StreamPartitioner是Flink中的数据流分区抽象接口,决定了在实际运行中的数据流分发模式,将数据切分交给Task计算,每个Task负责计算一部分数据流。所有的数据分区器都实现了ChannelSelector接口,该接口中定义了负载均衡选择行为。
代码清单3-14 ChannelSelector接口定义
![](https://epubservercos.yuewen.com/AB30C5/19773741101350906/epubprivate/OEBPS/Images/72_01.jpg?sign=1738924075-QKTw6i8pFrUjOYZAPVA57kAmqTzhXgB5-0-f93a4c5d96f367a75069b7edaff50382)
在该接口中可以看到,每一个分区器都知道下游通道数量,通道数量在一次作业运行中是固定的,除非修改作业的并行度,否则该值是不会改变的(此处跟后边容错章节模型中提到的Flink DAG有关系,Flink DAG的拓扑关系是静态的)。
数据分区类体系如图3-35所示。
![](https://epubservercos.yuewen.com/AB30C5/19773741101350906/epubprivate/OEBPS/Images/72_02.jpg?sign=1738924075-0cVCMFDC9WiBdCNbI9bBrWGGw3mnoKzY-0-9c36c552f6dee4cd4f193af9b0c5e912)
图3-35 数据分区类体系
1.自定义分区
在API层面上,自定义分区应用在DataStream上,生成一个新的DataStream。
使用用户自定义分区函数,为每一个元素选择目标分区,其使用如代码清单3-15所示。
代码清单3-15 DataStream中使用自定义分区
![](https://epubservercos.yuewen.com/AB30C5/19773741101350906/epubprivate/OEBPS/Images/73_01.jpg?sign=1738924075-kfuxpWKCrJbbv2Da55NdnQcVIiF06zyr-0-1ad87ebe189935993bfd25c2005b09af)
2. ForwardPartitioner
在API层面上,ForwardPartitioner应用在DataStream上,生成一个新的DataStream。
该Partitioner比较特殊,用于在同一个OperatorChain中上下游算子之间的数据转发,实际上数据是直接传递给下游的。
3. ShufflePartitioner
在API层面上,ShufflePartitioner应用在DataStream上,生成一个新的DataStream。
随机将元素进行分区,可以确保下游的Task能够均匀地获得数据,其使用如代码清单3-16所示。
代码清单3-16 DataStream中使用ShufflePartitioner
![](https://epubservercos.yuewen.com/AB30C5/19773741101350906/epubprivate/OEBPS/Images/73_02.jpg?sign=1738924075-546P0RPaVYrARGK1r8oWsHDL6y0Obolf-0-f4a53e071bc3a5f9f9d12950f39e7048)
4. ReblancePartitioner
在API层面上,ReblancePartitioner应用在DataStream上,生成一个新的DataStream。
以Round-robin的方式为每个元素分配分区,确保下游的Task可以均匀地获得数据,避免数据倾斜,其使用如代码清单3-17所示。
代码清单3-17 DataStream中使用ReblancePartitioner
![](https://epubservercos.yuewen.com/AB30C5/19773741101350906/epubprivate/OEBPS/Images/73_03.jpg?sign=1738924075-Xv2hEqvz6gOkSgebF0fUNgRIpwI0WyHT-0-3d9e5d311f77f9c5a0892d36b292c4fd)
5. RescalingPartitioner
在API层面上,RescalingPartitioner应用在DataStream上,生成一个新的DataStream。
根据上下游Task的数量进行分区。使用Round-robin选择下游的一个Task进行数据分区,如上游有2个Source,下游有6个Map,那么每个Source会分配3个固定的下游Map,不会向未分配给自己的分区写入数据。这一点与ShufflePartitioner和ReblancePartitioner不同,后两者会写入下游所有的分区,如图3-36所示。
![](https://epubservercos.yuewen.com/AB30C5/19773741101350906/epubprivate/OEBPS/Images/73_04.jpg?sign=1738924075-TBbozn9bQ0GNgtcSJImLsU8RBJi8Fa4F-0-07c5dd4ec45ba22e1dbad40b90398dc6)
图3-36 Rescaling分区效果示意
其使用如代码清单3-18所示。
代码清单3-18 DataStream中使用RescalingPartitioner
![](https://epubservercos.yuewen.com/AB30C5/19773741101350906/epubprivate/OEBPS/Images/73_05.jpg?sign=1738924075-RA5yYC3zsGMRZzO4VGzSn12Miafu4CvN-0-a1ae1c20d549c328418d5f51f754cf5c)
6. BroadcastPartitioner
在API层面上,BroadcastPartitioner应用在DataStream上,生成一个新的DataStream。
将该记录广播给所有分区,即有N个分区,就把数据复制N份,每个分区1份,其使用如代码清单3-19所示。
代码清单3-19 DataStream中使用BroadcastPartitioner
![](https://epubservercos.yuewen.com/AB30C5/19773741101350906/epubprivate/OEBPS/Images/74_01.jpg?sign=1738924075-SfwsUXLee2FndM0qZIpBcZfpklu9al4h-0-19599d7188219a71f14a65d024cb657a)
7. KeyGroupStreamPartitioner
在API层面上,KeyGroupStreamPartitioner应用在KeyedStream,生成一个新的KeyedStream。
KeyedStream根据KeyGroup索引编号进行分区,该分区器不是提供给用户来用的。KeyedStream在构造Transformation的时候默认使用KeyedGroup分区形式,从而在底层上支持作业Rescale功能。