GaussDB(DWS)负载管理核心技术解密:负载管控逻辑解密
该文章从内核角度介绍负载管控逻辑。重点介绍内存和并发管控。首先介绍一些相关概念
负载管理
GaussDB(DWS)通过对业务的并发控制,实现系统负载的均衡。避免业务间争抢资
源,实现所有作业的和谐共处,达到资源利用最优。而对并发控制,是通过对资源池的内存和并发进行管控实现。
控制组
控制组(Cgroups)是control groups的缩写,是Linux内核提供的一种可以限制、记
录、隔离进程组所使用的物理资源(如:CPU、内存、IO等)的机制。GaussDB(DWS)使用控制组主要用于对CPU的管控。控制方式有配额和限额两种方式。具体后续介绍。
资源池
资源池(Resource Pool)是GaussDB(DWS)提供的一种配置机制,用于对主机资源(内存、IO)进行划分并提供SQL的并发控制能力。资源池通过绑定Cgroups对CPU资源进行管理。用户通过绑定资源池可以实现对其下作业的资源负载管理。资源池主要包含了以下字段信息(表pg_resource_pool):
字段 |
描述 |
respool_name |
资源池名称 |
mem_percent |
内存百分比 |
control_group |
关联的控制组 |
active_statements |
慢车道并发数 |
max_dop |
快车道并发数 |
short_acc |
短查询加速开关 |
租户管理
租户管理即通过创建并管理租户,实现按租户对系统资源(CPU、内存、IO、存储空
间)的隔离和作业的异常处理。在业务运行中,系统压力可能集中在集群中的一部分节点或者系统资源中的某项资源,导致系统资源不能充分利用,集群性能不能充分发挥。创建用户是指定关联资源池,这样该用户下发的作业就关联到对应的资源池进行管理,以实现同一套集群下所有作业之间不相互影响。
作业类型
资源管理判断作业为简单作业,还是复杂作业。动态负载下,根据作业的估算内存和估算cost判断。如果估算内存>32MB 或者 估算cost > guc参数parctl_min_cost的设定值,则判定作业为复杂作业,否则为简单作业。注意如果parctl_min_cost= -1,则不参与作业类型的判断。静态负载下,根据作业的估算cost判断。如果估算cost > guc参数parctl_min_cost的设定值,则判定作业为复杂作业,否则为简单作业。如果parctl_min_cost= -1,则作业为简单作业。
快慢车道
资源管理将作业划分到快慢两个车道运行。消耗资源小的作业在快车道运行,否则在慢车道运行。资源池的short_acc字段是短查询加速开关,开启则简单作业在快车道运行,复杂作业在慢车道运行。关闭则简单作业和复杂作业都在慢车道运行。默认short_acc开启。快车道作业的并发数受max_dop管控,慢车道作业的并发数受mem_percent和active_statements管控。慢车道的作业管控,即后续介绍的内存和并发管控。
内存和并发管控
下面介绍并发管控的具体实现。用户下发一个SQL作业,判断在快车道执行,则受max_dop管控。由于快车道作业没有ccn统一管控,所以是各cn各自管控。即整个集群可以下发max_dop * cn数 的快车道作业。
慢车道作业,受mem_percent和active_statements管控。一个是内存上限,一个是并发上限,作业要满足两项均受控,只要一项到达上限,则阻止作业继续下发执行,作业pending在资源池。下表是各场景下的管控逻辑
mem_percent = 0 |
active_statements > 0 |
内存不管控,仅并发数管控 |
mem_percent > 0 |
active_statements = 0 或 -1 |
并发不管控,仅内存数管控 |
mem_percent > 0 |
active_statements > 0 |
同时管控 |
mem_percent = 0 |
active_statements = 0 或 -1 |
内存并发都不管控 |
mem_percent字段是一个百分比的值,通过mem_percent * max_dynamic_memory 得到资源池可使用的内存上限。租户场景下,业务资源池的内存是继承组资源池的内存。即其内存上限为mem_percent * 组资源池的内存。但并发数(active_statements)不继承。
注意,内存管控隐藏了一个管控上限,所有的资源池的慢车道作业,不能超过max_dynamic_memory的80%(留下的20%是给快车道作业使用)。所以mem_percent = 0或100,也使用不到全部的内存。
通过以下SQL获取max_dynamic_memory的值:
select memorymbytes*0.8 as memorymbytes_80 from pgxc_total_memory_detail where nodename like 'dn_%' and memorytype = 'max_dynamic_memory' order by memorymbytes limit 1;
以下需要注意:
- 动态负载下,慢车道作业由ccn统一管控;静态负载下,未使用ccn,各cn各自管控。
- 组资源池的mem_percent != 0,业务资源池的mem_percent = 0。业务用户继承组用户的内存,但由于内存不受控,内存可以超过组资源池的内存。作业受并发数或者max_dynamic_memory的80%管控。
管控范围
管控的用户:初始用户(集群同名用户)资源池、全局都不管控,其它所有用户资源池、全局都受控。
管控的作业分为以下三类:
所有作业都受全局并发管控(max_active_statements)
所有dml和create table as都受资源池的并发管控
copy from: 开启资源管理,动态负载,列存表,上述三种条件下才会走资源池管控(max_dop)
动静态负载管控的区别
动态负载和静态负载的管控逻辑有些区别。主要有以下区别:
- 作业类型判断的区别
- 慢车道作业管控的区别
启动资源负载管理
开启Control Group功能。
gs_guc reload -Z coordinator -Z datanode -N all -I all -c "enable_control_group=on"
开启基于资源池的资源负载管理功能。
gs_guc set -Z coordinator -Z datanode -N all -I all -c "use_workload_manager=on"
开启对数据库的常驻后备线程的控制。
gs_guc set -Z coordinator -Z datanode -N all -I all -c "enable_backend_control=on"
开启对数据库的常驻后备线程中的autoVacuumWorker线程的控制。
gs_guc set -Z coordinator -Z datanode -N all -I all -c "enable_vacuum_control=on"
开启动/静态负载
gs_guc set -Z coordinator -Z datanode -N all -I all -c "enable_dynamic_workload=on/off"
重启数据库使参数设置生效。
gs_om -t stop && gs_om -t start
----结束
设置控制组
-S后面指定的是class,-G后面指定的是workload
gs_ssh -c "gs_cgroup -cS ClassN1 -G wn1"
gs_ssh -c "gs_cgroup -cS ClassG1 -G wg1_1"
gs_ssh -c "gs_cgroup -cS ClassG1 -G wg1_2"
这里介绍一下CPU的管控,以下命令表示设定控制组的配额。当有关联两个控制组的作业同时执行,需要争抢CPU资源池时,按照20:40的比列分配。若是只有关联一个控制组的作业运行,则可以使用100%的CPU资源。
gs_ssh -c "gs_cgroup -cS ClassG1 -G wg1_1 -g 20"
gs_ssh -c "gs_cgroup -cS ClassG1 -G wg1_2 -g 40"
以下命令设定控制组的限额。表示各控制组能够使用CPU资源上限。比如系统有10个核,则wg1_1最多可用2个核,wg1_2最多可用4个核。
gs_ssh -c "gs_cgroup -cS ClassG1 -G wg1_1 -g 20 --fixed"
gs_ssh -c "gs_cgroup -cS ClassG1 -G wg1_2 -g 40 --fixed"
创建资源池
1.直接关联workload的资源池,称为普通资源池
create resource pool respool_1 with (control_group = 'ClassN1:wn1');
2.关联class的资源池,称为组资源池
create resource pool respool_grp_1 with (control_group = 'ClassG1');
3.关联组资源池下的workload的资源池,称为业务资源池。与组资源池为从属关系
create resource pool respool_g1_job_1 with (control_group = 'ClassG1:wg1_1');
create resource pool respool_g1_job_2 with (control_group = 'ClassG1:wg1_2');
创建租户
1.关联普通资源池的普通用户
CREATE USER user_normal RESOURCE POOL 'respool_1' PASSWORD 'Gauss_234' ;"
2.关联组资源池的组用户
CREATE USER user_grp_1 RESOURCE POOL 'respool_grp_1' PASSWORD 'Gauss_234' ;"
3.关联业务资源池的业务用户
CREATE USER user_1 RESOURCE POOL 'respool_g1_job_1' USER GROUP 'user_grp_1' PASSWORD 'Gauss_234' ;"
CREATE USER user_2 RESOURCE POOL 'respool_g1_job_2' USER GROUP 'user_grp_1' PASSWORD 'Gauss_234' ;"
如果创建用户时不指定资源池,则关联默认资源池。
创建用户时有一定限制,具体参看下表。
用户 |
资源池 |
关联cgroup |
资源池内存占比限制 |
用户/资源池对应关系 |
资源池/cgroup对应关系 |
组用户 |
组资源池 |
class |
资源池内存占比之和<= 100% |
一对一 |
一对一 |
业务用户 |
业务资源池 |
workload |
各组下资源池内存占比之和<= 100% |
多对一 |
多对一(Timeshare)/一对一(自建workload) |
普通用户 |
普通资源池 |
workload |
资源池内存占比之和>= 0 |
多对一 |
多对一 |
一般我们使用业务用户执行作业,达到资源管控的目的。
想了解GuassDB(DWS)更多信息,欢迎微信搜索“GaussDB DWS”关注微信公众号,和您分享最新最全的PB级数仓黑科技,后台还可获取众多学习资料哦~
- 点赞
- 收藏
- 关注作者
评论(0)