数据交换策略
数据交换策略(Data Exchange Strategy)定义了数据如何被分配到物理数据流图的 Task 中的。数据交换策略可以由执行引擎根据算子的语义自动选择,也可以由数据流程序显式施加。因此,我们简要回顾下常见的几种数据交换策略:
- Forward:该策略把数据从一个 Task 发送到另一个接收 Task。如果这两个 Task 位于同一台物理机上(通常用任务调度器保证),则该策略可以避免网络通信。
- Broadcast:该策略把数据发送到算子所有并行的 Task 上。因为该策略需要复制数据,并涉及网络通信,所以成本比较高。
- Key-Based:该策略把数据按照 Key 进行分区,并且保证具有相同 Key 的数据会被划分到相同的 Task 上。
- Random:该策略将数据项均匀地分配到 Task 中,以使负载均匀地分布在计算任务之间。
分区转换
分区转换对应于数据交换策略。该操作定义了事件如何被分配到 Task。当使用 DataStream API 构建应用程序时,系统自动地选择数据分区策略,并依据操作语义和配置的并发度将数据路由到正确的 Task。有时有必要在应用程序层面控制分区策略,或者自定义分区器。例如,如果我们已经知道 DataStream 的并行分区的负载是倾斜的,我们可能希望重新平衡数据,以便均匀地分配后续操作符的计算负载。或者,应用程序逻辑要求执行的所有 Task 都接收相同的数据,又或者要求事件按照自定义的策略分布。在本节中,我们将展示用户可以操作的 DataStream 方法或者定义他们自己的方法。
注意:KeyBy() 和本节讨论的分区转换是不同的。本节讨论的转换都会产生一个 DataStream,而 KeyBy() 产生的是 KeyedStream,并可以在它上应用访问 Keyed-state 的转换。
Random
Random 数据交换策略通过 DataStream.shuffle() 实现。该方法按照均匀分配的原则,随机地将数据分配到下游算子的并行 Task 中。
Round-Robin
rebalance() 方法对输入流进行分区,以便以 Round-Robin 方式将事件均匀地分配到下下游 Task。
Rescale
rescale() 也以 Round-Robin 的方式分配数据,但是它只分配给下游 Task 的子集。本质上,当发送者和接收者的 Task 数量不同时,Rescale 策略提供了一种执行轻量级负载重新均衡的方式。如果接收者的 Task 数量是发送者的 Task 数量的倍数,则 Rescale 转换会更有效,反之亦然。
rebalance() 和 rescale() 本质的不同在于 Task 的连接方式上。rebalance() 在所有发送 Task 和接收 Task 间创建通信通道,而 rescale() 仅仅创建从每个 Task 到下游算子的某些 Task 通信通道。
Broadcast
broadcast() 复制输入数据流,为了将所有数据发送到下游算子的所有并行的 Task 上。
Global
globa() 发送所有输入数据流到下游算子的第一个并行 Task。该分区策略必须谨慎使用,因为将所有数据路由到同一个 Task 可能会影响应用程序性能。
Custom
当预定义的分区策略没有一个适合使用时,你可以使用 partitionCustom() 定义自己的策略。该方法接收一个 Partitioner 对象,该对象实现分区逻辑和在被分区流上的字段或键的位置。