使用 Resource Groups 管理资源
Resource Group(资源组)可用来管理和保护 Apache Cloudberry 中 CPU、内存、并发事务限制和磁盘 I/O 的资源分配。定义资源组后,可将该组分配给一个或多个 Apache Cloudberry 用户角色(Role),或分配给外部组件(如 PL/Container),以控制其使用的资源。
一个资源组所定义的限制条件适用于所有被分配该资源组的用户角色。例如,资源组定义的最大内存使用量限制会应用于所有该组用户所提交的运行事务上。
Apache Cloudberry 使用基于 Linux 的控制组来管理 CPU 资源,并使用 Runaway Detector 进行统计、跟踪和内存管理。
理解角色和组件资源组
Apache Cloudberry 支持两种类型的资源组:用于管理角色资源的组,及用于管理外部组件(如 PL/Container)资源的组。
资源组的最常见应用是管理不同角色在 Apache Cloudberry 集群中可以并发运行的活动查询数量。也可以用来管理 Apache Cloudberry 为每个查询分配的 CPU、内存资源和磁盘 I/O 的数量。
当用户运行查询时,Apache Cloudberry 会根据为资源组定义的一组限制评估该查询。如果该组的资源限制尚未达到,并且该查询不会导致该组超过并发事务限制,Apache Cloudberry 会立即运行该查询。如果这些条件不满足,Apache Cloudberry 会将查询进行队列排序。例如,如果资源组的最大并发事务数已经达到,后续查询将被排序等待,必须等待其他查询完成后才能运行。当资源组的并发性和内存限制调整到足够大的值时,Apache Cloudberry 也可能运行待处理的查询。
在角色的资源组内,事务是按照先进先出 (First-in-first-out) 原则进行评估的。Apache Cloudberry 定期评估系统的活动工作负载,根据需要重新分配资源,并启动作业或将其放入队列。
您还可以使用资源组来管理外部组件(如 PL/Container)的 CPU 和内存资源。外部组件的资源组使用 Linux cgroups 来管理该组件的总 CPU 资源。
资源组属性和限制
当创建资源组时,需提供一组参数,以确定该组可用的 CPU 和内存资源。下表列出了资源组的可用限制参数:
限制类型 | 描述 | 范围 | 默认值 |
---|---|---|---|
CONCURRENCY | 资源组中允许的最大并发事务数,包括活动和空闲事务。 | [0,max_connections] | 20 |
CPU_MAX_PERCENT | 组可使用的 CPU 资源的最大百分比。 | [1,100] | -1(未设置) |
CPU_WEIGHT | 资源组的调度优先级。 | [1,500] | 100 |
CPUSET | 为该资源组保留的特定 CPU 逻辑核(或超线程中的逻辑线程)。 | 取决于系统核配置 | -1 |
IO_LIMIT | 读取/写入磁盘 I/O 吞吐量的最大限制,以及每秒的最大读/写 I/O 操作。按表空间设置值。 | [2,4294967295 或 max ] | -1 |
MEMORY_QUOTA | 为资源组指定的内存限制值。 | Integar (MB) | -1(未设置,使用 statement_mem 作为单个查询的内存限制) |
MIN_COST | 查询计划被包含在资源组中的最小成本。 | Integar | 0 |
对于 SET
、 RESET
和 SHOW
命令,不强制执行资源限制。
事务并发限制
CONCURRENCY
限制控制资源组允许的最大并发事务数。
每个资源组在逻辑上分为与 CONCURRENCY
限制相等的固定数量的 slot。Apache Cloudberry 为这些 slot 分配固定百分比的内存资源。
角色资源组的默认 CONCURRENCY
限制值为 20
。值为 0
表示该资源组不允许运行任何查询。
Apache Cloudberry 将任何在资源组达到 CONCURRENCY
限制后提交的事务排队。当运行的事务完成时,如果存在足够的内存资源,Apache Cloudberry 会取消排队并运行排队中最早的事务。请注意,如果事务处于 idle in transaction
状态,即使没有语句在运行,并发 slot 仍然处于使用中。
您可以设置服务器配置参数 gp_resource_group_queuing_timeout
来指定事务在 Apache Cloudberry 取消之前在队列中保持的时间。默认超时值为 0
,Apache Cloudberry 会无限期地排队事务。
绕过和解除资源组分配
通过设置服务器配置参数 gp_resource_group_bypass
,可使查询不受资源组并发设置的限制。此参数将启用或禁用资源组的并发事务限制,因此查询可以立即运行。默认值为 false
,这将强制执行 CONCURRENCY
限制。此参数只可在单个会话中设置,无法在事务或函数内设置。如将 gp_resource_group_bypass
设置为 true
,查询不再强制执行分配给其资源组的 CPU 或内存限制。相反,该查询分配的内存限制为每个查询的 statement_mem
。如果没有足够的内存满足内存分配请求,查询将失败。
你可绕过仅 catalogue tables 的查询,例如数据 库图形用户界面(GUI)客户端运行的获取元数据的 catalogue 查询。如果服务器配置参数 gp_resource_group_bypass_catalog_query
设置为 true
(默认),Apache Cloudberry 的资源组调度器会绕过所有仅从系统目录读取的查询,或查询文本中仅包含 pg_catalog
模式表的查询。这些查询会自动解除分配其当前资源组;它们不强制执行资源组的限制,也不计算资源使用。查询资源会从资源组中分配并立即运行。内存限制为每个查询的 statement_mem
。
可使用服务器配置参数 gp_resource_group_bypass_direct_dispatch
绕过直接调度查询。直接调度查询是一种特殊类型的查询,仅需要一个分段参与执行。为了提高效率,Apache Cloudberry 优化了此类型的查询,使用直接调度优化。系统将查询计划发送到需要执行该计划的单个分段,而不是将其发送到所有分段进行执行。如果将 gp_resource_group_bypass_direct_dispatch
设置为 true
,该查询不再强制执行分配给其资源组的 CPU 或内存限制,因此立即运行。相反,该查询分配的内存限制为每个查询的 statement_mem
。如果没有足够的内存满足内存分配请求,查询将失败。您只能在单个会话中设置此参数,而不能在事务或函数内。
计划成本低于限制 MIN_COST
的查询会自动解除分配其资源组,不强制执行其任何限制。查询使用的资源不会计算为资源组的资源。查询的内存限制为 statement_mem
。 MIN_COST
的默认值为 0
。
CPU 限制
Apache Cloudberry 利用 Linux 控制组实现 CPU 资源管理。Apache Cloudberry 通过以下两种方式分配 CPU 资源:
- 通过将 CPU 资源的百分比分配给资源组
- 通过将特定的 core 分配给资源组
当为资源组设置其中一种分配模式时,Apache Cloudberry 会停用另一种分配模式。可同时为同一 Apache Cloudberry 集群的不同资源组使用两种 CPU 资源分配模式。还可以在运行时更改资源组的 CPU 资源分配模式。
Apache Cloudberry 使用服务器配置参数 gp_resource_group_cpu_limit
来识别要分配给每个 Apache Cloudberry 分段节点的资源组的最大系统 CPU 资源百分比。剩余未保留的 CPU 资源用于操作系统内核和 Apache Cloudberry 守护进程。每个主机上可用于 Apache Cloudberry 查询的 CPU 量随后平均分配给 Apache Cloudberry 节点上的每个分段。
默认的 gp_resource_group_cpu_limit
值可能无法在 Apache Cloudberry 集群节点上留下足够的 CPU 资源,因此请确保相应地调整此服务器配置参数。
应避免将 gp_resource_group_cpu_limit
设置为高于 0.9 的值。这样做可能导致高负载查询占用几乎所有 CPU 资源,导致数据库辅助进程的资源紧张。
按核心分配 CPU 资源
可通过 CPUSET
属性识别要为资源组保留的 CPU 核。指定的 CPU 核必须在系统中可用,并且不能与为其他资源组保留的任何 CPU 核重叠。尽管 Apache Cloudberry 数据库将分配给资源组的核专用于该组,但这些 CPU 核也可能被系统中的非 Apache Cloudberry 进程使用。当为资源组配置 CPUSET
时,Apache Cloudberry 数据库会停用该组的 CPU_MAX_PERCENT
和 CPU_WEIGHT
,并将它们的值设置为 -1。
分别为 Coordinator 和 Segment 指定 CPU 核,用分号分隔。配置 CPUSET
的核时,使用以逗号分隔的单核数字或数字区间。必须用单引号括起核心数字/区间,例如,‘1;1,3-4’ 在 Coordinator 上使用核 1,在分段主机上使用核 1、3 和 4。
当将 CPU 核心分配给 CPUSET
组时,请考虑以下几点:
- 使用
CPUSET
创建的资源组将独占指定的核。如果组中没有正在运行的查询,则保留的核处于空闲状态,无法被其他资源组中的查询使用。考虑最小化CPUSET
组的数量,以避 免浪费系统 CPU 资源。 - 考虑保持 CPU 核 0 不分配。CPU 核 0 在以下情况下用作后备机制:
admin_group
和default_group
至少需要一个 CPU 核。当所有 CPU 核都被保留时,Apache Cloudberry 数据库将 CPU 核 0 分配给这些默认组。在这种情况下,为其分配 CPU 核 0 的资源组与admin_group
和default_group
共享该核。- 如以替换节点的方式重启 Apache Cloudberry 数据库集群,并且该节点没有足够的核来服务所有
CPUSET
资源组,则这些组会自动分配 CPU 核 0,以避免系统启动失败。
- 在为资源组分配核时,请使用尽可能低的核数字。如果替换 Apache Cloudberry 数据库节点,而新节点的 CPU 核少于原始节点,或者备份数据库并希望在核较少的集群中恢复,操作可能会失败。例如,如果的 Apache Cloudberry 数据库集群有 16 个核,分配核 1-7 是最佳选择。如果创建一个资源组并将 CPU 核心 9 分配给该组,则恢复到 8 核节点的数据库将失败。
使用 CPUSET
配置的资源组在 CPU 资源上具有更高的优先级。在 Segment 主机上为所有配置了 CPUSET
的资源组设置的最大 CPU 资源使用百分比为保留的 CPU 核数除以所有 CPU 核数,再乘以 100。
在为 Apache Cloudberry 数据库集群启用基于资源组的资源管理后,必须为资源组配置 CPUSET
,该参数是 gp_resource_manager
服务器配置参数。
按百分比分配 CPU 资源
通过 CPU_MAX_PERCENT
配置资源组,以按百分比分配 CPU 资源。当为资源组配置 CPU_MAX_PERCENT
时,Apache Cloudberry 数据库会停用该组的 CPUSET
。
参数 CPU_MAX_PERCENT
设置了资源管理中段 CPU 的百分比上限。可以为资源组指定的最小 CPU_MAX_PERCENT
百分比为 1,最大为 100。在定义的 Apache Cloudberry 数据库集群中,所有资源组指定的 CPU_MAX_PERCENT
的总和可以超过 100。它指定了资源组中所有任务在给定 CPU 时间段内可以运行的总时间比例。一旦资源组中的任务使用完所有由配额指定的时间,它们将在该时间段的剩余时间内受到限制,直到下一个时间段才允许运行。
当资源组中的任务处于空闲状态且未使用任何 CPU 时间时,剩余时间将被收集到未使用 CPU 周期的全局池中。其他资源组可以从这个池中借用 CPU 周期。可用于资源组的实际 CPU 时间可能会有所不同,具体取决于系统中存在的资源组数量。
参数 CPU_MAX_PERCENT
强制执行 CPU 使用的硬性上限。例如,如果设置为 40%,则表示尽管资源组可以临时使用其他组的一些空闲 CPU 资源,但它最多只能使用 Apache Cloudberry 可用的 40% CPU 资源。
你可以设置参数 CPU_WEIGHT
以分配当前组的调度优先级。默认值为 100,值的范围为 1 到 500。该值指定资源组中任务可用 CPU 时间的相对份额。例如,如果一个资源组的相对份额为 100,另两个组的相对份额为 50,则当所有资源组的进程尝试使用 100% 的 CPU(即,所有组的 CPU_MAX_PERCENT
的值设置为 100)时,第一个资源组将获得 50% 的所有 CPU 时间,另外两个各获得 25%。然而,如果添加另一个相对份额为 100 的组,第一个组只能使用 33% 的 CPU,其余组分别获得 16.5%、16.5% 和 33%。
例如,考虑以下组:
组名称 | CONCURRENCY | CPU_MAX_PERCENT | CPU_WEIGHT |
---|---|---|---|
default_group | 20 | 50 | 10 |
admin_group | 10 | 70 | 30 |
system_group | 10 | 30 | 10 |
test | 10 | 10 | 10 |
在 default_group
中的角色具有可用的 CPU 比率(由 CPU_WEIGHT
决定)为 10/(10+30+10+10)=16%。这意味着在系统工作负载较高时,它们至少可以使用 16% 的 CPU。当系统有空闲的 CPU 资源时,它们可以使用更多资源,因为硬限制(由 CPU_MAX_PERCENT
设置)为 50%。
在 admin_group
中的角色在系统工作负载较高时具有可用的 CPU 比率为 30/(10+30+10+10)=50%。当系统有空闲的 CPU 资源时,它们可以使用高达 70% 的硬限制的资源。
在 test
中的角色的 CPU 比率为 10/(10+30+10+10)=16%。但是,由于由 CPU_MAX_PERCENT
确定的硬限制为 10%,它们只能使用最多 10% 的资源,即使在系统空闲时也是如此。
内存限 制
当启用资源组时,内存使用在 Apache Cloudberry 数据库 Segment 和资源组级别进行管理。还可以在事务级别管理内存。
分配给查询的内存量由以下参数确定:
资源组的 MEMORY_QUOTA
参数设置此资源组在段上的最大内存量。这决定了查询执行期间该段主机上所有工作进程可消耗的内存总量。分配给查询的内存量是组内存限制除以组并发限制: MEMORY_QUOTA
/ CONCURRENCY
。
如果查询需要大量内存,您可以使用服务器配置参数 gp_resgroup_memory_query_fixed_mem
在会话级别为查询设置固定的内存量。该参数会覆盖并可以超出资源组的分配内存。
Apache Cloudberry 在处理传入查询时使用 gp_resgroup_memory_query_fixed_mem
的值(如果设置),以绕过资源组设置。否则,它使用 MEMORY_QUOTA
/ CONCURRENCY
作为查询的分配内存。如果 MEMORY_QUOTA
未设置,则查询内存分配的默认值为 statement_mem
。
对于所有查询,如果系统内存不足,它们会溢出到磁盘。当达到限制 gp_workfile_limit_files_per_query
时,Apache Cloudberry 数据库会生成内存不足 (OOM) 错误。
例如,考虑一个名为 adhoc
的资源组,其 MEMORY_QUOTA
设置为 1.5 GB,CONCURRENCY
设置为 3。默认情况下,提交给该组的每个语句分配 500 MB 的内存。现在考虑以下一系列事件:
-
用户
ADHOC_1
提交查询Q1
, 将gp_resgroup_memory_query_fixed_mem
重写为 800MB。Q1
语句被接纳到系统中。 -
用户
ADHOC_2
提交查询Q2
, 使用默认的 500MB。 -
在
Q1
和Q2
仍在运行时,用户ADHOC3
提交查询Q3
,使用默认的 500MB。查询
Q1
和Q2
已使用 1300MB 的组内 1500MB。不过,如果在该时刻段内有足够的系统内存可供查询Q3
使用,可正常运行。 -
用户
ADHOC4
提交查询Q4
, 使用将gp_resgroup_memory_query_fixed_mem
设置为 700MB。查询
Q4
立即运行,因为它绕过了资源组限制。
有关内存限制的一些特殊使用注意事项:
- 如果设置了配置参数
gp_resource_group_bypass
或gp_resource_group_bypass_catalog_query
来绕过资源组限制,则查询的内存限制将取决于statement_mem
的值。 - 当 (
MEMORY_QUOTA
/CONCURRENCY
) 小于statement_mem
时,系统会直接使用statement_mem
作为该查询的固定内存分配值。 statement_mem
的最大取值受max_statement_mem
限制。- 查询的计划成本如果低于设定的
MIN_COST
,则该查询也将使用statement_mem
所指定的内存作为限制。
磁盘 I/O 限制
Apache Cloudberry 利用 Linux 控制组实现磁盘 I/O 限制。参数 IO_LIMIT
限制分配给特定资源组的查询的最大读/写磁盘 I/O 吞吐量,以及最大读/写 I/O 操作数。它分配带宽,确保高优先级资源组的使用,避免过度使用磁盘带宽。该参数的值按表空间基础设置。
仅在使用 Linux cgroup v2 时,磁盘 I/O 限制才可用。
限制磁盘 I/O 时需要指定:
- 要设置限制的表空间名称或表空间对象 ID (OID)。使用
*
设置所有表空间的限制。 rbps
和wbps
的值以限制资源组内最大读取和写入磁盘 I/O 吞吐量,单位为 MB/sec。默认值为max
,意味着没有限制。riops
和wiops
的值以限制资源组内最大读取和写入 I/O 操作数。默认值为max
,意味着没有限制。
如果未设置参数 IO_LIMIT
,则 rbps
、wpbs
、riops
和 wiops
的默认值为 max
,这意味着没有磁盘 I/O 限制。在这种情况下,gp_toolkit.gp_resgroup_config
系统视图的值显示为 -1
。如果仅设置了 IO_LIMIT
的某些值(例如,rbps
),则未设置的参数默认为 max
(在此示例中,wbps
、riops
和 wiops
)。
配置和使用资源组
先决条件
Apache Cloudberry 资源组使用 Linux 控制组(cgroups)管理 CPU 资源和磁盘 I/O。cgroups 有两个版本: cgroup v1
和 cgroup v2
。Apache Cloudberry 支持这两个版本,但仅对 cgroup v2 支持参数 IO_LIMIT
。默认情况下随 Linux 发行版提供的 Linux 控制组版本取决于操作系统版本。对于 Enterprise Linux 8 及更早版本,默认版本为 v1;对于 Enterprise Linux 9 及更高版本,默认版本为 v2。有关 cgroups 的详细信息,请参考 Linux 发行版的控制组文档。
通过检查系统启动时默认挂载的文件系统,验证环境中配置的 cgroup 版本:
stat -fc %T /sys/fs/cgroup/
对于 cgroup v1,输出为 tmpfs
。对于 cgroup v2,输出为 cgroup2fs
。
- Linux 控制组可被更改,但如果您使用较旧版本的操作系统,例如 Centos 7.x 或更早,将只能使用默认的
cgroup v1
控制组;如果你使用的是 Centos 8.x,可按照下方步骤,将控制组从 v1 切换到 v2。 - 从 v2.0.0 起,对于
cpu.pressure
,即使gp_resource_manager
设置为group-v2
,Apache Cloudberry 也不再检查/proc/pressure/cpu
接口的权限或是否存在。因此,即使未启用 PSI(Pressure Stall Information),只要内核版本兼容,仍可正常使用group-v2
模式。
如无需更改 cgroup 版本,可以直接跳到配置 cgroup v1 或配置 cgroup v2 完成配置先决条件。
如希望从 cgroup v1 切换到 v2,可以以 root 身份运行以下命令:
-
Red Hat 8/Rocky 8/Oracle 8 系统:
grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="systemd.unified_cgroup_hierarchy=1"
-
Ubuntu 系统:
vim /etc/default/grub # 添加或修改: GRUB_CMDLINE_LINUX="systemd.unified_cgroup_hierarchy=1"
update-grub
如果希望从 cgroup v2 切换到 v1,可以以 root 身份运行以下命令:
-
Red Hat 8/Rocky 8/Oracle 8 系统:
grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="systemd.unified_cgroup_hierarchy=0 systemd.legacy_systemd_cgroup_controller"
-
Ubuntu 系统:
vim /etc/default/grub
# 添加或修改: GRUB_CMDLINE_LINUX="systemd.unified_cgroup_hierarchy=0"
update-grub
完成后,重启主机以使更改生效。
配置 cgroup v1
在每个 Apache Cloudberry 数据库节点上完成以下任务,以设置 cgroups v1 以用于资源组:
-
安装
libcgroup
和libcgroup-tools
:sudo yum install libcgroup
sudo yum install libcgroup-tools