粗粒度资源管理
- Apache Flink 1.1.4版本之前使用的是粗粒度的资源管理,即每个算子Slot Request所需要的资源都是未知的,Flink内部用UNKNOWN的特殊值来表示,这个值可以和任意资源规则的物理Slot匹配,站在Taskmanager的角度,他拥有的Slot个数与Slot资源是根据Flink的配置决定的。如下案例:
- 以上Flink处理kafka source 数据map处理 sink到 Redis中,可能需要三个task ,分别对应source, map,sink
- 粗粒度的资源控制,简单的将所有task任务运行在同一个SlotSharingGroup(SSG)就可以横好利用资源,因为我们这个链路中并发度上下游是完全一样的。此时我们只需要调整默认的Slot配置及可以达到很高的资源利用率
- 同时由于不同Task特点峰值不一定相同,当一个任务消耗减少,额外资源可以被另外一个消耗增加的任务使用,这被称为削峰填谷效应,通过这种效应,将不同task放到同一个大的slot里面,可以进一步降低整体的资源开销。
- 简单任务的粗粒度资源调度特点 如下:
- 对于所有任务具有相同的并行度的作业处理,每个slot将包含一个完整的管道,理想情况下,所有管道应该使用大致相同的资源,这可以通过调整相同Slot的资源轻松满足(所有任务资源要求一致)
- 任务资源消耗随着时间变化而变化,当一个任务消耗减少时候,额外的资源可以被另外一个消耗增加的任务使用,这被称为削峰填谷效应,减少所需要的整体资源(flink自己的优化)
粗粒度资源管理的弊端
-
任务流程每个处理节点并行度不同而且差距很大
-
任务流程每个处理节点资源要求相差很大比如Source/Sink/转换操作的tasks并行性可能受到外部上下游系统分区和IO负载的限制。有的计算密集型需要更多CPU,有的存储资源使用密集型需要更多内存,有的需要GPU
-
对于批处理作业,并非所有任务都可以同时执行,因此,管道的顺势资源需求随时间变化而变化
-
当整个管道需要资源非常庞大,单Slot/TaskManager无法提供,在这种情况下,需要将管道拆分成多个SSG(SlotSharingGroup),这些SSG可能并不总是具有相同的资源需求。
-
总结:用相同资源设置的Slot执行所有任务可能造成资源的浪费。应为每个Slot都是相同的资源必须,那么这个Slot必须满足于流程处理中最高要求的节点处理,当某个节点处理需要用到GPU时候,这种浪费就变得不可接受了。
细粒度资源管理
-
用如下案例解释粗粒度到细粒度资源管理的优势和流程
-
如上案例,Flink处理流转关系图中有两个128并发的Kafka Source和一个32并发的Redis ,上下两路数据处理路径,一条是两个Kafka Source经过Join以后在经过一些AGG聚合操作,最后将数据Sink到16并发的Kafka中;另一个链路Kafka Source 和Redis 进行Join,结果流入到一个鹅机遇TensorFlow的处理模块,最终存储到8个并发的Redis中。
-
以上作业并发不一致,如果统一Slot资源只能是128并发
-
对于较重的资源消耗的算子,导致很高的资源浪费(主要是内存),比如,Redis需要将数据缓存到内存提高性能,聚合则需要大量的managed memory存储state,对于这两本了只要申请32 和16份资源,对其后需要128份,那么多余的slot中内存资源就浪费了。
-
整个作业的pipelink可能由于资源过大无法无法放到一个slot或者TM中。再比如GPU资源保障计算效率,如果没有这么多GPU那么久无法申请到资源,久没办法执行
粗粒度优化成细粒度
- 以上,将算子按照并发度分成4个SSG,保证每个SSG内部并发是对齐的,但是由于每个slot只有一种默认规格,依然需要将该Slot的所有资源为度都对齐到对应SSG的最大值,比如内存需要和Redis维表的需求对齐,managed momory需要和聚合算子对齐,甚至扩展资源中都需要加入一块GPU,这依然不能解决资源浪费问题
- 为了解决以上问题,再次优化细粒度资源管理,让每一个Slot的资源规格都可以单独设置,用户安需申请,最大化资源利用率,细粒度资源管理就是通过作业让每个模块安需申请和使用资源来提高资源整理利用率
细粒度资源适用场景
- 作业中上下游task并发有明显的差异
- 整个任务pipeline需要的资源太多,无法放入单个Slot/TaskManager中
- 批作业,不同Stage消耗资源有明显的差异。
- 以上几个,都需要拆分多个SSG,不同SSG资源存在差异,这时候,通过细粒度资源管理久能减少资源浪费了。
细粒度资源原理
- Flink架构,TaskManager会划分多个Slot资源,Slot是Flink运行时候进行资源考度和分配的基本单元
- Flink 高版本1.1.4之后,用户可以指定配置Slot资源,完成配置后,Flink根据用户资源配置从TaskManager中动态剪切一个完全匹配的Slot,如下图,需要一个具有0.25Core 和1GB内存的Slot,Flink为分配Slot1
- 如果我设置TaskManager的时候不知道具体的Slot分配资源,他会安默认情况配置自动决定资源配置,默认情况TaskManager总资源和TaskManager.numberOfTaskSlots计算的,就和粗粒度一样了。
- 以下是一个完整的细粒度配置,TaskManger分配Slot1,Slot2,TaskManager中甚于的可用内存为0.25Core 和1G内存,这些空闲资源可以进一步划分,以满足他资源需求。
资源分配策略-动态资源切割机制
- Flink对每一个SSG进行资源分配采用的都是动态资源切割机制,以下案例分析:
-
如上图:TaskManager在切割的时候,
- 首先Taskmanager适用全部资源启动,但是没有预定义的Slot,
- 当有一个具有0.25Core的1GB内存的请求到达时,Flink将选择一个具有足够空闲资源的TaskManager来完成Slot请求,
- 当没有足够可用资源的TaskManager的时候,Flink会Native Kubernetes或者YARN上时尝试分配新的TaskManager
-
预定义配置方式会有如下问题:
- 集群中可能存在资源碎片:因为我们是自定义,如果有两Slot请求,每个Slot具有3G堆内存,但是TaskManager总内存是4G,那么Flink将会启动两个TaskManger,每个TaskManager中会有1G内存浪费,(这种情况Flink还解决不了,以后可能会优化。)
- 请确保为Slot共享自建配置的资源数量不超过TaskManager的资源总量。否则FlinkJob将异常失败。
-
通过以上案例,再来细分一下资源:
- 在集群中,进行资源分配:
- SSG1 中并发最大,CPU要求高,那么给2Core。1G
- SSG2 内存要求高,那么给。1Core。4G
- SSG3中Manager memory 要进行State的存储,内存要求高,那么给 1Core 8G
- SSG4 中要求图形计算,那么给GPU,那么资源给。 1Core,1G,1GPU
Flink细粒度资源管理局限性
- 是一项新的实验性功能
- 不支持评价分配Slot策略:这个策略让所有可能的Taskmanager上平均分配Slot,
- 与Flink的WebUI集成有限:细粒度资源管理中的Slot可以具有不同资源规格,webUI目前不限制Slot详细信息
- 与批处理作业有限集成:目前,细粒度资源管理要求在所有边缘类型都被阻塞Blocking的情况下处理工作负载,为此,需要配置fine-grained.shuffle-mode.all-blocking = true,会影响性能。详见FLINK-20865。
- 不建议配置混合资源:不建议仅仅为作业的某些部分指定资源需求,而未制指定其余部分的资源需求,目前任何资源的Slot都可以满足未指定的需求,他获取的时机资源可能在不同的作业执行或故障切换中不一致
- Slot分配结果可能不是最优的:由于Slot需求包含多个维度的资源,默认的资源分配策略可能无法实现最优的Slot分配,某些场景下可能会导致资源分片资源分配失败