paint-brush
Apache Doris 中的工作负载隔离:优化资源管理和性能by@frankzzz
315
315

Apache Doris 中的工作负载隔离:优化资源管理和性能

Frank Z10m2024/05/25
Read on Terminal Reader

Apache Doris 支持基于 Resource Tag 和 Workload Group 的工作负载隔离,针对隔离级别、资源利用率、稳定性能之间的不同权衡提供了解决方案。
featured image - Apache Doris 中的工作负载隔离:优化资源管理和性能
Frank Z HackerNoon profile picture
0-item
1-item


这是对Apache Doris工作负载隔离功能的深入介绍。但首先,为什么以及何时需要工作负载隔离?如果您遇到以下任何一种情况,请继续阅读,您将找到解决方案:


  • 您有不同的业务部门或租户共享同一个集群,并且您希望防止工作负载干扰。


  • 您有不同优先级的查询任务,并且您希望在资源和执行方面优先考虑您的关键任务(例如实时数据分析和在线交易)。


  • 您需要工作负载隔离,但也希望获得较高的成本效益和资源利用率。


Apache Doris 支持基于 Resource Tag 和 Workload Group 的工作负载隔离。Resource Tag 在后端节点级别对不同工作负载进行 CPU 和内存资源隔离,而 Workload Group 机制可以进一步划分后端节点内的资源,从而提高资源利用率。

基于 Resource Tag 的资源隔离

首先介绍一下 Apache Doris 的架构。Doris 有两种类型的节点:前端(FE)和后端(BE)。FE 节点存储元数据、管理集群、处理用户请求和解析查询计划,而 BE 节点负责计算和数据存储。因此,BE 节点是主要的资源消耗者。


基于 Resource Tag 的隔离方案主要思想是通过为集群中的 BE 节点分配标签,将计算资源分成几组,相同标签的 BE 节点组成一个 Resource Group。Resource Group 可以看作是数据存储和计算的单位。对于接入 Doris 的数据,系统会根据配置将数据副本写入不同的 Resource Group。查询也会被分配到相应的Resource Group中执行。


例如,如果您想在 3-BE 集群中分离读写工作负载,可以按照以下步骤操作:


  1. 为 BE 节点分配资源标签:将 2 个 BE 绑定到“读取”标签,将 1 个 BE 绑定到“写入”标签。


  2. 为数据副本绑定资源标签:假设表1有3个副本,将其中2个副本绑定“读”标签,1个副本绑定“写”标签。写入Replica 3的数据会与Replica 1和Replica 2同步,数据同步过程消耗BE 1和BE2的资源较少。


  3. 为工作负载组分配资源标签:SQL 中包含“Read”标签的查询将自动路由到带有“Read”标签的节点(本例中为 BE 1 和 BE 2)。对于数据写入任务,您还需要为其分配“Write”标签,以便将其路由到相应的节点(BE 3)。这样,除了副本 3 到副本 1 和 2 的数据同步开销外,读写工作负载之间不会发生资源争用。



Resource Tag 还可以在 Apache Doris 中实现多租户功能。例如,标记为“用户 A”的计算和存储资源是用户 A 独享的,标记为“用户 B”的计算和存储资源则是用户 B 独享的。这就是 Doris 在 BE 端通过 Resource Tag 实现多租户资源隔离的方式。



将 BE 节点分成几组可确保高水平的隔离


  • 不同租户的CPU、内存、I/O物理隔离。


  • 一个租户永远不会受到另一个租户的故障(例如进程崩溃)的影响。


但它也有一些缺点:


  • 读写分离时,当数据写入停止时,标记为“Write”的BE节点将处于空闲状态,从而降低集群整体利用率。


  • 在多租户下,如果想通过为每个工作负载分配单独的BE节点来进一步隔离同一租户的不同工作负载,则需要承受巨大的成本和较低的资源利用率。


  • 租户数量与数据副本数量相关。因此,如果您有 5 个租户,则需要 5 个数据副本。这是巨大的存储冗余。


为了改进这一点,我们在 Apache Doris 2.0.0 中提供了基于 Workload Group 的工作负载隔离解决方案,并在Apache Doris 2.1.0中对其进行了增强

基于工作负载组的工作负载隔离

基于Workload Group的方案实现了更细粒度的资源划分,将 CPU 和内存资源进一步划分到 BE 节点上的进程内,使得同一 BE 节点内的查询可以实现一定程度的相互隔离,避免 BE 进程内的资源竞争,优化资源利用率。


用户可以将查询关联到 Workload Group,从而限制查询可使用的 CPU 和内存资源百分比。在集群负载较高时,Doris 可以自动终止 Workload Group 中最耗资源的查询。在集群负载较低时,Doris 可以让多个 Workload Group 共享闲置资源。


Doris 支持 CPU 软限制和 CPU 硬限制,软限制可以让 Workload Group 突破限制,利用闲置资源,实现更高效的利用;硬限制可以避免 Workload Group 之间相互影响,是性能稳定的硬保障。


(CPU软限制和CPU硬限制是互相矛盾的,您可以根据自己的使用情况进行选择。)


它与基于资源标签的方案的区别在于:


  • 工作负载组在进程内形成。多个工作负载组在同一个 BE 节点内竞争资源。


  • 由于工作负载组只是一种资源管理方式,因此无需考虑数据副本分布。

CPU 软限制

CPU 软限制由cpu_share参数实现,该参数在概念上类似于权重。具有较高cpu_share的工作负载组将在某个时间段内分配更多 CPU 时间。


例如,如果组 A 的cpu_share配置为 1,组 B 的 cpu_share 配置为 9。在 10 秒的时间段内,当组 A 和组 B 都满载时,组 A 和组 B 将分别能够消耗 1 秒和 9 秒的 CPU 时间。


实际情况是,集群中并非所有工作负载都以满负荷运行。在软限制下,如果组 B 的工作负载较低或为零,则组 A 将能够使用所有 10s CPU 时间,从而增加集群中的整体 CPU 利用率。



软限制带来了灵活性和更高的资源利用率。但另一方面,也可能导致性能波动。

CPU 硬限制

Apache Doris 2.1.0 中的 CPU 硬限制是针对需要稳定性能的用户而设计的。简单来说,CPU 硬限制定义了 Workload Group 使用的 CPU 资源不能超过其限制,无论是否有空闲的 CPU 资源。


工作原理如下:


假设组 A 设置了cpu_hard_limit=10% ,组 B 设置了cpu_hard_limit=90% 。如果组 A 和组 B 都满负荷运行,那么组 A 和组 B 将分别使用整体 CPU 时间的 10% 和 90%。区别在于组 B 的工作负载何时减少。在这种情况下,无论组 A 的查询负载有多高,它都不应使用超过分配给它的 10% 的 CPU 资源。




与软限制相反,硬限制以灵活性和更高的资源利用率的可能性为代价来保证系统的稳定性能。

内存资源限制

BE节点的内存由以下部分组成:


  • 为操作系统保留的内存。


  • 非查询所消耗的内存,不包含在工作负载组的内存统计中。


  • 查询(包括数据写入)会消耗内存。这可以通过工作负载组进行跟踪和控制。


memory_limit参数定义 BE 进程中工作负载组可用的最大内存 (%)。它还会影响资源组的优先级。


初始状态下,高优先级的 Resource Group 会被分配较多的内存。通过设置enable_memory_overcommit ,可以允许 Resource Group 在有空闲空间时占用超过 limits 的内存。当内存紧张时,Doris 会取消任务以回收它们 commit 的内存资源。此时系统会尽可能的为高优先级的资源组保留更多的内存资源。



查询队列

有时集群承担的负载超过其处理能力。在这种情况下,提交新的查询请求不仅毫无意义,而且还会中断正在进行的查询。


为了改善这一点,Apache Doris 提供了查询队列机制,用户可以限制集群中并发运行的查询数量,当查询队列已满或者等待超时后,查询将被拒绝,从而保证系统在高负载下的稳定性。



查询队列机制涉及三个参数: max_concurrencymax_queue_sizequeue_timeout

测试

为了证明 CPU 软限制和硬限制的有效性,我们做了一些测试。


  • 环境:单机,16核,64GB


  • 部署:1 FE + 1 BE


  • 数据集:ClickBench,TPC-H


  • 负载测试工具:Apache JMeter

CPU软限制测试

启动两个客户端,分别在有和没有使用 Workload Groups 的情况下持续提交查询(ClickBench Q23)。注意关闭 Page Cache,以免影响测试结果。


比较两次测试中两个客户端的吞吐量,可以得出结论:


  • 如果不配置工作负载组,两个客户端将平等地消耗 CPU 资源。


  • 配置 Workload Groups并将cpu_share设置为 2:1,两个客户端的吞吐量比率为 2:1。cpu_share cpu_share ,客户端 1 获得的 CPU 资源份额就越大,从而提供更高的吞吐量。

CPU硬限制测试

启动客户端,设置Workload Group的cpu_hard_limit=50% ,分别在并发数1、2、4下执行ClickBench Q23 5分钟。



随着查询并发性的增加,CPU 利用率保持在 800% 左右,这意味着使用了 8 个核心。在 16 核的机器上,利用率为 50% ,这是预期的。此外,由于施加了 CPU 硬限制,随着并发性的增加,TP99 延迟的增加也是预期的结果。

在模拟生产环境中进行测试

在实际使用中,用户特别关注的是查询延迟,而不仅仅是查询吞吐量,因为延迟在用户体验中更容易被察觉。这就是为什么我们决定在模拟生产环境中验证工作负载组的有效性。


我们挑选了一组需要在 1s 内完成的查询(ClickBench Q15、Q17、Q23 和 TPC-H Q3、Q7、Q19),包括单表聚合和连接查询。TPC-H 数据集的大小为 100GB。


同样,我们在配置和不配置工作负载组的情况下也进行了测试。


结果显示:


  • 没有工作负载组(比较测试 1 和 2):当拨打客户端 2 的并发时,两个客户端的查询延迟都会增加 2 到 3 倍。


  • 配置工作负载组(比较测试3和4):随着客户端2的并发度上升,客户端1的性能波动要小得多,这证明了它受到了工作负载隔离的有效保护。

建议和计划

基于Resource Tag的方案是一套完善的工作负载隔离方案,基于Workload Group的方案在资源隔离和利用率上实现了更好的平衡,并辅以查询队列机制来保证稳定性。


那么,您应该根据自己的用例选择哪一个?以下是我们的建议:


  • 资源标签:适用于部门不同业务线共享同一集群的用例,因此不同租户的资源和数据在物理上是隔离的。


  • 工作负载组:适用于一个集群承担各种查询工作负载以实现灵活资源分配的用例。


在未来的版本中,我们将继续改进工作负载组和查询队列功能的用户体验:


  • 通过取消查询来释放内存空间是一种粗暴的手段,我们计划通过磁盘溢出的方式来实现,这将带来更高的查询性能稳定性。


  • 由于 BE 中非查询所消耗的内存未包含在工作负载组的内存统计信息中,因此用户可能会发现 BE 进程内存使用量与工作负载组内存使用量之间存在差异。我们将解决此问题以避免混淆。


  • 在查询队列机制中,通过设置最大查询并发量来控制集群负载。我们计划根据 BE 端的资源可用性启用动态最大查询并发量。这在客户端造成反压,从而在客户端持续提交高负载时提高 Doris 的可用性。


  • Resource Tag 的主要思想是对 BE 节点进行分组,而 Workload Group 的主要思想是对单个 BE 节点的资源进行进一步划分。要掌握这些思想,用户首先需要了解 Doris 中 BE 节点的概念。但从操作角度来看,用户只需要了解每个工作负载的资源消耗百分比,以及集群负载饱和时它们应该具有什么优先级。因此,我们会尝试找出一种方法来降低用户的学习曲线,比如将 BE 节点的概念放在黑匣子里。


如需有关 Apache Doris 中工作负载隔离的进一步帮助,请加入Apache Doris 社区