多租户

本文介绍了PolarDB PostgreSQL版(兼容Oracle)的多租户资源配置功能。

概念

租户:在多租户中,租户是一个逻辑实体,它代表一个特定的数据和资源分配单元。租户的层级定位在集群之下,用户和数据库之上,它们之间的对应关系是多对一的,多个账户或数据库对应一个租户。租户与用户或数据库不是等同的概念。租户分为两大类:

  • 系统租户:这是一个特殊的管理实体,通常只有一个。系统租户拥有对资源的优先访问权,能够占用普通租户的资源。当通过系统租户的用户连接到数据库时,如果该用户具备相应的集群访问权限,他们将能够访问所有租户下的集群。

  • 普通租户:每个普通租户的资源是完全隔离的,租户之间无法相互访问。普通租户必须在系统租户的上下文中创建。

资源配置:资源配置涉及为特定的租户分配确定的资源(如CPU和内存)。这种配置方式允许高权限账户根据业务需求,为每个租户指定资源限制。

租户资源配置功能旨在限制单个或多个进程所使用的资源量。在PolarDB PostgreSQL版(兼容Oracle)中,一个会话对应一个进程,且一个会话只能由一个用户登录到一个数据库。因此,进程、用户和数据库构成了进程的基本元素。系统允许将任意进程、用户、数据库映射到指定的租户,但一个进程只能属于一个租户,从而避免了资源使用量的重复统计。后台并行查询的子进程属于发起查询的进程所属的租户。因此基于进程的属性可以将资源限制分为三个维度:

  • 进程:指用户主动发起的账户连接进程(会话进程),包括与进程相关的并行查询进程,但不包括系统辅助进程。

  • 用户:指由同一用户发起的所有用户连接进程(会话进程),包括与进程相关的并行查询进程,但不包括系统辅助进程。

  • 数据库:指访问同一数据库的所有用户连接进程(会话进程),包括与进程相关的并行查询进程,但不包括系统辅助进程。

说明

由于系统进程特定的功能作用,默认情况下不对其资源使用进行限制。

前提条件

支持的PolarDB PostgreSQL版(兼容Oracle)的版本如下:

Oracle语法兼容 2.0(内核小版本2.0.14.24.0及以上)。

说明

您可通过如下语句查看PolarDB PostgreSQL版(兼容Oracle)的内核小版本的版本号:

SHOW polar_version; 

参数说明

参数

描述

生效方式

polar_max_tenants

最大租户数量,取值范围为0~65536,默认值为32。

重启生效。

polar_resource_manager.enable_resource_manager

是否打开Resource Manager进程,进行内存限制和OOM预防,默认值为on。

重启生效。

polar_resource_manager.database_name

存放租户元数据的数据库名称,默认值为polardb_admin

重启生效。

polar_resource_manager.stat_interval

数据采集间隔时间,单位为毫秒,取值范围为10~10000。默认值为500 ms。

RELOAD加载生效。

SELECT pg_reload_conf();

polar_resource_manager.total_mem_request_rate

主动淘汰阈值,取值范围为50%~100%,默认值为80%。

RELOAD加载生效。

SELECT pg_reload_conf();

polar_resource_manager.total_mem_limit_rate

强制淘汰阈值,取值范围为50%~100%,默认值为95%。

RELOAD加载生效。

SELECT pg_reload_conf();

polar_resource_manager.total_mem_limit_remain_size

内存预留大小,取值范围为131072~INT_MAX(整型数据类型最大值),单位为KB,默认值为256000 KB。

RELOAD加载生效。

SELECT pg_reload_conf();

polar_resource_manager.enable_log

是否开启日志记录,取值范围如下:

  • ON(默认值):开启日志记录。

  • OFF:关闭日志记录。

RELOAD加载生效。

SELECT pg_reload_conf();

使用说明

在使用多租户时,需要在polar_resource_manager.database_name参数设置的数据库中安装插件polar_resource_manager

重要

修改polar_resource_manager.database_name设置的存放租户元数据的数据库名称,前期设定的多租户信息会失效。

CREATE EXTENSION polar_resource_manager;

创建资源配置

使用函数polar_create_resource_config创建资源配置。

SELECT polar_resource_manager.polar_create_resource_config('resource_config_name');

其中,参数resource_config_name需要符合数据库对象名限制,只支持64字节以内的名称,超过64字节后会自动截断。

删除资源配置

使用函数polar_drop_resource_config删除资源配置。

SELECT polar_resource_manager.polar_drop_resource_config('resource_config_name');

修改资源配置

使用函数polar_alter_resource_config修改资源配置的资源设置。

SELECT polar_resource_manager.polar_alter_resource_config('resource_config_name', 'config_name', value);

其中,支持的config_name类型为:

  • cpu_rate_limit,CPU限制值,单位为核心数。

  • mem_limit,内存限制值,单位是字节数。

创建租户

使用函数polar_create_tenant创建租户。

SELECT polar_resource_manager.polar_create_tenant('tenant_name', 'resource_config_name');

其中:

  • tenant_name参数需要符合数据库对象名限制,只支持64字节以内的名称,超过64字节后会自动截断。

  • resource_config_name资源配置需要优先建立,否则无法成功建立租户。

删除租户

使用函数polar_drop_tenant删除租户。删除租户不会删除资源配置。

SELECT polar_resource_manager.polar_drop_tenant('tenant_name');

修改租户

使用函数polar_alter_tenant修改租户。

SELECT polar_resource_manager.polar_alter_tenant('tenant_name', 'config_name', 'value');

其中,支持的config_name类型为:

  • name:租户名称。

  • resource_config:资源配置。

数据库归属租户

使用函数polar_tenant_add_database将数据库归属到租户下。数据库只能归属到一个租户,否则无法归属成功。

SELECT polar_resource_manager.polar_tenant_add_database('tenant_name', 'database_name');

查看数据库和租户

使用polar_tenants_dbs视图可以查看数据库及其所属的租户。

SELECT dbsname, tenantname FROM polar_resource_manager.polar_tenants_dbs;

用户归属租户

使用函数polar_tenant_add_user将用户归属到租户下。用户只能归属到一个租户,否则无法归属成功。

SELECT polar_resource_manager.polar_tenant_add_user('tenant_name', 'user_name');

查看用户和租户

使用polar_tenants_users视图可以查看用户及其所属的租户。

SELECT username, tenantname FROM polar_resource_manager.polar_tenants_users;

进程归属租户

使用函数polar_tenant_add_process将进程归属到租户下。进程只能归属到一个租户,归属多个租户时,以最后一次为准。

SELECT polar_resource_manager.polar_tenant_add_process('tenant_name', pid);

查看租户资源情况

使用polar_all_resource_configs_detail视图可以查看租户资源情况。

SELECT * FROM polar_resource_manager.polar_all_resource_configs_detail;

视图信息如下:

列名称

列类型

描述

tenantname

NAME

租户名称。

resource_config_name

NAME

资源配置名称。

num_processes

INTEGER

进程数量。

num_idle_processes

INTEGER

idle进程数量。

num_active_processes

INTEGER

活跃进程数量。

cpu_rate_limit

DOUBLE PRESISION

租户CPU资源限制值。

per_process_cpu_rate_limit

DOUBLE PRESISION

进程CPU限制值。

mem_limit

DOUBLE PRESISION

内存限制值。

mem_usage

DOUBLE PRESISION

内存使用量。

idle_processes_mem_usage

DOUBLE PRESISION

空闲进程内存使用量。

active_processes_mem_usage

DOUBLE PRESISION

活跃进程内存使用量。

cpu_usage_rate

DOUBLE PRESISION

CPU 使用率。

CPU资源管理

将进程、用户或者数据库添加到对应租户后,可以设置租户资源配置的CPU相关限制值。如果有可分配的后端子进程,则将后端子进程加入到发出并行查询的会话连接的租户中,让后端子进程和会话进程共享租户限制的资源。而当会话的并行查询执行完后,将后端子进程从租户中移除。此过程是一个动态增加和移除资源限制的过程。

CPU使用率限制

用于限制租户内对象的CPU使用率的最大值。当租户内的对象CPU使用率过大时,集群会进行限制,将CPU使用率降低,使其小于限制值。

通过polar_resource_manager.polar_alter_resource_config设置cpu_rate_limit,参数值为float类型。

说明

参数值表示CPU的使用率(一段时间内的CPU使用时间比率)。例如,0.3表示使用一个核的30%,2表示使用2个核的能力。由于限制的是最大使用率,因此所有租户资源配置的cpu_limit和可以大于规格额T,即cpu_limit_A + cpu_limit_B + cpu_limit_C + ... >= T

内存资源管理

由于内存资源是刚性资源(swap off),无法像CPU可以动态限制,如果内存资源超过硬性限制,一般是通过中止进程来释放资源。租户的内存管理类似操作系统的OOM处理策略,相比于系统的整个数据库级别的OOM处理,这里只是一个租户级别的OOM处理。

内存使用量限制

通过polar_resource_manager.polar_alter_resource_config来设置mem_limit,参数值为float类型。与CPU使用率限制类似,用于限制内存使用的最大值,总的限制值可以大于等于规格额。包含以下两种策略:

  • 主动资源超限管理:当总内存使用量大于主动淘汰阈值(total_mem_request_rate,默认值为80%)时,如果租户内存使用量大于此租户资源配置的内存limit量,则释放相应会话释放资源,并返回给用户内存超限的错误。直到内存使用量小于主动淘汰阈值。

  • 强制资源超限管理:为了避免集群内存过量使用,引起集群OOM,当总内存使用量大于强制淘汰阈值(total_mem_limit_rate,默认值为95%)时,遍历所有进程,释放相应会话的资源,并返回给用户内存超限的错误。

内存限制进行淘汰时,会中止用户会话并释放进程资源,可以通过发送SIGUSR2实现,向用户返回指定的OOM错误。如果存在并行查询的后台进程内存超限,会中止对应的用户进程。目前只对用户进程进行限制,系统后台进程目前属于系统租户,不会主动中止释放资源。