![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=1738789107-Ki5YdRhru4ngKhSZEEkiXKtvwSJE95uV-0-72f9f4907b9466db90a4112ac6fb6b07)
在该接口中可以看到,每一个分区器都知道下游通道数量,通道数量在一次作业运行中是固定的,除非修改作业的并行度,否则该值是不会改变的(此处跟后边容错章节模型中提到的Flink DAG有关系,Flink DAG的拓扑关系是静态的)。
数据分区类体系如图3-35所示。
![](https://epubservercos.yuewen.com/AB30C5/19773741101350906/epubprivate/OEBPS/Images/72_02.jpg?sign=1738789107-JDUl5HoZYjl4Kq4hBqiwawdy1eq1fgj7-0-b580673fcbdc6122a686c79e3348849c)
图3-35 数据分区类体系
1.自定义分区
在API层面上,自定义分区应用在DataStream上,生成一个新的DataStream。
使用用户自定义分区函数,为每一个元素选择目标分区,其使用如代码清单3-15所示。
代码清单3-15 DataStream中使用自定义分区
![](https://epubservercos.yuewen.com/AB30C5/19773741101350906/epubprivate/OEBPS/Images/73_01.jpg?sign=1738789107-8bzthX2W1XgIapIXDewLyQ8FSAfJ2mRv-0-c270b3bddb607ca55325f587f0fbecbb)
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=1738789107-h5waPjdRFNfyOq68HRsdnN0vTFY1AQUd-0-26e2f4f435eab4237d1e743f82562972)
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=1738789107-bFitom83CmwwV5mNCme2AEkOZMUqHXLC-0-69b801bc66edd69eda68b9602f92dd2c)
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=1738789107-yGUlGD0kcVsOZ5Xyn9ym6xF4EQ4zxrru-0-a7c0c3cd9ad04d4c64787de7ddb1b933)
图3-36 Rescaling分区效果示意
其使用如代码清单3-18所示。
代码清单3-18 DataStream中使用RescalingPartitioner
![](https://epubservercos.yuewen.com/AB30C5/19773741101350906/epubprivate/OEBPS/Images/73_05.jpg?sign=1738789107-LJPWeSTiWfjW4zHizeONRZkLB5p6ypo0-0-3f44ad33e83045364c1156b8920b94b5)
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=1738789107-xpa6OYFafqBziqjGq2KeVZGZUrx2PxUq-0-70a8b258d1253c54f18f8741297ce5ae)
7. KeyGroupStreamPartitioner
在API层面上,KeyGroupStreamPartitioner应用在KeyedStream,生成一个新的KeyedStream。
KeyedStream根据KeyGroup索引编号进行分区,该分区器不是提供给用户来用的。KeyedStream在构造Transformation的时候默认使用KeyedGroup分区形式,从而在底层上支持作业Rescale功能。