本文在Redhat 7.6环境使用Greenplum 6.9.0(部署在一台物理机上,2个segment)测试通过。 # 一、cgroups配置 ## 安装cgroup工具 ```bash sudo yum install libcgroup-tools ``` ## 创建配置文件 ```json [gpadmin@bogon ~]$ sudo vi /etc/cgconfig.d/gpdb.conf group gpdb { perm { task { uid = gpadmin; gid = gpadmin; } admin { uid = gpadmin; gid = gpadmin; } } cpu { } cpuacct { } cpuset { } memory { } } ``` 注:/etc/cgconfig.d/这个目录,在安装libcgroup-tools之后才会生成。 ## 解析conf文件和并挂载层级 ```bash [gpadmin@bogon ~]$ sudo cgconfigparser -l /etc/cgconfig.d/gpdb.conf ``` ## 识别cgroups命令挂载点(mount point) 看命令输出结果第一行。 ```bash [gpadmin@bogon ~]$ grep cgroup /proc/mounts tmpfs /sys/fs/cgroup tmpfs ro,seclabel,nosuid,nodev,noexec,mode=755 0 0 cgroup /sys/fs/cgroup/systemd cgroup rw,seclabel,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd 0 0 cgroup /sys/fs/cgroup/pids cgroup rw,seclabel,nosuid,nodev,noexec,relatime,pids 0 0 …… ``` 或者, ```bash [root@bogon ~]# grep cgroup /proc/mounts | head -n 1 | awk '{print $2}' /sys/fs/cgroup ``` ## 验证cgroups配置是否正确 ```bash [root@bogon cgroup]# grep cgroup /proc/mounts|head -n 1|awk '{print $2}'|xargs -i ls -l {}/{cpu,cpuacct,cpuset,memory}/|grep -w gpdb|awk '{print $3":"$4}'|uniq gpadmin:gpadmin ``` 或者, ```bash ls -l /cpu,cpuacct/gpdb ls -l /cpuacct/gpdb ls -l /cpuset/gpdb ls -l /memory/gpdb ``` ## 启动cgconfig服务 Redhat/CentOS 7.x and SuSE11+系统: ```bash # 重启系统生效: sudo systemctl enable cgconfig.service # 立即生效: sudo systemctl start cgconfig.service # 查询状态: sudo systemctl status cgconfig.service ``` Redhat/CentOS 6.x系统: ```bash sudo chkconfig cgconfig on ``` # 二、Greenplum ## 设置资源管理器为"group" 安装GPDB时,默认情况下会启用资源队列。要使用资源组而不是资源队列,必须设置gp\_resource\_manager服务器配置参数为值"group",**重启GPDB才会生效**。 ```bash [gpadmin@bogon ~]$ export PGPORT=7456 [gpadmin@bogon ~]$ gpconfig -s gp_resource_manager Values on all segments are consistent GUC : gp_resource_manager Master value: queue Segment value: queue [gpadmin@bogon ~]$ gpconfig -c gp_resource_manager -v "group" 20200722:20:24:39:053663 gpconfig:bogon:gpadmin-[INFO]:-completed successfully with parameters '-c gp_resource_manager -v group' ``` ## 重启GP服务 ```bash [gpadmin@bogon ~]$ gpstop -r -a [gpadmin@bogon ~]$ gpconfig -s gp_resource_manager Values on all segments are consistent GUC : gp_resource_manager Master value: group Segment value: group ``` 启用后,角色提交的任何事务都将定向到分配给该角色的资源组,并受该资源组的并发、内存和CPU限制的约束。同样,外部组件的CPU和内存使用量由为分配给组件的资源组配置的CPU和内存限制控制。 GPDB为角色创建了名为admin\_group和default\_group的两个默认资源组。启用资源组时,将为未明确分配资源组的任何角色分配角色功能的默认组。SUPERUSER角色分配了admin\_group,非管理员角色分配了名为default\_group的组。 # 三、验证CPU按比例配额 完成上述配置后,接下来我们做一个小实验,验证资源组控制不同角色CPU使用比例。 ## 创建资源组 创建资源组rgroup1,调整缺省资源的CPU配额比例值。default\_group、admin\_group和rgroup1资源组的CPU配比为:10:10:5 = 2:2:1。查看设置结果: ```sql tpch1s=# CREATE RESOURCE GROUP rgroup1 WITH (CPU_RATE_LIMIT=5, MEMORY_LIMIT=25, MEMORY_SPILL_RATIO=20); tpch1s=# ALTER RESOURCE GROUP admin_group SET CPU_RATE_LIMIT 10; tpch1s=# ALTER RESOURCE GROUP default_group SET CPU_RATE_LIMIT 10; tpch1s=# SELECT * FROM gp_toolkit.gp_resgroup_config; groupid | groupname | concurrency | cpu_rate_limit | memory_limit | memory_shared_quota | memory_spill_ratio | memory_auditor | cpuset ---------+---------------+-------------+----------------+--------------+---------------------+--------------------+----------------+-------- 6437 | default_group | 20 | 10 | 0 | 80 | 0 | vmtracker | -1 6438 | admin_group | 10 | 10 | 10 | 80 | 0 | vmtracker | -1 16385 | rgroup1 | 10 | 5 | 25 | 80 | 20 | vmtracker | -1 (3 rows) ``` ## 创建角色 使用超级用户创建一个新角色yz,并指派资源组rgroup1: ```sql tpch1s=# CREATE ROLE yz WITH SUPERUSER CREATEDB CREATEROLE LOGIN REPLICATION INHERIT PASSWORD '111' RESOURCE GROUP rgroup1; tpch1s=# \du List of roles Role name | Attributes | Member of -----------+-----------------------------------------------------------------------+----- gpadmin | Superuser, Create role, Create DB, Ext gpfdist Table, ……, Replication | {} yz | Superuser, Create role, Create DB, Replication | {} -- 查询角色与资源组之间关系: tpch1s=# SELECT rolname, rsgname FROM pg_roles, pg_resgroup WHERE pg_roles.rolresgroup=pg_resgroup.oid; rolname | rsgname ---------+------------- gpadmin | admin_group yz | rgroup1 (2 rows) ``` ## 允许新用户连接数据库 修改master节点pg_hba.conf配置文件: ```bash vim /opt/gp/gpmaster/gpseg-1/pg_hba.conf # 修改 host all gpadmin,yz 127.0.0.1/28 trust host all gpadmin,yz 192.168.0.219/32 trust host all gpadmin,yz ::1/128 trust ``` 如果新用户无法登录,请参考:[Greenplum新建用户无法登录问题](../安装与调试/Greenplum新建用户无法登录问题)。 ## 验证 从两个psql客户端分别连接GP数据库,同时执行一条耗CPU的长查询(例如,热数据 TPC-H q1): ```bash [gpadmin@bogon ~]$ psql -d tpch1s tpch1s=# \i q1.sql [gpadmin@bogon ~]$ psql -h 127.0.0.1 -d tpch1s -U yz tpch1s=# \i q1.sql ``` 监视进程postgres进程使用率,gpadmin用户和yz用户的CPU使用率近似2:1,符合预期: ![img](../../../../../ff_internal_upload/img/2020/2020-07-29-111457.png) # 四、迁移查询至其它资源组 GPDB 从v6.8开始,运行管理员将正在执行的查询从一个资源组迁移到另一个资源组。例如,用户yz指派了资源组rgroup1,该用户执行的某个查询进程号为pid,管理员可以根据当前资源组使用情况,临时将正在执行的资源组迁到另一个资源组rgroup2上继续运行(无需中断查询),以达到临时调配资源目的。 ## 函数 查询迁移资源组功能函数为: ```sql gp_toolkit.pg_resgroup_move_query( pid int4, group_name text ); ``` 注:v6.8 ~ v6.10,上述函数在gp\_toolkit schema中,而在当前master分支,已经移出gp\_toolkit了。 ## 示例 在第1个psql客户端,使用admin\_group资源组执行一个长查询: ```sql [gpadmin@bogon ~]$ psql -d tpch1s # 第1个psql客户端 tpch1s=# \i ~/1.sql ``` 在第2个psql客户端,先查询上述查询的pid、资源组等信息,然后将上述查询迁移到另一个资源组,并确认是否迁移成功。 ```sql [gpadmin@bogon ~]$ psql -d tpch1s # 第2个psql客户端 tpch1s=# select pid,sess_id,query,rsgid,rsgname from pg_stat_activity; -- 迁移前状态 pid | sess_id | query | rsgid | rsgname ---------+---------+------------------------------------------------------------------------------+-------+------------- 2933567 | 6 | select +| 6438 | admin_group | | l_returnflag, +| | | | l_linestatus, +| | | | sum(l_quantity) as sum_qty, +| | | | sum(l_extendedprice) as sum_base_price, +| | …… -- 上述查询pid为2933567,资源组是admin_group(oid为6438)。 tpch1s=# SELECT gp_toolkit.pg_resgroup_move_query(2933567, 'default_group') FROM pg_stat_activity; -- 迁移到default_group资源组 -- 如果是master分支,迁移命令为: -- SELECT pg_resgroup_move_query(2933567, 'default_group') FROM pg_stat_activity; tpch1s=# select pid,sess_id,query,rsgid,rsgname from pg_stat_activity; -- 迁移后状态 pid | sess_id | query | rsgid | rsgname ---------+---------+------------------------------------------------------------------------------+-------+--------------- 2933567 | 6 | select +| 6437 | default_group | | l_returnflag, +| | | | l_linestatus, +| | | | sum(l_quantity) as sum_qty, +| | | | sum(l_extendedprice) as sum_base_price, +| | …… -- 可以看到,pid为2933567的查询以及迁移到default_group组(oid为6437) ``` 另外,我们也可以从cgroups状态判断是否迁移成功。 ```sql tpch1s=# SELECT * FROM gp_toolkit.gp_resgroup_config; groupid | groupname | concurrency | cpu_rate_limit | memory_limit | memory_shared_quota | memory_spill_ratio | memory_auditor | cpuset ---------+---------------+-------------+----------------+--------------+---------------------+--------------------+----------------+-------- 6437 | default_group | 20 | 30 | 0 | 80 | 0 | vmtracker | -1 6438 | admin_group | 10 | 10 | 10 | 80 | 0 | vmtracker | -1 ``` 从GPDB资源组配置可知,目标资源组default\_group的CPU资源控制使用的是"cpu\_rate\_limit",我们可以通过查看/sys/fs/cgroup/cpu/gpdb/6437/tasks是否有以上进程pid(已经相关计算与管理进程的pid)来确认迁移是否成功: ```bash [gpadmin@bogon ~]$ cat /sys/fs/cgroup/cpu/gpdb/6437/tasks 2933567 2933568 2935432 …… ``` # 五、参考 - [Greenplum 6.9 资源组中文文档](Greenplum 6.9 资源组中文文档) - [Greenplum 6.9 在线文档之资源组](https://gpdb.docs.pivotal.io/6-9/admin_guide/workload_mgmt_resgroups.html) - [Greenplum 资源隔离的原理与源码分析](https://developer.aliyun.com/article/57763) - [《GPDB学习笔记》资源管理](https://blog.csdn.net/MasterLeon/article/details/103617968) - [Greenplum 资源队列](https://cloud.tencent.com/developer/article/1388547)