乐趣区

关于flink:深入解析-Flink-细粒度资源管理

细粒度资源管理的背景

目标

Flink 目前采纳粗粒度的资源管理办法,其中 task 被部署到预约义的、通常雷同的 slot 中,而不须要每个蕴含多少资源的概念。应用 slot 共享,能够将同一 slot 共享组 (SSG) 中的 task 部署到一个 slot 中,而不论每个 task/operator 须要多少资源。在 FLIP-56 中,咱们提出了细粒度资源管理,它依据工作负载的资源需要,利用具备不同资源的 slot 来执行 task。

对于许多 job 来说,应用粗粒度的资源管理并将所有 task 简略地放在一个 SSG 中就足够了,无论是在资源利用率还是可用性方面。

  • 对于所有 task 都具备雷同并行度的许多流式 job,每个 slot 将蕴含一个残缺的 pipeline。现实状况下,所有 pipeline 应该应用大致相同的资源,这能够通过调整雷同 slot 的资源轻松满足。
  • task 的资源耗费随工夫而变动。当一个 task 的耗费缩小时,额定的资源能够被另一个耗费减少的 task 应用。这被称为削峰填谷效应,缩小了所需的整体资源。

然而,在某些状况下,粗粒度的资源管理不能很好地工作。

  • task 可能有不同的并行度。有时,无奈防止这种不同的并行性。例如,source/sink/lookup task 的并行性可能会受到内部上游 / 上游零碎的分区和 IO 负载的限度。在这种状况下,具备较少 task 的 slot 将比具备整个 task pipeline 的 slot 须要更少的资源。
  • 有时,整个 pipeline 所需的资源可能太多,无奈放入单个 slot/task 管理器中。在这种状况下,pipeline 须要拆分为多个 SSG,它们可能并不总是具备雷同的资源需要。
  • 对于批处理 job,并非所有 task 都能够同时执行。因而,pipeline 的刹时资源需要随工夫而变动。

尝试应用雷同的 slot 执行所有 task 可能会导致非最佳资源利用率。雷同 slot 位的资源必须可能满足最高资源要求,这对于其余要求将是节约的。当波及到 GPU 等低廉的内部资源时,这种节约会变得更加难以承受。
因而,须要细粒度的资源管理,利用不同资源的 slot 来进步这种场景下的资源利用率。

现状

目前,FLIP-56 中提出的大部分 slot 调配和调度逻辑曾经实现,除了一个仍在进行中的 slot 管理器插件(FLINK-20835)。次要缺失的局部是用于指定 job 资源需要的用户接口。

有一些古老的代码用于设置转换算子资源并聚合它们以生成 slot 申请。然而,这些代码从未真正应用过,也没有向用户公开 API。最重要的是,咱们不确定让用户指定 operator 级别的资源需要并在运行时聚合它们是正确的办法,这将在后续局部中探讨。

范畴

此 FLIP 提出了基于 slot 共享组 (SSG) 的运行时接口,用于指定细粒度的资源需要。具体来说,咱们探讨了如何在 Transformation 层指定资源需要并在之后加以利用,这涵盖了 Table/SQL API 和 DataStream API 工作负载的公共门路。

因为以下起因,用于指定资源要求的最终用户接口被排除在本 FLIP 的范畴之外。

  • 细粒度的资源管理不是端到端的。咱们认为这应该是通过公开用户 API 来激活该性能的最初一步。
  • 不同的开发 API 可能会以不同的形式公开用于指定资源需要的接口。它须要与组件专家进行更深刻的探讨,以决定开发 API 应如何集成此性能。以下示例只是一些初步想法,用于演示用户接口在不同开发 API 中的外观。

    • 对于 DataStream API,曾经有为算子设置 SSG 的接口。基于此,咱们能够引入新的接口来间接指定 SSG 的资源需要。
    • 对于 Table API & SQL,因为没有裸露 operator 和 SSG 的概念,因而布局器可能应该生成 SSG 资源需要,只向用户裸露几个配置旋钮。

细粒度资源需要的粒度

在本节中,咱们将探讨应该以什么粒度指定细粒度的资源需要,这是设计运行时接口须要答复的最根本问题。具体来说,咱们探讨了三种设计方案的优缺点:为每个算子、task 或 slot 共享组指定资源要求。

用户故事

在深入研究设计选项之前,咱们想明确细粒度资源管理的用户故事,这有助于理解每个设计选项的优缺点如何影响咱们的指标用例。

咱们认为,细粒度的资源管理并不是对现有办法的代替,而是对管制 Flink 资源应用的用户参加范畴的扩大。用户能够依据他们的专业知识和要求抉择他们想要参加的水平。

  • 起码波及的选项是利用开箱即用的粗粒度资源配置。它应该实用于大多数简略的用例,尤其是对于尝试 Flink 的初学者。然而,资源利用通常不是最优的。
  • 在生产中,通常须要更多的用户参加,指定算子的并行度,配置粗粒度的 slot/taskmanager 资源,以及拆分 slot 共享组。
  • 对于粗粒度资源管理成果不佳的状况(如目标局部所述)细粒度资源管理为专家用户提供了一种进一步优化资源利用率的办法,办法是管制 pipeline 的每个特定局部应该应用多少资源应用,以更多的用户参加为代价。

算子粒度

如果为每个算子指定了细粒度的资源需要,那么 Flink 运行时须要聚合这些资源需要来生成 slot 资源需要,对于算子如何链接以及 task 如何共享 slot。

长处是:

  • 资源需要与算子链 /slot 共享之间的解耦。operator 资源需要独立于 operator 的链接形式以及 task 共享 slot 的形式。现实状况下,算子链和 slot 共享的更改不应要求用户从新指定资源需要。
  • 针对并行性差别的潜在优化。对于具备不同并行度的算子的 SSG,有机会应用 slot 中算子所需的资源来满足 slot 申请,这可能会以进一步提高 Flink 运行时的致力为代价,进一步提高资源利用率。

然而,也有一些毛病:

  • 用户参加过多。简单的工作可能蕴含数十甚至数百个 operator。为每个 operator 指定资源需要是不切实际的。
  • 难以反对混合资源需要。

    • 混合资源需要:有时用户可能只想为工作的某些局部指定资源需要,而未指定其余部分的需要,并冀望他们应用与粗粒度资源管理相似的资源。
    • 反对混合算子资源要求很艰难,因为具备指定和未指定资源要求的算子可能链接在一起或共享同一个 slot。很难通过聚合指定和未指定的 operator 需要来定义 slot 须要哪些资源。
  • 累积配置谬误。配置的资源需要和理论须要的资源之间总是存在偏差。算子越多,这种偏差的累积误差就越大,这可能会侵害资源的利用率。

留神:为 operator 资源要求设置默认值可能有助于缩小用户参加。然而,找出一个适合的默认值也很艰难,有时甚至是不可能的。不正确的默认值也可能放大累积配置谬误。

task 粒度

如果为每个 task 指定了细粒度的资源需要,那么 Flink 运行时须要裸露算子如何链接到 task 中,并聚合 task 资源需要以生成对于 task 如何共享 slot 的 slot 资源需要。

task 粒度形式的优缺点与算子粒度形式相似,但有以下区别。

  • task 是链式 operator,因而资源需要不再与算子链解耦。
  • task 比 operator 少,因而用户参加较少但依然过多,累积配置谬误。
  • 公开算子链。尽管 DataStream API 提供了接口来提醒应该如何链接算子,但残缺的算子链接策略依然在 Flink 的运行时外部。裸露 operator 在运行时如何被链接意味着对波及链接策略设置重大限度,因为任何导致不同链接后果的新更改都可能毁坏资源配置的向后兼容性。

slot 共享组粒度

通过为每个 SSG 指定细粒度的资源需要,Flink 运行时能够间接申请具备所需资源的 slot。它克服了算子 /task 粒度办法的毛病。

  • 灵便的用户参加 。须要多少用户致力取决于用户定义了多少 SSG。SSG 越多,须要指定的资源需要就越多。
  • 反对混合资源需要 。因为需要在 SSG 上,因而无需放心具备混合需要的 operator/task 被链接在一起或共享同一个 slot。FLIP-56 曾经反对从同一 TM 调配具备混合要求的 slot。具备未指定要求的 slot 申请将由与粗粒度资源管理中的等效资源来满足。
  • 较少的累积配置谬误 。同一 SSG 内的 operator 之间的削峰填谷效应应该会缩小所需的整体资源。

此外,基于 SSG 的办法还有助于简化零碎。

  • 指定的资源需要能够间接用于 slot 调配。不须要进一步的解决 / 转换 / 聚合。
  • 试图认真决定每个算子 /task 应该应用多少资源(CPU、堆内存等)不会在运行时执行中失效,因为除了托管内存之外,slot 内的算子 /task 之间没有资源隔离。
  • 对于托管内存,FLIP-53 和 FLIP-141 曾经引入了一种基于分数的办法,用于在 slot 内共享托管内存。裸露更多用于管制 operator/task 内存的旋钮可能会毁坏现有办法,或者至多会使零碎复杂化。

与算子 /task 粒度办法相比,这种办法有以下毛病。

  • 资源需要和算子链 /slot 共享之间的耦合。如果 SSG 发生变化,无论是用户明确指定的还是因为算子链 /slot 共享策略的变动,指定的资源需要也须要调整。
  • 针对并行性差别的用户参加。对于具备不同并行度的算子的 SSG,不蕴含所有算子的子 task 的 slot 可能会占用比须要的资源多。为了针对这个问题进步资源利用率,用户须要将具备不同并行度的算子分成不同的 SSG。

概括

粒度 长处 毛病
operator 资源需要与算子链 /slot 共享之间的解耦。针对并行性差别的潜在优化。 用户参加过多。难以反对混合资源需要。累积配置谬误。
task 资源需要和 slot 共享之间的解耦。针对并行性差别的潜在优化。与 operator 粒度相比,更少的用户参加和累积的配置谬误。 难以反对混合资源需要。依然有太多的用户参加和累积的配置谬误。公开算子链。
slot 共享组 灵便的用户参加。反对混合资源需要。较少的累积配置谬误。简化零碎。 资源需要和算子链 /slot 共享之间的耦合。针对并行性差别的用户参加。

上表总结了三种设计方案的优缺点。

通过以上利弊,咱们看到了一个重要的底层事实,这也是咱们抉择基于 SSG 的形式最有说服力的理由, 即 Slot 是 Fink 运行时资源管理的根本单元

  • 资源需要的粒度应该对应于它们在运行时的实现形式。依据 slot 调配的要求,从任何其余粒度转换到 slot 资源要求将减少零碎复杂性。
  • 运行时接口应该只须要资源管理所需的起码信息集,为开发 API 留出更大的灵活性。开发 API 将用户提供的 operator/task 要求(如果这是向最终用户公开的内容)聚合到 slot 位要求比从用户提供的 slot 位要求中组成 operator/task 要求更间接。

综上所述,在这个 FLIP 中,咱们提出了基于 SSG 的运行时接口,用于配置细粒度的资源需要,因为它与运行时资源的治理形式绝对应,从而具备可用性、效率和简略性。与收益相比,咱们认为毛病影响较小:算子链和 slot 共享策略不会常常以影响资源需要的形式变动,用户参加与并行差别是可用性和资源利用率之间的衡量用户来决定。

提议的变更

本 FLIP 中提出的更改非常简单。

  • 引入用于指定基于 SSG 的资源要求的运行时接口。
  • 调配具备指定资源要求的 slot。

运行时接口

作为对立运行时的入口点,从用户开发 API 中 StreamGraphGenerator 获取各种设置,并相应地生成。TransformationsStreamGraph 咱们倡议增加以下接口来指定 SSG 的细粒度资源需要。

public class StreamGraphGenerator {
    /**
     * Specify fine-grained resource requirements for slot sharing groups.
     *
     * <p>Note that a slot sharing group hints the scheduler that the grouped operators CAN be
     * deployed into a shared slot. There's no guarantee that the scheduler always deploy the
     * grouped operator together. In cases grouped operators are deployed into separate slots,
     * the slot resources will be derived from the specified group requirement.
     */
    public StreamGraphGenerator setSlotSharingGroupResource(Map<String, ResourceProfile> slotSharingGroupResources);
}

指定的 SSG 资源需要须要始终传递到对应 SlotSharingGroup 的 ExecutionGraph。

slot 调配

目前,SSG 的 slot 申请由 SlotSharingExecutionSlotAllocator. 咱们倡议 SlotSharingExecutionSlotAllocator 利用相应的资源需要 SlotSharingGroups 来生成 slot 申请。

相干问题

网络内存

网络内存蕴含在以后的 ResourceProfile 实现中,冀望细粒度的资源管理不会将太多的 task 部署到须要比 TM 蕴含的更多网络内存的 TM 上。
然而,每个 task 须要多少网络内存很大水平上取决于 shuffle 服务的实现,并且在切换到另一个 shuffle 服务时可能会有所不同。因而,目前无论是用户还是 Flink 运行时都无奈轻松指定 task/slot 的网络内存需要。网络内存管制的具体解决方案超出了本 FLIP 的范畴。然而,咱们晓得解决这个问题的一些潜在方向。

  • 绝对于给定的内存池大小,使 shuffle 服务自适应地管制调配给每个 task/slot 的内存量。这样,就不须要依赖细粒度的资源管理来管制网络内存耗费。
  • 让 shuffle 服务公开用于计算给定 SSG 的网络内存需要的接口。通过这种形式,Flink 运行时能够指定计算出的针对 slot 的网络内存需要,而无需理解不同 shuffle 服务实现的外部细节。

目前,咱们在 FLINK-20863 中倡议临时排除网络内存 ResourceProfile,以解除对网络内存管制问题的细粒度资源管理性能的妨碍。如果须要,它能够在将来增加回来,只有有一个好的办法来指定需要。

资源匹配

目前,ResourceProfile::isMatching 应用以下规定(以下称为涣散匹配)来决定是否能够应用 slot 资源来满足给定的资源需要,在 SlotManager 和中 SlotPool:

  • 任何资源都能够满足未指定的要求 ()。ResourceProfile::UNKNOWN
  • 任何大于或等于本身的资源都能够满足指定的需要。请留神,此规定未失效,因为没有指定要求 atm。

在动静 slot 调配之前设计了涣散匹配规定。在 slot 的资源在 TM 启动时就已确定且不可更改的假如下,涣散匹配规定具备以下长处。

  • 对于独立部署,它容许在预启动的 TM 的 slot 简直没有确切所需的资源时满足 slot 申请。
  • 对于流动资源管理器部署,它减少了 slot 被重用的机会,从而升高了为各种资源需要启动新 TM 的老本。

随着 FLIP-56 中引入的动静 slot 调配,涣散匹配规定的益处已大大降低。因为 slot 能够在 TM 启动后动态创建,只有可用任何所需的资源,涣散匹配规定保留的惟一益处是防止在 slot 能够在 JM 端重用时调配新 slot,这无关紧要,因为无需启动新的 TM。

另一方面,涣散匹配规定也引入了一些问题。

  • 重复使用较大的 slot 来满足较小的要求可能会侵害资源利用率。
  • 在匹配一组需要和 slot 时,在 job 故障转移或申明性 slot 调配协定的状况下,总是找到一个可行的匹配解决方案(假如有一个)并不简略。

上图展现了如何在涣散匹配规定下找不到可行的匹配解决方案。假如有两个资源需要 A 和 B,并且有两个 slotX 和 Y。每个 Requirement/Slot 上面的数字代表资源的数量。那么 A 能够用 X 和 Y 来满足,而 B 只能用 Y 来满足。右边显示了一个可行的匹配,这两个条件都能够满足。然而,涣散匹配规定也可能导致另一个匹配,如右侧所示,其中 A 由 Y 满足,而 B 和 X 不匹配。

鉴于其益处的缩小和它引入的问题,咱们在 FLINK-20864 中提出用以下准确匹配规定替换涣散匹配规定。

  • 未指定的要求 (ResourceProfile::UNKNOWN) 只能由 TM 的默认 slot 资源来满足。
  • 指定的要求只能由与其本身相等的资源来满足。

资源死锁

上图演示了因为调度依赖性导致的潜在死锁状况。对于给定的拓扑,最后调度程序将申请 4 个 slot,别离用于 A、B、C 和 D。假如只有 2 个 slot 可用,如果两个 slot 都调配给 pipeline 区域 0(如左图所示),A 和 B 将先实现执行,而后执行 C 和 D,最初执行 E。然而,如果一开始将 2 个 slot 调配给 A 和 C(如右图所示),那么 A 和 C 都无奈实现执行,因为短少 B 和 D 耗费了它们产生的数据。

目前,通过粗粒度的资源管理,调度程序保障在开始满足另一个 pipeline 区域的要求之前总是实现满足一个 pipeline 区域的要求。这意味着上图右侧所示的死锁状况永远不会产生。

然而,细粒度的资源管理没有这样的保障。因为 SSG 的资源要求可能不同,因而当没有足够的资源来满足所有要求时,无法控制首先满足哪些要求。因而,并不总是能够先实现一个 pipeline 区域。

为了解决这个问题,FLINK-20865 倡议让调度程序在以后 SSG 的要求失去满足之前推延其余 SSG 的申请 slot,以进行细粒度的资源管理,但代价是更多的调度工夫。

反馈式调度

咱们晓得细粒度的资源管理可能不容易与反馈式调度一起应用,这是一个仍在布局中的将来性能,它依据可用资源决定执行的并行度(如 FLIP-138 中所述)。
为了使细粒度的资源管理与反馈式调度一起工作,一个重要的悬而未决的问题是,当没有足够的资源来满足所有资源需要时,应该首先满足哪些资源需要。

上图左侧显示了一个指标执行打算,A 和 B 各须要 4 个 slot。右侧有 3 种可能的状况,无奈满足所有资源需要。

  • 在状况 1 中,咱们取得了大概一半的指标解决能力。
  • 在状况 2 中,咱们可能只能失去指标解决能力的 1/4 左右,受到 B 的限度。
  • 在状况 3 中,job 根本无法执行。

正如咱们所见,在资源有余的状况下如何满足资源需要会显着影响 Flink 的性能,甚至可用性。当波及更简单的指标执行打算时,它可能会变得更加简单,具备异构的指标并行性和调度依赖性。

作为第一步,咱们不反对细粒度资源管理的反馈式调度。

未来,该问题可能会通过以下方向失去解决。

  • 调度器能够为每个 slot 资源申明一对最小 / 指标所需的 slot 数。这样,咱们应该始终尝试为执行 job 调配起码的资源集。这应该有助于在可能的状况下防止最坏的状况(上例中的状况 3)。
  • 咱们也可能依赖调度器来检测非最优状况(上例中的状况 2 和 3),并调整申明的资源需要并返回不必要的资源。

要记录的已知限度和束缚

当向用户提供细粒度资源管理性能时,应具体记录以下限度和束缚,以及潜在的影响和倡议。

  • 将可链接算子设置为不同的 SSG 可能会毁坏算子链,从而扭转性能。
  • 在 SSG 中更改数据交换模式(流水线与阻塞)可能会影响组的资源需要。
  • 同一 SSG 中的算子之间的并行度差别可能会升高资源利用率。

欢送关注 gzh HEYDATA 一起交换更多。

退出移动版