我有一个Flink应用程序运行在亚马逊的Kinesis数据分析服务(托管的Flink集群(中。在应用程序中,我从Kinesis流keyBy userId中读取用户数据,然后聚合一些用户信息。在问了这个问题之后,我了解到Flink将在集群中的物理主机之间分配流的读取。Flink随后将传入事件转发给主机,该主机将聚合器任务分配给与给定事件相对应的密钥空间。
考虑到这一点,我正在努力决定使用什么作为Kinesis流的分区键,我的Flink应用程序从中读取。我的目标是限制Flink集群中主机之间的网络流量,以优化我的Flink应用程序的性能。我可以随机分区,使事件均匀分布在碎片上,也可以按userId对碎片进行分区。
这个决定取决于Flink内部的工作方式Flink是否足够聪明,可以为主机上的本地聚合器任务分配一个密钥空间,该密钥空间将与同一主机上Kinesis消费者任务正在读取的碎片的密钥空间相对应如果是这种情况,那么按userId进行分片会导致ZERO网络流量,因为每个事件都是由聚合它的主机流式传输的。Flink似乎没有明确的方法来做到这一点,因为它不知道Kinesis流是如何分片的。
或者,Flink是否随机为每个Flink消费者任务分配一个子集的碎片来读取,并随机为聚合器任务分配一部分密钥空间 如果是这种情况,那么碎片的随机分区似乎会导致最少的网络流量,因为至少一些事件将由与事件聚合器任务位于同一主机上的Flink消费者读取。这比按userId进行分区,然后必须通过网络转发所有事件要好,因为碎片的keySpace与本地聚合器分配的密钥空间不一致。
10年前,通过网络传输尽可能少的数据非常重要。自5年以来,网络变得如此之快,以至于你会注意到通过网络或内存访问一大块数据之间几乎没有什么区别(随机访问当然仍然快得多(,所以我不会为额外的流量而担心(除非你必须为此付费(。有趣的是,谷歌数据流开始在两个任务之间将所有数据流传输到一个中央洗牌服务器,有效地将流量增加了一倍;但他们仍然在Petabyte网络上体验到巨大的加速。
考虑到这一点,让我们转到Flink。Flink目前无法动态调整碎片,因为它们可能会随着时间的推移而来来去去。在FLIP-27的半年内,情况可能会有所不同。
目前,有一种变通方法,目前主要用于Kafka土地(静态分区(。DataStreamUtils#reinterpretAsKeyedStream
允许您在没有物理混洗的情况下指定逻辑keyby
。当然,您有责任确保所提供的分区与现实相一致,否则会得到不正确的结果。