资源组(Resource Group) 是PolarDB PostgreSQL版(兼容Oracle)提供的可以对进程、数据库和用户三种粒度所使用资源进行限制的机制,可以对CPU,内存资源实现精细化的控制。
背景信息
如果在同一个节点上存在多个实例或者一个实例存在复杂的多种业务,会引起资源的争抢,从而影响到正常的业务运行。资源组提供Limit和Request两种能力,用来保证业务,减少资源争抢的问题。
- Limit:最大资源共享。表示资源组最大可用的共享资源,不设置则最大可使用所有资源,多个资源组的Limit资源相加可以大于整体资源。 
- Request:最小资源保证。表示资源组最小的保证资源,任何时刻系统都必须满足这个资源需求,多个资源组的Request资源相加要小于等于整体资源。 
使用限制
- 资源限制维度 - 资源组整个功能是基于限制单个或者多个进程所使用资源实现的。资源组的基本限制维度是进程,由于PolarDB PostgreSQL版(兼容Oracle)的一个会话对应一个进程,同时一个会话只能有一个用户登录到一个数据库,因此,进程、用户、数据库是一个进程的基本元素。允许指定任意进程、用户、数据库到指定的资源组,但一个进程只能属于一个资源组。因此不存在重复统计的问题。并行查询的后台并行子进程都属于发起查询的后台进程所属资源组。 - 进程 - 由用户主动发起的用户连接进程(会话进程)。 
- 后端子进程: 例如某用户的会话进程发起的并行查询,由并行查询调用的后端进程。 
- 其他一些系统辅助进程:background writer、checkpointer、startup进程等。 
 
- 用户 - 由同一个用户主动发起的用户连接进程(会话进程)。 
- 后端子进程: 例如某用户的会话进程发起的并行查询,由并行查询调用的后端进程。 
- 不包括系统辅助进程。 
 
- 数据库 - 访问同一个数据库的用户连接进程(会话进程)。 
- 后端子进程: 例如访问某数据库的会话进程发起的并行查询,由并行查询调用的后端进程。 
- 不包括系统辅助进程。 
 
 
- 资源限制策略 - PolarDB PostgreSQL版(兼容Oracle)对资源的限制策略如下: - 基于Request/Limit的资源阈值设置,当资源使用量大于Limit时,会执行资源限制确保使用量小于等于Limit的值。 
- 当整体资源利用率大于特定阈值,会执行资源限制确保资源组使用量大于等于Request的值。 
- 未被分配到资源组的进程,自动进入default资源组,不做任何资源限制。 
 
参数说明
| 参数名称 | 参数说明 | 
| database_name | 存放资源组元数据的数据库名称。 默认值为polardb_admin。 生效方式:重启集群。 | 
| stat_interval | 数据采集间隔时间。 取值范围:100~10000,单位为毫秒。默认值为500ms。 生效方式:执行 | 
| total_mem_request_rate | 主动淘汰阈值。 取值范围:50%~100%,默认值为80%。 生效方式:执行 | 
| total_mem_limit_rate | 强制淘汰阈值。 取值范围:50%~100%,默认值为95%。 生效方式:执行 | 
| total_mem_limit_remain_size | 内存预留大小。 取值范围:131072~INT_MAX,单位为KB。默认值为512000 KB。 生效方式:执行 说明  当数据库集群内存水位线达到强制淘汰阈值或者剩余内存小于预留内存大小,会按照内存释放策略对内存占用较高的用户进程进行强制操作(cancel query或者terminate)。 | 
| policy_mem_release | 内存释放策略。取值如下: 取值如下: 
 | 
| enable_terminate_active | 直接终止用户active进程,默认值为ON,取值范围ON/OFF。执行 | 
| enable_log | 开启日志记录,默认值为ON,取值范围ON/OFF。执行 | 
操作指南
需要使用超级用户创建和管理资源组,如您有相应需求,请联系我们处理。
- 切换数据库。 - \c polardb_admin说明- polardb_admin为存放资源组元数据的数据库名称,请以database_name的参数值为准。 - 显示结果如下: - You are now connected to database "polardb_admin" as user "postgres".
- 创建资源组插件。 - CREATE EXTENSION polar_resource_group;
- 创建资源组。 - SELECT polar_resource_group.polar_create_resource_group('group_name');说明- polar_create_resource_group为资源组生成函数,用于生成新的资源组。
- 其他操作。 - 修改资源组。 - SELECT polar_resource_group.polar_alter_resource_group('group_name', 'mem_limit', 1024)说明- polar_alter_resource_group为资源组资源限制修改函数,可以对CPU使用率和内存使用率进行限制。
- 添加和删除进程。 - 添加进程。 - SELECT polar_resource_group.polar_resource_group_add_process('group_name', pg_backend_pid());说明- polar_resource_group_add_process函数将指定的进程加入到资源组内进行限制。
- 删除进程。 - SELECT polar_resource_group.polar_resource_group_add_process('DEFAULT', pg_backend_pid());说明- 添加DEFAULT,即可删除进程。 
 
- 添加和删除指定用户。 - 添加指定用户。 - SELECT polar_resource_group.polar_resource_group_add_user('group_name', 'user_name');说明- polar_resource_group_add_user函数将指定的用户加入资源组内进行限制。
- 删除指定用户。 - SELECT polar_resource_group.polar_resource_group_add_user('DEFAULT', 'user_name');说明- 添加DEFAULT,即可删除指定用户。 
 
- 添加和移除指定数据库。 - 添加指定数据库。 - SELECT polar_resource_group.polar_resource_group_add_database('group_name', 'database');说明- polar_resource_group_add_database函数将指定的数据库添加到资源组内进行限制。
- 移除指定数据库。 - SELECT polar_resource_group.polar_resource_group_add_database('DEFAULT', 'database');说明- 添加DEFAULT,即可移除指定数据库。 
 
- 查看资源组内部表。 - 记录资源组的表。 - SELECT * FROM polar_resource_group.resource_group;
- 记录资源组和用户的关系表。 - SELECT * FROM polar_resource_group.polar_resource_group_user;
- 记录资源组和数据库的关系表。 - SELECT * FROM polar_resource_group.polar_resource_group_dbs;
- 记录当前活跃的资源组的关系函数。 - SELECT * FROM polar_resource_group.polar_get_active_resource_groups_detail();
- 记录当前活跃的资源组的关系视图。 - SELECT * FROM polar_resource_group.polar_all_resource_groups_detail;
 
- 删除资源组。 - SELECT polar_resource_group.polar_drop_resource_group('group_name');说明- 其中, - polar_drop_resource_group为资源组删除函数,用于删除已有的资源组。
 
CPU资源管理
将进程、用户或者数据库添加到对应资源组后,可以设置资源组CPU的Limit值和Request值。
如果有可分配的后端子进程,则将后端子进程加入到发出并行查询的会话连接的资源组限制中,让后端子进程和会话进程共享资源组限制的资源。而当会话的并行查询执行完后,将后端子进程从资源限制组中移除。此过程是一个动态增加和移除资源限制的过程。
可以考虑单独为系统辅助进程设置资源组。例如,限制Vacuum CPU使用率,防止其过高从而引起业务异常;或者为startup进程设置Request,防止业务使用CPU过高后,引起数据库redo变慢,造成流复制异常。
- CPU Limit - Limit是用来限制资源组内对象的CPU使用率的最大值。当资源组内的对象CPU使用率过大时,数据库会进行限制,将CPU使用率降低,使其小于Limit值。 - 通过 - polar_alter_resource_group设置cpu_limit,参数值为float类型。说明- 参数值表示CPU的使用率(一段时间内的CPU使用时间比率)。例如,0.3表示使用一个核的30%,2表示使用2个核的能力。 - 由于限制的是最大使用率,因此所有资源组的cpu_limit和可以大于规格额T,即 - cpu_limit_A + cpu_limit_B + cpu_limit_C + ... >= T。- 考虑到资源使用上的效率,如果资源组中进程使用的资源小于当前规格额T时,可以允许运行使用超过资源组限制的资源。例如,有两个资源组 - cpu_limit_A和- cpu_limit_B, 并且- cpu_limit_A + cpu_limit_B >= T,当- cpu_limit_B中进程资源没有使用或者很小时,为了提高资源利用率,允许A中的进程使用超过- cpu_limit_A或者整个规格的限额资源。- 每个资源组除了当前有的硬性limit限制外(用户设置的),还有对应的soft限制,soft最初和limit的限制相同,但是soft会根据资源组req和usage的使用情况,做动态的调整,但是soft总是小于等于limit。 
- CPU Request - Request是用来保证资源组的最基本的CPU资源使用率的。cpu_request可以保证资源组对象需要较高CPU使用率时,至少能够使用到cpu_request值的CPU使用率。 - 通过 - polar_alter_resource_group设置cpu_request,参数值为float类型。- 由于是基本保证值,因此所有资源组的cpu_request的总和必须小于等于规格额T,即 - cpu_request_A + cpu_request_B + cpu_request_C + ... <= T,其次- cpu_request_x <= cpu_limit_x。- 假设有两个资源组R1(limit1, req1)和 R2(limit2, req2),两个资源组的实际CPU使用为usage1和usage2,整个集群的CPU规格额为T: - 当 - usage1 + usage2 < T时,则无需调整限制。
- 当 - usage1 + usage2 >= T,并且- usage1 >= req1,- usage2 >= req2时,则无需限制。
- 当 - usage1 + usage2 >= T时, 如果某个资源组的CPU使用率小于request,- usage1 < req1,- delta = req1 - usage1,则需要资源组2的CPU软限制动态下降调整, 直至资源组1可以达到req1的使用率。
 
内存资源管理
内存资源的管理涉及数据库的sharedbuffer、进程内存以及pfsd内存。内存资源管理的基础是三者之和。由于内存资源是刚性资源(swap off),不像CPU可以动态限制,如果内存资源超过limit硬性限制,一般是通过中止进程来释放资源。资源组的内存管理类似操作系统的OOM处理策略,相比于系统的整个数据库级别的OOM处理,这里只是一个资源组级别的OOM处理。
- 内存 Limit - 通过 - polar_alter_resource_group来设置mem_limit,参数值为float类型。- 与cpu_limit类似,内存的limit限制内存使用的最大值,总的limit值可以大于等于规格额。包含以下两种策略: - 主动资源超限管理 - 当总内存使用量大于主动淘汰阈值(total_mem_request_rate,默认值为80%)时,如果资源组内存使用量大于此资源组内存limit量,则释放相应会话释放资源,并返回给用户内存超限的错误。直到内存使用量小于主动淘汰阈值。 
- 强制资源超限管理 - 当总内存使用量大于强制淘汰阈值(total_mem_limit_rate,默认值为95%)时,遍历资源组,如果资源组内存使用量超过内存limit量,则释放相应会话的资源,并返回给用户内存超限的错误;如果所有资源组内存使用量都不超过内存limit量(default资源组占用),则释放资源占用多的会话,并返回给用户内存资源不足错误。直到内存使用量小于强制淘汰阈值。 说明- 内存限制进行淘汰时,会中止用户会话并释放进程资源,可以通过发送SIGUSR2实现,向用户返回指定的OOM错误。如果存在并行查询的后台进程内存超限,会中止对应的用户进程。目前只对用户进程进行限制,系统后台进程目前属于default资源组,不会主动中止释放资源。 
 
- 内存 Request - 通过 - polar_alter_resource_group来设置mem_request,参数值为float类型。- 与cpu_request类似,同样是保证资源组使用最基本的内存使用量,总的request值必须小于等于规格额,并且资源组的request值必须小于等于资源组的limit值。 - 因为总的request值是小于规格额的。因此,当某个资源组的request值无法得到满足时,需要通过释放其他资源组的会话内存资源来增加可用的资源。 说明- 如果不存在其他资源组,或其他资源组没有任何内存资源限制时,则会按照内存限制的逻辑执行。