实践丨GaussDB(DWS)资源管理排队原理与问题定位

摘要:GaussDB(DWS)提供了资源管理功能,用户可以根据自身业务情况对资源进行划分,将资源按需划分成不同的资源池,不同资源池之间资源互相隔离。

本文分享自华为云社区《​​GaussDB(DWS)资源管理排队原理与问题定位​​》,作者: 门前一棵葡萄树 。

一、内存管控原理

GaussDB(DWS)提供了资源管理功能,用户可以根据自身业务情况对资源进行划分,将资源按需划分成不同的资源池,不同资源池之间资源互相隔离。再通过用户关联资源池的方式将数据库用户关联至不同的资源池,用户查询依据“用户-资源池”的关联关系将查询路由至对应资源池执行,以此实现对查询并发、内存及CPU资源的管控。从而实现对不同业务之间的资源限制和隔离,满足数据库混合负载需求,保证查询执行时资源调度的有序可控,防止烂SQL影响整个集群。

1.1 自适应内存

传统内存管理场景下,使用work_mem限制算子可以使用的内存上限,通常复杂查询的执行计划中包含多个算子,每个算子可能需要使用的内存并不相同,但是每个算子可用的内存上限均为work_mem,很难找到一个最优的work_mem取值,一方面保证查询性能满足预期,一方面还需要保证不会导致内存报错。在查询并发场景下,静态内存管理的work_mem及并发上限就更难设置了。单查询算子数量从0~N不等,设置work_mem后无法实现语句级内存资源使用的控制,多并发场景下可能会导致内存资源不受控,进而导致OOM。

针对传统内存管理的弊端,GaussDB(DWS)设计实现了内存自适应技术:

  • 解除对work_mem的依赖,优化器依据统计信息对查询使用内存进行估算;
  • 执行器执行SQL过程中,如果使用内存超过估算内存即触发下盘;
  • 资源管理依据优化器估算的查询内存,对查询进行调度和管控。

另外,为保证多CN场景下的内存可控,设计实现CCN用于查询的统一调度,以此保证所有CN上运行的查询使用内存之和不会超过内存上限,进而导致内存不足引发报错。CM在第一次集群启动时,通过集群部署形式,选择编号最小的CN作为CCN,CCN故障之后,由CM选择新的CCN进行替换

CCN管控与CN管控间差异及优劣:

  • CN管控查询由各CN单独调度,各CN间互相不感知负载情况,无法准确感知和控制整个集群并发,内存管控效果有限,有可能出现内存报错;
  • CCN管控查询由CCN统一调度,结合DN内存负反馈机制,CCN可以感知集群整体负载,内存管控更加精准,可以消除内存不足报错;
  • CCN管控涉及CN与CCN之间的通信,通信延迟可能带来查询性能的不稳定;通信延迟与网络环境及查询并发度有关,大概10ms~ 1s不等;
  • CCN管控相对CN管控逻辑更加复杂,除涉及资源池内存/并发管控外,还包含CCN全局内存管控,在作业管控和唤醒时都需要进行两层逻辑判断;
  • CCN管控因为所有查询都需要由CCN统一调度,因此管控时发生所冲突的可能性就更大。

综上所述,CN管控对查询性能影响较小,但是内存管控效果有限,CCN管控对查询性能影响可能较大,但是可以实现内存精准管控,消除内存不足报错。

为实现更为精细的管控,我们根据查询预期执行时间和资源消耗,将查询划分为执行时间长、资源消耗多的复杂查询和执行时间短、资源消耗少的简单查询。简单查询和复杂查询的划分与资源消耗密切相关,同时因为查询执行前就需要划分简单/复杂查询,因此根据估算内存(代价)对查询进行划分:

  • 简单查询:估算内存小于32MB;
  • 复杂查询:估算内存大于等于32MB。

混合负载场景下,虽然简单查询本身执行时间短、消耗资源少,但是因为复杂查询可能会长时间大量占用资源,进而导致资源耗尽,使得简单查询不得不在队列中等待复杂查询执行完成。为提升执行效率、提高数据库整体吞吐量, 设计实现“短查询加速”功能,实现对简单查询的单独管控。

  • 开启短查询加速后,简单查询与复杂查询分别进行管控。
  • 关闭短查询加速后,简单查询与复杂查询一起进行管控。

虽然单个简单查询资源消耗少,但是大量简单查询并发运行还是可能占用大量资源,另外对简单查询进行CCN管控可能会影响查询性能,降低吞吐量。因此为降低对查询的性能影响,同时实现内存管控目的,我们仅对复杂查询进行CCN并发和内存管控,简单查询由各自CN单独进行并发控制

1.2 内存管控能力

GaussDB(DWS) 内存管控分为三级,分别是:

  1. 实例级内存管控:通过max_process_memory限制CN、DN可以使用的内存上限;
  2. 资源池内存管控:通过资源池参数mem_percent限制资源池内存使用,结合优化器估算的查询内存,实现资源池之间的内存隔离;
  3. 作业内存管控:查询优化器根据统计信息估算查询执行时使用内存的最大值,查询以估算内存为准向资源管理申请内存资源,查询执行过程中使用内存超过估算内存即触发下盘。

基于优化器给出的查询估算内存,资源管理提供了两种内存管控方式:

  1. 静态内存管控(单CN管控):各CN互不感知,分别进行管控,多CN同时下发作业可能导致内存不可控;
  2. 动态内存管控(CCN管控):估算内存大于32MB的查询统一由CCN调度,结合DN内存负反馈机制,CCN感知集群整体负载,实现内存的精准管控。

特例:

  1. 静态内存管控关闭(资源池mem_percent=0)或查询估算内存为0情况下,查询执行过程中使用work_mem控制每个算子可以使用的内存上限,多算子并行可能导致内存不受控;
  2. 默认资源池支持DN上内存扩展,DN内存资源充足情况下查询可以使用更多内存,提升查询执行性能。

通过以上描述,其实不难看出内存管控的基础是优化器的内存估算,内存估算准确可以实现内存的精准管控,内存估算不准可能引起一系列的问题:

  1. 内存估算小使用大(DN内存扩展),可能导致内存报错;
  2. 内存估算大使用小,可能导致内存利用率低,吞吐量上不去;
  3. 内存估算过大,可能导致CCN/CN异常排队。

基于以上问题,资源管理做了以下功能降低估算不准带来的影响:

  1. 资源池增加参数memory_limit,用于配置单查询估算内存上限,默认情况下查询估算内存上限为资源池内存*0.4,实际场景下可按需设置该值大小,理论上查询估算内存不应超过该值;
  2. 内存负反馈:正在执行的作业查询估算内存之和超过总内存40%,实际使用内存低于估算内存60%时触发内存负反馈,按照一定比例逐步降低查询估算内存记账值,以此下发更多查询,提升内存使用率;

查询估算内存兜底机制(820-1230):在查询估算内存超过单查询估算内存上限时,对查询估算内存进行修正,按照单查询估算内存上限进行管控。

二、排队原理与问题排查

2.1 排队原理

GaussDB(DWS)可能在以下情况下发生排队:

  1. 单CN并发控制:单个CN上查询并发超过max_active_statements引发排队;
  2. 资源池快车道并发控制:资源池上简单查询并发超过资源池参数max_dop引发排队;
  3. 资源池慢车道并发控制:资源池上复杂查询并发超过资源池参数active_statements引发排队;
  4. 资源池慢车道内存管控:资源池上运行的复杂查询估算内存之和超过资源池参数mem_percent配置的资源池内存上限引发排队;
  5. CCN全局内存管控:所有CN上运行的查询内存估算内存/使用内存超过DN内存上限(max_dynamic_memory)引发排队。

特例:初始用户及白名单语句不受控。

2.2 常见视图

GaussDB(DWS)对外提供诸多系统视图,可以用来辅助资源管理及资源使用相关问题的分析定位,常用视图及用法说明如下表所示。(☆代表常用程度)

实践丨GaussDB(DWS)资源管理排队原理与问题定位

除过上述常用视图,资源管理问题定位过程需要根据实际场景,结合实例日志、集群状态等共同分析定位。

2.3 自定义视图

为方便迅速定位问题,根据现网实践经验对以上常见视图进行组合,整合了三个问题定位过程中的常用视图:资源池监控视图、用户监控视图以及作业监控视图。与上面内置视图相比,这几个视图依据现网定位经验与分布式数据库特点,对查询结果做了针对性优化,同时优化了字段显示,用户更易理解,可以作为常规监控视图使用。具体视图定义可参考附件。

实践丨GaussDB(DWS)资源管理排队原理与问题定位

2.4 排队问题排查

出现业务阻塞、性能下降、查询无响应等类似现网问题时,通过以下方法可以排查是否排队问题并定位排队原因,同时根据排队原因给出相应规避措施。

Step1确认是否排队

首先确认是否排队问题,其次排查排队原因,确认是否属于正常排队:

  • 813及以上版本可以查询资源池监控视图
SELECT * FROM pgxc_respool_runtime_info ORDER BY 1,2,3;
  • 811及以上版本可以作业运行监控视图
SELECT 
s.resource_pool AS rpname, s.node_group,
count(1) AS session_cnt,
SUM(CASE WHEN a.enqueue = 'waiting in global queue' THEN 1 ELSE 0 END) AS global_wait,
SUM(CASE WHEN s.lane= 'fast' AND a.state = 'active' AND (a.enqueue IS NULL OR a.enqueue = 'no waiting queue') THEN 1 ELSE 0 END) AS fast_run,
SUM(CASE WHEN s.lane= 'fast' AND a.enqueue = 'waiting in respool queue' THEN 1 ELSE 0 END) AS fast_wait,
SUM(CASE WHEN s.lane= 'slow' AND a.state = 'active' AND (a.enqueue IS NULL OR a.enqueue = 'no waiting queue') THEN 1 ELSE 0 END) AS slow_run,
SUM(CASE WHEN s.lane= 'slow' AND (a.enqueue = 'waiting in ccn queue' OR a.enqueue = 'waiting in respool queue') THEN 1 ELSE 0 END) AS slow_wait,
SUM(CASE WHEN (a.enqueue IS NULL OR a.enqueue = 'no waiting queue') AND a.state = 'active' THEN statement_mem ELSE 0 END) AS est_mem
FROM pgxc_session_wlmstat s,pgxc_stat_activity a
WHERE s.threadid=a.pid(+) AND s.attribute != 'Internal'
GROUP BY 1,2
  • 800版本查询作业运行监控视图
SELECT 
s.resource_pool AS rpname, s.node_group,
count(1) AS session_cnt,
SUM(CASE WHEN a.enqueue = 'waiting in global queue' THEN 1 ELSE 0 END) AS global_wait,
SUM(CASE WHEN s.attribute= 'Simple' AND a.state = 'active' AND (a.enqueue IS NULL OR a.enqueue = 'no waiting queue') THEN 1 ELSE 0 END) AS fast_run,
SUM(CASE WHEN s.attribute= 'Simple' AND a.enqueue = 'waiting in respool queue' THEN 1 ELSE 0 END) AS fast_wait,
SUM(CASE WHEN s.attribute= 'Complicated' AND a.state = 'active' AND (a.enqueue IS NULL OR a.enqueue = 'no waiting queue') THEN 1 ELSE 0 END) AS slow_run,
SUM(CASE WHEN s.attribute= 'Complicated' AND (a.enqueue = 'waiting in ccn queue' OR a.enqueue = 'waiting in respool queue') THEN 1 ELSE 0 END) AS slow_wait,
SUM(CASE WHEN (a.enqueue IS NULL OR a.enqueue = 'no waiting queue') AND a.state = 'active' THEN statement_mem ELSE 0 END) AS est_mem
FROM pgxc_session_wlmstat s,pgxc_stat_activity a
WHERE s.threadid=a.pid(+) AND s.attribute != 'Internal'
GROUP BY 1,2;

某些老版本不存在pgxc_session_wlmstat视图,可以参考附件创建类似函数/视图。

  • 直接查询自定义视图

通过查询自定义视图可以获取到各资源池快慢车道作业运行信息以及作业排队信息,据此可以直接判断是否排队问题。

Step2 排查排队原因

常见排队原因及解决措施

实践丨GaussDB(DWS)资源管理排队原理与问题定位

1.全局并发排队

  • 单CN实际运行作业数≥全局并发上限,则全局并发排队正常;
  • 单CN实际运行作业数长时间小于全局并发上限,则可能存在计数泄露。

2.快车道排队

  • 快车道实际运行作业数≥快车道并发上限,则快车道并发排队正常;
  • 快车道实际运行作业数长时间小于快车道并发上限,则可能存在计数泄露。

3.静态慢车道排队

  • 慢车道实际运行作业数≥慢车道并发上限,则慢车道并发排队正常;
  • 慢车道实际运行作业累计估算内存≥慢车道内存上限,则慢车道内存占用达到上限导致排队,关注是否有查询估算内存过大;
  • 如果慢车道并发和内存占用长时间达不到上限,则可能存在计数泄露。

4.动态CCN排队

如果查询在CCN排队,可使用附件中自定义资源池监控视图和作业监控视图确认排队原因,或查询CCN开发者视图确认排队原因(不推荐):

SELECT * FROM pg_stat_get_workload_struct_info();

CCN上可能的排队原因:

  • CCN全局可用内存不足导致排队,此时需特别关注是否有查询估算内存过大;
  • 资源池实际运行作业数≥慢车道车道并发上限,资源池并发上限,正常排队;
  • 资源池实际运行作业累计估算内存≥慢车道内存上限,则慢车道内存占用达到上限导致排队,此时需特别关注是否有查询估算内存过大;
  • 资源池实际运行作业数或占用内存与记账值不符,则可能存在计数泄露BUG;
  • 队首作业在CCN哈希中不存在,说明队首作业残留导致查询不能正常下发;
  • CN/CCN处于recover状态或收集DN内存信息失败(多CCN)导致所有查询等待5s下发,现象为所有查询排队时间均为5~6s。

附件:​​自定义监控视图.rar18.11KB​​

​​点击关注,第一时间了解华为云新鲜技术~​​