关于sql:实操指南-Resource-Queue如何实现对AnalyticDB-PostgreSQL的资源管理

33次阅读

共计 8032 个字符,预计需要花费 21 分钟才能阅读完成。

简介:作者:阿里云数据库 OLAP 产品部 – 子华

一 背景

AnalyticDB PostgreSQL 版(简称 ADB PG)是阿里云数据库团队基于 PostgreSQL 内核(简称 PG)打造的一款云原生数据仓库产品。在数据实时交互式剖析、HTAP、ETL、BI 报表生成等业务场景,ADB PG 都有着独特的技术劣势,在金融、物流、泛互联网等行业都有宽泛的利用,是传统数仓上云、去 O 去 T、替换自建 Greenplum 的标杆云上数据仓库产品。

数据仓库产品是数据分析系统的重要组件之一,各类线上业务对数据仓库产品的稳定性、可用性具备很高的要求。不足无效的资源管理机制会导致数据库产品的稳定性降落,产生例如连接数打满 OS 限度、内存不足、过程卡死等问题,从而影响产品的可用性。

Resource Queue(资源队列)是 ADB PG 的一种资源管理形式,可能对数据库的 CPU、内存等资源进行限度,对多租户资源限度、保障数据库稳固运行具备肯定的作用。顾名思义,Resource Queue 以队列模式对运行在数据库集群上的 SQL 进行资源管理。对于每个用户,他的所有连贯只能归属于一个队列。而对于每个队列可能治理多个用户的连贯。没有显示指定资源队列的用户,会归属于默认资源队列治理。通过限度每个队列的资源总量,咱们能够达到限度某类业务或者某个用户应用的资源总量的目标。

咱们以 ADB PG 某在线交易平台类客户 A 为例,介绍 Resource Queue 的应用。客户 A 基于 ADB PG 构建数据仓库,日常运行三类业务:以交易数据入库为代表的实时类业务;用于撑持决策分析的报表类业务;以及用于实时大屏展现的可视化类业务。咱们依据三类业务的不同特点,按如下策略配置资源队列。

客户 A 的实时类业务的典型代表是,交易数据经 Kafka->Flink->ADB PG 链路实时写入 ADB PG。这类业务的典型特点是,峰值并发比拟大,单个 SQL 资源耗费小。在进行资源队列限度前,业务高峰期常常产生忽然进步的并发查问打满数据库连贯,造成高可用探活查问执行失败,引发实例不可用。对于这类业务咱们将其关联到一个高 CPU 权重、大并发限度(平安阈值内)、单个 SQL 内存份额低的队列。既保证数据的疾速入库,又避免流量洪峰造成零碎不稳固。

客户 A 的另一类典型业务是报表类、ETL 类业务,这类业务会在实时类业务的低峰期进行调度,生成报表以提供决策反对。这类业务波及的数据量较大,耗费内存量和产生的临时文件量大。对于这类业务,咱们将其关联到低 CPU 权重、低并发限度,然而内存份额高的队列,在满足业务须要的同时,管制内存应用下限;

除此之外,客户还基于 ADB PG 数据仓库反对数据的实时可视化展现,这类可视化计划往往具备十分稳固的并发,然而对查问的延时具备肯定的要求。对于这类业务,咱们将其资源队列设定为高 CPU 权重,低并发限度,以及宽泛的优化器查问打算耗费份额,最大水平为其生成良好的查问打算,以保障业务稳固。

接下来,本文会具体介绍 Resource Queue 的应用形式、状态监控,以及它的实现机制。

二 Resource Queue 简介

Resource Queue 反对通过 SQL 配置,反对进行四种类型的资源限度:并发限度、CPU 限度、内存限度和查问打算限度。用户能够通过 SQL 在数据库内定义多个资源队列,并设置每个资源队列的资源限度。在一个数据库中,每个资源队列能够关联一个或多个数据库用户,而每个数据库用户只能归属于单个资源队列。

另外,并不是所有提交到资源队列的 SQL 都会受到队列限度的限度,数据库只会限度 SELECT、SELECT INTO、CREATE TABLE AS SELECT、DECLARE CURSOR、INSERT、UPDATE 和 DELETE 这些类型 SQL 的资源利用。另外,在执行 EXPLAIN ANALYZE 命令期跑的 SQL 也会被资源队列排除。

资源队列反对的资源限度配置如下:

配置名配置阐明
MEMORY_LIMIT队列中所有查问所应用的内存总量。
ACTIVE_STATEMENTS队列中容许同时运行的查问数。超出该设置值的查问须要排队期待执行。
PRIORITY队列的 CPU 应用优先级,能够设置为以下级别:LOW、MEDIUM、HIGH 和 MAX。默认值为 MEDIUM,优先级越高的队列会被调配越高的 CPU 份额。
MAX_COST查问打算耗费限度。

通过 SQL 语句定义一个新的资源队列:

`
CREATE RESOURCE QUEUE etl WITH (ACTIVE_STATEMENTS=3,
MEMORY_LIMIT=’1GB’, PRIORITY=LOW, MAX_COST=-1.0);
`

ACTIVE\_STATEMENTS:

队列中容许同时运行的查问数,即队列中容许并发查问的最大并发值。数据库容许超出 ACTIVE\_STATEMENTS 数目、然而少于数据库最大连接数 MAX\_CONNECTIONS 数目的链接连贯到数据库,然而这部分 SQL 连贯并不会立即开始运行,而是排队期待。

MAX\_COST:

查问打算 Cost 限度。数据库优化器会为每个查问计算 Cost,如果该 Cost 总量超过了资源队列所设定的的 MAX\_COST 的值,该查问就会被回绝。ADB PG 的默认配置为 0,即不受限制。

Memory Limit:

ADB PG 能够通过设置 statement\_mem 来决定每条 SQL 在每个 Segment 上应用的内存下限。Memory Limit 既没有默认值,也能够不指定。在 MEMORY\_LIMIT 参数没有被配置时,一个资源队列中的一条 SQL 所容许的内存大小,由 statement\_mem 参数决定:

* 如果一个资源队列没有设置 MEMORY\_LIMIT 的话,每个资源所调配到的内存大小就是 statement\_mem 的服务器配置参数,一个资源队列的可用内存大小是依据 statement\_mem 和 ACTIVE\_STATEMENTS 的计算结果。

* 当资源队列有设置 MEMORY\_LIMIT 时,单个 SQL 所应用的内存量会由队列中的平均分配值 (MEMORY\_LIMIT/ACTIVE\_STATEMENTS) 和 statement\_mem 中的最大值决定,具体计算形式能够参考前面实现章节。

资源队列中能够并行执行的查问数会受到该队列的可用内存限度。举个例子:对于队列 etl,设置 STATEMENTS=3,MEMORY\_LIMIT=2.1G;那么在没有设置 statement\_mem 的状况下,每个查问默认应用内存 700MB。

SQL1 进入队列,应用内存 700MB,此时队列残余内存 1.4G;

SQL2 进入队列,设置 statement\_mem 为 1.0GB,此时队列残余内存为 0.4GB;

此时,队列残余内存无奈满足 SQL3 的内存应用需要(默认 700GB),那么尽管队列中并行查问数没有达到队列限度,SQL3 仍然无奈执行,须要排队期待。

PRIORITY:

数据库运行的 SQL 会依照其所在资源队列的优先权设置来共享可用的 CPU 资源。当一个来自高优先权队列的语句进入到流动运行语句分组中时,它能够失去可用 CPU 中较高的份额,同时也会升高具备较低优先权设置队列中曾经在运行的语句失去的份额。

查问的绝对尺寸或复杂度不影响 CPU 的调配。如果一个简略的低代价的查问与一个大型的简单查问同时运行,并且它们的优先权设置雷同,它们将被调配等同份额的可用 CPU 资源。当一个新的查问变成流动时,CPU 份额将会被从新计算,然而优先权相等的查问仍将失去等量的 CPU。

例如,管理员创立三个资源队列:streaming、etl、prod,并相应地配置为以下优先权:

* streaming — 低优先权

* etl— 高优先权

* prod — 最大优先权

当数据库中只有 etl 队列中有查问 1 和 2 同时运行时,它们有相等份额的 CPU,因为它们的优先权设置相等:

上图中显示的百分数都是近似值。高、低和中优先权队列的 CPU 应用并不总是精确地用这些比例计算出来。

当一个 streaming 队列中的查问开始运行时,在 etl 队列中两个查问仍然放弃相等的 CPU 份额,而低优先级的 query3 则会以较低 CPU 份额运行。

而当最高优先级队列 prod 中有查问进入队列之后,其 CPU 应用会被调整以阐明其最大优先权设置。它可能是一个非常简单的查问,但直到它实现前,它都将要求最大份额的 CPU。而其余查问的优先级则会被调整为较低的 CPU 份额。

#

# 三 Resource Queue 应用

##

## 3.1 创立资源队列

ADB PG 容许用户应用 SQL 创立资源队列,并指定各类资源限度。应用 CREATE RESOURCE QUEUE 命令来创立新的资源队列。

### 创立带有并发限度的队列

带有 ACTIVE\_STATEMENTS 设置的资源队列会限度指派给该队列的角色所执行的并发查问数量。

`
CREATE RESOURCE QUEUE etl WITH (ACTIVE_STATEMENTS=3);
`

这意味着对于所有被调配到 etl 资源队列的角色,在任意给定时刻只能有三个流动查问被运行在这个零碎上。如果这个队列曾经有三个查问在运行并且一个角色在该队列中提交第四个查问,则第四个查问只有等到一个槽被释放出来后能力运行。

###

### 创立带有内存限度的队列

带有 MEMORY\_LIMIT 设置的资源队列管制所有通过该队列提交的查问的总内存。在与 ACTIVE\_STATEMENTS 联结应用时,每个查问被调配的默认内存量为:MEMORY\_LIMIT /ACTIVE\_STATEMENTS。

例如,要创立一个流动查问限度为 10 且总内存限度为 2000MB 的资源队列(每个查问将在执行时被调配 200MB 的 Segment 主机内存):

`
CREATE RESOURCE QUEUE etl WITH (ACTIVE_STATEMENTS=10,
MEMORY_LIMIT=’2000MB’);
`

另外 gp\_vmem\_protect\_limit 参数会限度一个 Segment 上调配的内存总大小。该参数的优先级更高,如果这个参数超标,查问可能会被勾销。

###

### 设置优先级

为了管制一个资源队列对可用 CPU 资源的耗费,用户能够指派一个适合的优先级。

`
ALTER RESOURCE QUEUE etl WITH (PRIORITY=LOW);
ALTER RESOURCE QUEUE etl WITH (PRIORITY=MAX);
`

## 3.2 指派角色(用户)到资源队列

一旦创立了一个资源队列,用户必须把角色(用户)指派到它们适合的资源队列。如果没有显式地把角色指派给资源队列,它们将进入默认资源队列 pg\_default。

应用 ALTER ROLE 或者 CREATE ROLE 命令来指派角色到资源队列。例如:

`
ALTER ROLE name RESOURCE QUEUE queue_name;
CREATE ROLE name WITH LOGIN RESOURCE QUEUE queue_name;
`

### 从资源队列移除角色

所有用户都必须被指派到资源队列。如果没有被显式指派到一个特定队列,用户将会进入到默认的资源队列 pg\_default。如果用户想要从一个资源队列移除一个角色并且把它们放在默认队列中,能够将该角色的队列指派改成 none。例如:

`
ALTER ROLE role_name RESOURCE QUEUE none;
`

## 3.3 批改资源队列

在资源队列被创立后,用户能够应用 ALTER RESOURCE QUEUE 命令更改队列限度,或应用 DROP RESOURCE QUEUE 命令移除一个资源队列。

### 批改资源队列配置

ALTER RESOURCE QUEUE 命令更改资源队列的限度。要更改一个资源队列的限度,能够为该队列指定想要的新值。例如:

`
ALTER RESOURCE QUEUE etl WITH (ACTIVE_STATEMENTS=5);
ALTER RESOURCE QUEUE etl WITH (PRIORITY=MAX);
`

### 删除资源队列

DROP RESOURCE QUEUE 命令能够删除资源队列。要删除一个资源队列,该队列不能有指派给它的角色,也不能有任何语句在其中期待。

`
DROP RESOURCE QUEUE etl;
`

# 四 Resource Queue 状态监控

##

## 4.1 查看队列中的语句和资源队列状态

gp\_toolkit.gp\_resqueue\_status 视图容许用户查看一个负载治理资源队列的状态和流动。对于一个特定资源队列,它展现有多少查问在期待运行以及零碎中以后有多少查问是流动的。要查看零碎中创立的资源队列、它们的限度属性和以后状态:

`
SELECT * FROM gp_toolkit.gp_resqueue_status;
`

## 4.2 查看资源队列统计信息

如果想要继续跟踪资源队列的统计信息和性能,用户能够应用 pg\_stat\_resqueues 零碎视图来查看在资源队列应用上收集的统计信息。

`
SELECT * FROM pg_stat_resqueues;
`

## 4.3 查看指派到资源队列的角色

要查看指派给资源队列的角色,执行下列在 pg\_roles 和 gp\_toolkit.gp\_resqueue\_status 系统目录表上的查问:

`
SELECT rolname, rsqname FROM pg_roles, gp_toolkit.gp_resqueue_status
WHERE pg_roles.rolresqueue=gp_toolkit.gp_resqueue_status.queueid;
`

## 4.4 查看资源队列的期待查问

用户能够看到所有资源队列的所有以后沉闷的以及在期待的查问:

`
SELECT * FROM gp_toolkit.gp_locks_on_resqueue WHERE
lorwaiting=’true’;
`

如果这个查问不返回后果,那就意味着以后没有语句在资源队列中期待。

## 4.5 查看流动语句的优先权

查看以后正在被执行的语句并且提供优先权、会话 ID 和其余信息:

`
SELECT * FROM gp_toolkit.gp_resq_priority_statement;
`

## 4.6 重置流动语句的优先权

用户能够应用函数 gp\_adjust\_priority(session\_id,statement\_count,priority)调整以后正在被执行的语句的优先权。应用这个函数,用户能够晋升或者升高任意查问的优先权。例如:

`
SELECT gp_adjust_priority(12, 10000, ‘LOW’);
`

在这个函数的参数中,session\_id 代表会话 id, statement\_count 代表要调整的 SQL 在 session 中的序号,priority 是待调整的优先级。能够通过 gp\_resq\_priority\_statement 视图查问现有语句的上述信息。

`
select * from gp_toolkit.gp_resq_priority_statement;
`

# 五 Resource Queue 实现

ADB PG 数据库是 MPP 架构,整体分为一个或多个 Master,以及多个 segment,数据在多个 segment 之间能够随机、哈希、复制散布。在 ADB PG 中,Resource Queue 的资源限度级别是语句级别,即在整条 SQL 执行的任何时刻,不论是否处于事务中,均会受到资源队列的限度。

如上文所述,Resource Group 反对对并发、CPU 和内存等进行限度,本节会具体介绍对这些资源进行限度的实现细节。

## 5.1 并发限度

ADBPG 数据库是多过程模型,分布式数据库的每个节点会启动多个子过程,各个子过程通过共享内存、共享信号量、共享音讯队列的形式实现过程间通信。

Resource Queue 基于分布式锁实现。在 ADBPG 中所有的 SQL 连贯首先会达到 Master 节点,在通过解析、优化,达到执行器层面时,会首先尝试获取 ResQueueLock 类型的排他锁。

在单个 ADB PG 节点中,同一时间只能有一个过程获取到 ResQueueLock 类型的排他锁,而每个过程只会蕴含单个线程。

在取得 ResQueueLock 类型的排他锁之后,执行 SQL 的后盾过程会读取及更新共享内存中的值,特地是队列中并发执行语句的计数值。若资源短缺,则会在更新完共享内存中对应资源队列中的资源使用量之后,开释 ResQueueLock,开始 SQL 的理论执行;

若资源有余,比方以后队列中正在运行的 SQL 数量曾经达到了所设定的并发上限值,对应的后盾过程则会 sleep 排队期待其余 query 执行结束后开释资源。

## 5.2 内存限度

对于内存的限度的实现形式与对并发限度的实现形式大体是统一的,只是对于判断资源队列中是否有资源来运行提交的 SQL 的形式有一些区别。

对于某个 Resource Queue 中的 SQL,可能应用的内存下限计算如下:

1)如果没有设定 resource queue 的 memory\_limit 值,那么间接取数据库的 statement\_mem 值;

2)如果设定了 resource queue 的 memory limit 值,则依据所设定的 resource queue 的 memory\_limit 值,计算资源组可能应用的内存总量;用总量除以 resource queue 设定的并发数,失去单条 SQL 所能利用的上限值。再将这个上限值与 statement\_mem 取一个最大值,作为 SQL 最终应用的内存上限值。

## 5.3 CPU 限度

Resource Queue 的 CPU 限度是一个很有意思的实现。ADB PG 专门为 Resource Queue CPU 限度的性能拉起了一个专门的过程:sweeper 过程来监控各个后盾过程的 CPU 应用,以及调节各个后盾过程的 CPU 份额。

这个过程是一个与数据库高度独立的过程,它没有加载一些缓存、资源类的货色,也无奈开启事务或者查零碎表,它的流动就是不停的读写共享内存,计算各个过程的 CPU 应用,更改 CPU 调配份额。各个理论执行 SQL 的后盾过程 (backend) 会依据所计算的 CPU 份额去休眠肯定的工夫,从而调节各个 SQL 理论的 CPU 使用率。

这个过程的主体流程如上,他的流程非常简单,就是一直地 sweep 和 sleep。

各个理论执行 SQL 的 backend 过程在启动时,会在共享内存中注册一些状态,并在执行过程中执行零碎调用 getrusage 等,更新 CPU 应用状态;sweeper 过程会依据这些共享内存状态,以及所设定的资源队列 CPU 利用值,在共享内存中更新对应 backend 过程的 CPU 份额(targetCPU)。而在 backend 运行过程中,则会调用 BackoffBackend,依据 CPU 份额来进行一段时间的休眠,从而调节整体的 CPU 利用率。

在运行过程中,分布式数据库的每个计算节点都会有一个 sweeper 过程来调节每个节点的 CPU 调用,使资源队列的 CPU 配置全局无效。

#

# 六 总结

资源管理对于数据库集群的多租户治理、资源细粒度调配具备很重要的价值。Resource Queue 可能对分布式数据库进行整体的资源管理和管制,在多租户隔离、保障数据库整体安稳运行具备肯定的价值。

除了 Resource Queue 的资源管理形式外,ADB PG 还反对 Resource Group 的资源管理形式,可能进行更精密的资源管制。Resource Group 现已在专有云环境提供应用,后续会逐渐在私有云提供能力。后续咱们会介绍 Resource Group 的根本应用和最佳实际。

> 版权申明:本文内容由阿里云实名注册用户自发奉献,版权归原作者所有,阿里云开发者社区不领有其著作权,亦不承当相应法律责任。具体规定请查看《阿里云开发者社区用户服务协定》和《阿里云开发者社区知识产权爱护指引》。如果您发现本社区中有涉嫌剽窃的内容,填写侵权投诉表单进行举报,一经查实,本社区将立即删除涉嫌侵权内容。

正文完
 0