资源组使用

本文档介绍了如何使用资源组管理 YMatrix 中事务并发、CPU和内存的资源分配。定义资源组后,可以将资源组分配给一个或多个数据库角色以控制角色所能使用的资源。

YMatrix 使用基于 Linux 的控制组来管理数据库资源,并使用 Runaway 来进行内存的统计、跟踪和管理。

相关参数

下表列出了可配置的资源组参数

参数 描述 取值范围 默认参数
CONCURRENCY 资源组中允许的最大并发事务数,包括活动事务和空闲事务。 [0 - 最大连接数] 20
CPU_MAX_PERCENT 配置资源组可以使用的CPU资源的最大百分比。 [1 - 100] -1 (未启用)
CPU_WEIGHT 配置资源组的调度优先级。 [1 - 500] 100
CPUSET 为该资源组保留的特定CPU逻辑核心(或超线程中的逻辑线程)。 依赖系统核心配置 -1
MEMORY_QUOTA 为资源组指定内存限制值。 整数(MB) -1 (未启用,使用 statement_mem 作为单次查询的内存限制)
MIN_COST 一个查询计划被包含在资源组中的最小成本。 整数 0

注意!
针对 SET / RESET / SHOW 命令,资源组不会生效

设置说明

当用户运行查询时,YMatrix 会根据为资源组定义的一组限制来评估查询状态。

并发限制

CONCURRENCY 控制资源组允许的最大并发事务数。默认限制值为 20,值为 0 时表示此资源组不允许运行查询。
如果资源限制尚未达到且查询不会导致超出资源组的并发事务限制,YMatrix 会立即运行查询。如果已达到资源组的最大并发事务数,YMatrix 会将资源组达到其 CONCURRENCY 限制后提交的任何事务排队,并且等到其他查询完成后进行运行。

gp_resource_group_queuing_timeout 可以用来指定队列中事务取消前的等待时间。默认为 0,意味着事务无限期排队。

绕过资源组分配限制

  • gp_resource_group_bypass 用于启用或禁用资源组的并发事务限制,使查询可以立即执行。设为 true,查询就会跳过资源组的并发限制。此时查询的内存配额按照 statement_mem 进行分配,如果内存不足,查询就会失败。此参数只能在单个会话中设置,不能在事务或函数内设置。
  • gp_resource_group_bypass_catalog_query 用于系统表查询是否跳过资源组的资源限制。默认为 true。适用于类似数据库的图形用户界面(GUI)客户端运行目录查询以获取元数据的情况。其资源分配在资源组之外,内存配额为每个查询的 statement_mem
  • gp_resource_group_bypass_direct_dispatch 用于控制直接分发查询(direct dispatch queries)是否跳过资源组的限制。将其设为 true,查询时将不再受其所属资源组分配的 CPU 或内存限制的约束,从而可以立即执行。此时查询的内存配额按照 statement_mem 进行分配,如果内存不足,查询就会失败。此参数只能在单个会话中设置,不能在事务或函数内设置。

CPU 限制

YMatrix 通过以下两种方式分配 CPU 资源:

  1. 分配指定百分比的 CPU 资源
  2. 分配特定的 CPU 核心(Core)

在同一群集上可以为不同的资源组配置不同的 CPU 资源分配模式,同一资源组只能使用一种 CPU 资源分配模式。 运行时也可更改资源组的 CPU 资源分配模式。

可通过 gp_resource_group_cpu_limit 来确定要分配给每个 segment 节点的资源组的系统 CPU 资源的最大百分比。

通过核心(Core)分配 CPU 资源

CPUSET 用于设置要为资源组保留的 CPU 核心。当为资源组配置 CPUSET 时,YMatrix 会停用该组的 CPU_MAX_PERCENTCPU_WEIGHT,并将其值设置为 -1

使用注意:

  • 使用分号 (;) 分隔主节点和 segment 节点指定 CPU 核心,。使用逗号(,)分隔的单核编号或编号区间列表,且需将核心编号/区间列表使用单引号(' ')括起来。例如,'1;1,3-4' 在主节点上使用 core1,在 segment 上使用core 1、core 3 和 core 4。
  • 避免使用 CPU core0,其次将 core 分配给资源组时,使用尽可能低的核心数。如果替换数据库节点,并且新节点的 CPU 核心数少于原始节点,或者如果备份数据库并希望在具有较少 CPU 核心的节点的集群上恢复它,则操作可能会失败。例如,如果数据库集群有 16 个core,则分配 core 1-7 是最佳选择。如果创建资源组并将 CPU core 9 分配给该组,则将数据库恢复到 8 核节点将失败。

通过百分比分配 CPU 资源

CPU_MAX_PERCENT 用于设置 segment 可以使用的 CPU 资源上线,比如设置为 40,表明最多可以使用可用 CPU 资源的 40%。当资源组中的任务处于空闲状态且未使用任何 CPU 时间时,剩余时间将被收集到未使用 CPU 周期的全局池中,其他资源组可以从此池中借用 CPU 周期。

CPU_WEIGHT 用于分配当前组的调度优先级。默认值是 100,取值范围是 1 到 500。该值指定了资源组中任务可获得的相对份额的 CPU 时间。

使用注意:

  • 如果一个资源组的相对份额是 100,另外两个资源组的相对份额是 50,当所有资源组中的进程都试图使用 100% 的 CPU(即所有组的 CPU_MAX_PERCENT 值都设置为 100)时,第一个资源组将获得 50% 的总 CPU 时间,另外两个组各获得 25%。
  • 如果再次添加一个相对份额为 100 (CPU_MAX_PERCENT 设置为 100)的组,则第一个组只能使用 33% 的 CPU,剩下的组分别获得 16.5%、16.5% 和 33%。

配置说明

Group Name 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_WEIGHT 参数所确定的可用 CPU 百分比为 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% 的资源。

内存限制

MEMORY_QUOTA 表示 Segment 上为该资源组保留的最大内存量。这是查询执行期间 Segment 上所有查询的工作进程可以消耗的总内存量。分配给某个查询的内存量是该组内存限制除以该组并发限制:MEMORY_QUOTA / CONCURRENCY

如果一个查询需要更大内存,可以使用 gp_resgroup_memory_query_fixed_mem 在会话级别为查询设置所需内存量,该配置可覆盖并超过资源组分配的内存。

使用注意

  • 如果设置了 gp_resgroup_memory_query_fixed_mem,会使用设置值来绕过资源组设置。
  • 如果未设置 gp_resgroup_memory_query_fixed_mem,会使用 MEMORY_QUOTA / CONCURRENCY 作为查询分配的内存量。
  • 如果未设置 MEMORY_QUOTA,则查询内存分配的值默认为 statement_mem
  • 对于所有查询,如果系统中没有足够的内存,它们就会溢出到磁盘。当达到限制 gp_workfile_limit_files_per_query 时,YMatrix 会生成内存不足 (OOM) 错误。

配置示例
考虑一个名为 adhoc 的资源组,MEMORY_QUOTA 设置为 1.5 GB,CONCURRENCY 设置为 3。默认情况下,提交给该组的每个语句都分配 500MB 的内存。现在考虑以下一系列事件:

  • 用户 ADHOC_1 提交查询 Q1,覆盖 gp_resgroup_memory_query_fixed_mem 到800MB。Q1 语句被允许进入系统。
  • 用户 ADHOC_2 提交查询 Q2,使用默认的 500MB。
  • Q1Q2 仍在运行的情况下,用户 ADHOC_3 提交查询 `Q3,使用默认的 500MB 。
  • 查询 Q1Q2 已经使用了该资源组 1500MB 中的 1300MB。但是,如果某些时段系统有足够的可用内存用于查询 Q3Q3 则可以正常运行。
  • 用户 ADHOC_4 提交查询 Q4,使用 gp_resgroup_memory_query_fixed_mem 设置为 700MB。 由于查询 Q4 绕过资源组限制,他会立即运行。

特殊使用注意事项

  • 如果 gp_resource_group_bypassgp_resource_group_bypass_catalog_query 设置配置参数以绕过资源组限制,则查询的内存限制值为 statement_mem
  • 当( MEMORY_QUOTA / CONCURRENCY)< statement_mem 时,则使用 statement_mem 作为查询分配的固定内存量。
  • statement_mem 的最大值上限为 max_statement_mem
  • 查询计划成本低于限制值 MIN_COST 的查询语句,使用 statement_mem 作为内存配额。

配置资源组

0.通过检查系统启动期间默认挂载的文件系统来验证您的环境中配置的 cgroup 版本:

stat -fc %T /sys/fs/cgroup/

对于 cgroup v1,输出是 tmpfs。对于 cgroup v2,输出是 cgroup2fs

如果不需要更改 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
# add or modify: 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
# add or modify: GRUB_CMDLINE_LINUX="systemd.unified_cgroup_hierarchy=0"
update-grub

如果您想继续使用 cgroup v1,请确保 /sys/fs/cgroup/memory/gpdb 下的每个 memory.limit_in_bytes 文件(包括 /sys/fs/cgroup/memory/gpdb/memory.limit_in_bytes/sys/fs/cgroup/memory/gpdb/[OID]/memory.limit_in_bytes)没有极限值。如果是,请运行:

echo -1 >> memory.limit_in_bytes

之后,重新启动主机以使更改生效。


配置 cgroup v1

1.在集群中的每个节点上操作:

注意!
需使用超级用户或具有 sudo 访问权限的用户才能编辑此文件。

vi /etc/cgconfig.conf

在配置文件中添加以下信息。

group gpdb {
     perm {
         task {
             uid = mxadmin;
             gid = mxadmin;
         }
         admin {
             uid = mxadmin;
             gid = mxadmin;
         }
     }
     cpu {
     }
     cpuacct {
     }
     cpuset {
     }
     memory {
     }
} 

此内容配置了由 mxadmin 用户管理的 CPU、CPU 核算、CPU 核心集以及内存控制组。

2.为 YMatrix 集群每一个节点开启 cgroup 服务。

cgconfigparser -l /etc/cgconfig.conf 
systemctl enable cgconfig.service
systemctl start cgconfig.service

3.确定节点的 cgroup 目录挂载点

grep cgroup /proc/mounts 
  • 第一行输出为 cgroup 目录挂载点 /sys/fs/cgroup
tmpfs /sys/fs/cgroup tmpfs ro,nosuid,nodev,noexec,mode=755 0 0                                                             
cgroup /sys/fs/cgroup/systemd cgroup rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd 0 0                                                                                                      
cgroup /sys/fs/cgroup/devices cgroup rw,nosuid,nodev,noexec,relatime,devices 0 0                                           
cgroup /sys/fs/cgroup/net_cls,net_prio cgroup rw,nosuid,nodev,noexec,relatime,net_prio,net_cls 0 0                         
cgroup /sys/fs/cgroup/pids cgroup rw,nosuid,nodev,noexec,relatime,pids 0 0                                                 
cgroup /sys/fs/cgroup/freezer cgroup rw,nosuid,nodev,noexec,relatime,freezer 0 0                                           
cgroup /sys/fs/cgroup/cpu,cpuacct cgroup rw,nosuid,nodev,noexec,relatime,cpuacct,cpu 0 0                                   
cgroup /sys/fs/cgroup/perf_event cgroup rw,nosuid,nodev,noexec,relatime,perf_event 0 0                                     
cgroup /sys/fs/cgroup/hugetlb cgroup rw,nosuid,nodev,noexec,relatime,hugetlb 0 0                                           
cgroup /sys/fs/cgroup/memory cgroup rw,nosuid,nodev,noexec,relatime,memory 0 0                                             
cgroup /sys/fs/cgroup/cpuset cgroup rw,nosuid,nodev,noexec,relatime,cpuset 0 0                                             
cgroup /sys/fs/cgroup/blkio cgroup rw,nosuid,nodev,noexec,relatime,blkio 0 0  

4.检验是否正确配置

ls -l <cgroup_mount_point>/cpu/gpdb
ls -l <cgroup_mount_point>/cpuset/gpdb
ls -l <cgroup_mount_point>/memory/gpdb

如果目录存在,并且属主是 mxadmin:mxadmin,说明成功配置 cgroup 对 YMatrix 数据库的资源管理。


配置 cgroup v2

1.将系统配置为在系统启动时默认挂载 cgroups-v2,通过 systemd 系统和服务管理器以 root 用户身份实现。

grubby --update-kernel=ALL --args="systemd.unified_cgroup_hierarchy=1"

2.重新启动系统,使更改生效。

reboot now

3.创建目录 /sys/fs/cgroup/matrixdb6.service,添加所有必要的控制器,并确保 mxadmin 用户对其具有读写权限。

mkdir -p /sys/fs/cgroup/matrixdb6.service
echo "+cpuset +io +cpu +memory" | tee -a /sys/fs/cgroup/cgroup.subtree_control
chown -R mxadmin:mxadmin /sys/fs/cgroup/matrixdb6.service

运行上述命令后,您可能会遇到错误无效参数。这是因为 cgroup v2 不支持控制实时进程,只有当所有实时进程都在根 cgroup 中时才能启用 cpu 控制器。在这种情况下,请找到所有实时进程并将它们移动到 root cgroup,然后再重新启用控制器。
1.确保 mxadmin/sys/fs/cgroup/cgroup.procs 具有写入权限。这是在集群启动后将 YMatrix 进程从用户移动到 /sys/fs/cgroup/matrixdb6.service/ 以管理 postmaster 服务及其所有必需的辅助进程。

chmod a+w /sys/fs/cgroup/cgroup.procs

由于资源组手动管理 cgroup 文件,系统重启后上述设置将失效。为 systemd 添加以下 bash 脚本,使其在系统启动期间自动运行。以 root 用户身份执行以下步骤:

1.创建 matrixdb6.service

vim /etc/systemd/system/matrixdb6.service

2.将以下内容写入 matrixdb6.service,如果用户不是 mxadmin,则替换为相应的用户。

[Unit]
Description=Greenplum Cgroup v2 Configuration Service
[Service]
Type=simple
WorkingDirectory=/sys/fs/cgroup/matrixdb6.service
Delegate=yes
Slice=-.slice

# set hierarchies only if cgroup v2 mounted
ExecCondition=bash -c '[ xcgroup2fs = x$(stat -fc "%%T" /sys/fs/cgroup) ] || exit 1'
ExecStartPre=bash -ec " \
chown -R mxadmin:mxadmin .; \
chmod a+w ../cgroup.procs; \
mkdir -p helper.scope"
ExecStart=sleep infinity
ExecStartPost=bash -ec "echo $MAINPID > /sys/fs/cgroup/cgroup.procs;"
[Install]
WantedBy=basic.target

3.重新加载 systemd 守护程序并启用服务:

systemctl daemon-reload
systemctl enable gpdb.service

启用资源组

1.将 gp_resource_manager 服务器配置参数设置为值 "group"

gpconfig -c gp_resource_manager -v "group"

2.重启 YMatrix 数据库集群

mxstop -arf

启用后,角色提交的任何事务都将定向到分配给该角色的资源组,并受该资源组的并发、内存、CPU限制的约束。

YMatrix 默认创建名为 admin_groupdefault_groupsystem_group 的角色资源组。启用资源组时,任何未显式分配资源组的角色都将分配至该角色功能的默认组。SUPERUSER 角色分配至 admin_group,非管理员角色分配至 default_group,系统进程的资源分配至 system_group。其中,不能手动将任何角色分配给 system_group

各角色资源组配置如下.

参数 admin_group default_group system_group
CONCURRENCY 10 5 0
CPU_MAX_PERCENT 10 20 10
CPU_WEIGHT 100 100 100
CPUSET -1 -1 -1
IO_LIMIT -1 -1 -1
MEMORY_LIMIT -1 -1 -1
MIN_COST 0 0 0

创建资源组

CREATE RESOURCE GROUP 命令创建新的资源组。为角色创建资源组时,提供名称和 CPU 资源分配模式(核心或百分比)。必须提供 CPU_MAX_PERCENTCPUSET 限制值。

使用示例
创建一个名为 rgroup1 的资源组,其 CPU 限制为 20,内存限制为 250,CPU 优先级为 500,最小开销为 50:

CREATE RESOURCE GROUP rgroup1 WITH (CONCURRENCY=20, CPU_MAX_PERCENT=20, MEMORY_QUOTA=250, CPU_WEIGHT=500, MIN_COST=50);

其中,CPU 和内存限制由分配给 rgroup1 的每个角色共享。

ALTER RESOURCE GROUP 命令更新资源组的限制。

ALTER RESOURCE GROUP rg_role_light SET CONCURRENCY 7;
ALTER RESOURCE GROUP exec SET MEMORY_QUOTA 30;
ALTER RESOURCE GROUP rgroup1 SET CPUSET '1;2,4';

注意!
不能将 admin_groupCONCURRENCY 值设置或更改为 0。

DROP RESOURCE GROUP 命令删除资源组。要删除角色的资源组,该组不能分配给任何角色,资源组中也不能有任何活动或等待的事务。

DROP RESOURCE GROUP exec;

配置基于内存使用的自动查询终止

YMatrix 支持 Runaway 检测。对于由资源组管理的查询,可以根据查询所使用的内存量自动终止查询。 相关的配置参数如下:

  • gp_vmem_protect_limit:设置活动 segment 实例中所有 postgres 进程可以消耗的内存量。如果一个查询导致这个限制被超过,将不会分配内存,查询将失败。
  • runaway_detector_activation_percent:当启用资源组时,如果使用的内存量超过了指定值 gp_vmem_protect_limit * runaway_detector_activation_percent,YMatrix 将根据内存使用量来终止由资源组(不包括 system_group 资源组中的查询)管理的查询。查询终止将从消耗内存量最大的查询开始,直到内存使用量低于指定的百分比终止。

分配资源组给角色

  • 使用 CREATE ROLEALTER ROLE 命令的 RESOURCE GROUP 子句将资源组分配给数据库角色。

    ALTER ROLE bill RESOURCE GROUP rg_light;
    CREATE ROLE mary RESOURCE GROUP exec;

    可以将资源组分配给一个或多个角色。如果已定义角色的层次结构,分配给父角色的资源组不会向下传播到该角色组的成员。

  • 如果需要从角色中删除资源组分配并为角色分配默认组,可将角色的组名分配更改为 NONE

    ALTER ROLE mary RESOURCE GROUP NONE;

监控资源组状态

  • 查看资源组限制
    SELECT * FROM gp_toolkit.gp_resgroup_config;
  • 查看资源组查询状态
    SELECT * FROM gp_toolkit.gp_resgroup_status;
  • 查看每台主机上资源组的内存使用情况
    SELECT * FROM gp_toolkit.gp_resgroup_status_per_host;
  • 查看分配给角色的资源组
    SELECT rolname, rsgname FROM pg_roles, pg_resgroup
    WHERE pg_roles.rolresgroup=pg_resgroup.oid;
  • 查看资源组的运行中和待处理查询
    SELECT query, rsgname,wait_event_type, wait_event 
    FROM pg_stat_activity;
  • 取消资源组中正在运行或排队的事务 手动取消正在运行或排队的事务,必须先确定与事务关联的进程 id 或 pid。获得进程 id 后,可调用 pg_cancel_backend() 来结束该进程。 具体步骤如下:
    • 首先运行以下查询,查看所有资源组中当前活动或空闲的所有语句关联的流程信息。如果查询没有返回任何结果,则说明资源组中都没有正在运行或排队的事务。
      SELECT rolname, g.rsgname, pid, waiting, state, query, datname 
      FROM pg_roles, gp_toolkit.gp_resgroup_status g, pg_stat_activity 
      WHERE pg_roles.rolresgroup=g.groupid
      AND pg_stat_activity.usename=pg_roles.rolname;
    • 查询结果示例
      rolname | rsgname  | pid     | waiting | state  |          query           | datname 
      ---------+----------+---------+---------+--------+------------------------ -+---------
        sammy  | rg_light |  31861  |    f    | idle   | SELECT * FROM mytesttbl; | testdb
        billy  | rg_light |  31905  |    t    | active | SELECT * FROM topten;    | testdb
    • 事务进程结束
      SELECT pg_cancel_backend(31905);

      注意!
      不要使用操作系统 KILL 命令取消任何 YMatrix 数据库进程。

移动查询至不同资源组

具有超级用户权限的用户可以运行 gp_toolkit.pg_resgroup_move_query() 函数将正在运行的查询从一个资源组移动到另一个资源组,而不会停止该查询。使用此函数可以通过将长时间运行的查询移动到资源分配或可用性更高的资源组来加快查询速度。

pg_resgroup_move_query() 仅将指定的查询移动到目标资源组,后续提交的查询仍分配至原资源组。

注意!
只能将活动或正在运行的查询移动到新资源组。由于并发或内存限制,不能移动处于空闲状态的排队或挂起的查询。

pg_resgroup_move_query() 需要正在运行的查询的进程 id 或 pid,以及要将查询移动到的资源组的名称。

pg_resgroup_move_query( pid int4, group_name text );

如取消资源组中正在运行或排队的事务中所述,可以使用 gp_toolkit.gp_resgroup_status 视图列出每个资源组的名称、id 和状态。

当调用 pg_resgroup_move_query() 函数时,正在运行的查询会受到目标资源组配置的限制,这些限制包括并发任务限制、内存限制等。

  • 如果目标资源组已达到其并发任务限制,数据库会将查询排队,直到有可用的槽位,或者如果设置了 gp_resource_group_queuing_timeout,则会排队等待指定的毫秒数。
  • 如果目标资源组有空闲插槽,pg_resgroup_move_query() 会尝试将槽位控制权交给目标进程,最多尝试 gp_resource_group_move_timeout 指定的毫秒数。如果目标进程在 gp_resource_group_queuing_timeout 时间内无法处理移动请求,数据库会返回错误信息。
  • 如果 pg_resgroup_move_query() 被取消,但目标进程已经获得了所有插槽空之前,segment 进程将不会移动到新组,目标进程将保留插槽。这种不一致的状态将在事务结束时或目标进程在同一事务中调度的任何下一个命令中修复。
  • 如果目标资源组没有足够的可用存储器来满足查询的当前内存需求,数据库将返回错误信息。可以选择增加目标资源组分配的共享内存,或者等待一段时间,让正在运行的查询完成,然后再调用该函数。

移动查询后,无法保证目标资源组中当前运行的查询不会超过该组内存配额。在这种情况下,目标资源组中一个或多个正在运行的查询可能会失败,包括移动的查询。可通过预留足够的资源组全局共享内存,以尽量减少这种情况发生的可能性。