阿里云HybridDB for PostgreSQL内存与负载管理(resource queue)实践

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

标签

PostgreSQL , Greenplum , 阿里云HybridDB for PostgreSQL , 内存管理 , OOM , 操作系统内核参数 , 资源队列 , 数据库内存保护参数


背景

Greenplum是一个重计算和重资源的MPP数据库,可谓有多少资源就能消耗多少资源,带来的好处是处理速度变快了,坏处就是容易用超。

CPU、网络、硬盘用超的话,关系不大,因为大不了就是到硬件瓶颈,但是内存用超的话会带来较大的负面影响,例如操作系统OOM用户进程,导致数据库崩溃等。

如果要达到非常强壮的稳定性,Greenplum内存的配置非常的关键。(当然代码本身的质量也很关键)

如何避免OOM

OOM指遇到了进程申请内存不足的错误。例如

Out of memory (seg27 host.example.com pid=47093)  
VM Protect failed to allocate 4096 bytes, 0 MB available  

哪些情况会引发OOM

导致数据库OOM报错的原因可能有:

1、数据库节点的内存不足。

2、操作系统内存相关的内核参数配置不当。

3、数据倾斜,导致某些查询时,某个SEGMENT需要申请的内存超大。

4、查询倾斜,例如某些聚合、窗口函数的分组不是分布键,那么需要对数据进行重分布,重分布后导致某个SEGMENT的数据出现倾斜,导致某些查询是,某个SEGMENT需要申请的内存超大。

如何避免OOM

1、调整QUERY,使之需要更少的内存。

2、使用资源队列(Greenplum控制资源的一种手段),限制并发QUERY数。降低集群内同时运行的QUERY数,从而减少系统整体的内存资源的使用。

3、减少单个主机部署的SEGMENT数量,例如有128G内存的主机,部署16个和部署8个SEGMENT节点,每个节点能使用的内存相差了一倍。

4、增加单台主机的内存数。

5、设置数据库参数gp_vmem_protect_limit,限制单个SEGMENT可以使用的VMEM上限。单个主机的内存以及部署多少个SEGMENT决定了平均单个SEGMENT最多可以使用多少内存。

6、对于某些对内存使用量不可预知的SQL,通过在会话中设置statement_mem参数,限制单条SQL对内存的使用,从而避免单条SQL把内存吃光的情况。

7、也可以在库级别设置statement_mem参数。对这个数据库的所有会话生效。

8、使用资源队列(Greenplum控制资源的一种手段),限制这个资源组的内存使用上限,将数据库用户加入资源组,控制这些用户共同使用内存的上限。

如何配置内存相关参数

正确的配置(操作系统、数据库参数、资源队列管理)可以有效的降低OOM发生的概率。

1、加内存并不是最有效的方法,因为加内存还有成本问题,而且无法避免所有问题。

2、在计算单主机内单个SEGMENT的平均可使用内存时,不能只考虑primary segment,还需要考虑mirror segment,因为当集群出现主机故障时,会将SEGMENT切换到对应的MIRROR,此时,主机上跑的SEGMENT数就比平时更多了。

因此我们必须考虑到failover时,mirror需要占用的资源。

接下来我们分析一下操作系统内核配置、数据库配置。如何让数据库尽量的避免OOM。

操作系统内核参数

1、不要配置系统的huge page,因为Greenplum的PG版本较老,还没有支持huge page。而操作系统的huge page会锁定内存的分配,导致这部分内存不能被数据库节点使用。

2、vm.overcommit_memory,如果使用SWAP建议设置为2,如果不使用SWAP建议设置为0。

==============================================================      
.    
overcommit_memory:      
.    
This value contains a flag that enables memory overcommitment.      
.    
When this flag is 0,       // 比较友好,允许申请的内存空间通常不能超过"总内存-不可释放内存(RSS部分)"的部分。超过时申请内存才会报错。      
the kernel attempts to estimate the amount      
of free memory left when userspace requests more memory.      
.    
When this flag is 1,       // 比较暴力,因为大多数进程不管三七二十一,先使用malloc申请一打开空间,但是不使用它或者是只使用部分。所以设置为2时,不管什么情况都允许malloc申请成功,除非遇到真的内存不足的情况。  
the kernel pretends there is always enough memory until it actually runs out.      
.    
When this flag is 2,       // 最友好,在计算允许申请的内存空间时,将SWAP也算进去,也就是说申请大量内存时,可能触发SWAP但是允许你申请成功。  
                           // 在开启SWAP的时候,建议设置为2。GPDB官网也推荐设置为2。主要是防止OOM。  
the kernel uses a "never overcommit"      
policy that attempts to prevent any overcommit of memory.      
Note that user_reserve_kbytes affects this policy.      
.    
This feature can be very useful because there are a lot of      
programs that malloc() huge amounts of memory "just-in-case"      
and don't use much of it.      
.    
The default value is 0.      
.    
See Documentation/vm/overcommit-accounting and      
security/commoncap.c::cap_vm_enough_memory() for more information.      
.    
==============================================================      
.    
overcommit_ratio:      
.    
When overcommit_memory is set to 2,   // 当设置为2时,允许申请的内存地址范围不能超过“swap+内存大小*overcommit_ratio”  
the committed address space is not permitted to exceed     
      swap + this percentage of physical RAM.      
See above.      
.    
==============================================================     

3、overcommit_ratio,越大允许用户进程申请的内存空间越大,但是给操作系统保留的空间就越小。需要一个公式来计算。具体参考后面的例子。

数据库参数

1、gp_vmem_protect_limit

控制每个segment上,所有进程可以申请到的最大内存。如果这个值太高,可能触发系统的OOM或者更严重的问题。如果设置太低,则可能导致系统有足够内存的情况下,SQL确无法运行。

后面有设置公式。

2、runaway_detector_activation_percent

这个参数默认为90,是一个百分比值。当任一SEGMENT使用的内存超过(runaway_detector_activation_percent*gp_vmem_protect_limit/100)时,主动terminate QUERY。防止OOM。

terminate 的顺序从使用最多内存的QUERY依次开始,直到内存降低到(runaway_detector_activation_percent*gp_vmem_protect_limit/100)以下。

通过 gp_toolkit.session_level_memory_consumption 视图可以观察每个会话的内存使用情况,以及runaway的信息。

3、statement_mem

默认为125MB。设置单条SQL最多可以申请的内存,当超过这个内存时,写spill file文件。

建议的设置为单个SEGMENT的保护内存乘以0.9除以期望的最大SQL并行运行的值。

(gp_vmem_protect_limit * 0.9) / max_expected_concurrent_queries  

注意1,statement_mem在会话中设置,如果当前并行度很低,某个会话需要RUN一条需要大量内存的QUERY,可以在会话中设置一下。

注意2,statement_mem比较适合低并发的环境对内存的使用控制。对于高并发的环境,如果使用statement_mem来控制内存,你会发现每条QUERY可以使用的内存极少,不利于高并发情况下少量对内存需求多的QUERY的性能。建议高并发的情况下,使用资源队列(resource queue)来控制内存的使用上限。

4、gp_workfile_limit_files_per_query

限制每个QUERY可以使用的最大spill文件数(当QUERY申请的内存超过statement_mem的限制时,使用spill file(workfiles),类似操作系统的swap空间)。当使用的spill file超过限制时,QUERY会被terminate。

默认为0,表示无限制。

5、gp_workfile_compress_algorithm

设置spill file的压缩算法。Valid values are "NONE", "ZLIB".

设置压缩,CPU换空间,或CPU换IO能力。当磁盘紧张、磁盘spill file有写入瓶颈时可以设置压缩。

内存参数计算例子

gp_vmem,gp_vmem_protect_limit,vm.overcommit_ratio,设置举例:

环境如下:

主机配置:  
  
Total RAM = 256GB  
  
SWAP = 64GB  
  
部署配置:  
8 primary segments and 8 mirror segments per host, in blocks of 4 hosts (4台主机)  
  
当挂掉一台主机时,8个PRIMARY要分摊到剩余的3台主机,最多单台额外承担3个PRIMARY。所以是8+3=11。  
Maximum number of primaries per host during failure is 11  

1、首先计算给gpdb的总内存

(给操作系统保留 "7.5G + 5%内存" 的余量,算出整个系统给应用软件的实际可用内存。),然后(实际可用内存 除以 1.7的经验系数)

gp_vmem = ((SWAP + RAM) – (7.5GB + 0.05 * RAM)) / 1.7  
        = ((64 + 256) - (7.5 + 0.05 * 256)) / 1.7   
        = 176  

2、计算overcommit_ratio,用到了一个经验系数0.026。

vm.overcommit_ratio = (RAM - (0.026 * gp_vmem)) / RAM   
                    = (256 - (0.026 * 176)) / 256   
                    = .982  
  
Set vm.overcommit_ratio to 98.  

3、计算每个segment的内存使用上线保护参数:gp_vmem_protect_limit,除以挂掉一台节点后单台节点需要运行的primary数。

gp_vmem_protect_limit calculation  
gp_vmem_protect_limit = gp_vmem / maximum_acting_primary_segments  
                      = 176 / 11   
                      = 16GB  
                      = 16384MB  

资源队列的使用

Greenplum resource queue可以用来限制“并发的QUERY数、总的内存使用”。当QUERY运行时,会添加到对应的队列中,使用的资源将记录到对应的队列中,对应队列的资源控制限制对该队列内的所有会话起作用。

Greenplum资源队列控制资源的思想和Linux 的CGROUP非常类似。

一、创建资源队列的语法:

Command:     CREATE RESOURCE QUEUE  
Description: create a new resource queue for workload management  
Syntax:  
CREATE RESOURCE QUEUE name WITH (queue_attribute=value [, ... ])   
where queue_attribute is:  
   ACTIVE_STATEMENTS=integer  
        [ MAX_COST=float [COST_OVERCOMMIT={TRUE|FALSE}] ]  
        [ MIN_COST=float ]  
        [ PRIORITY={MIN|LOW|MEDIUM|HIGH|MAX} ]  
        [ MEMORY_LIMIT='memory_units' ]  
|  MAX_COST=float [ COST_OVERCOMMIT={TRUE|FALSE} ]   
        [ ACTIVE_STATEMENTS=integer ]  
        [ MIN_COST=float ]  
        [ PRIORITY={MIN|LOW|MEDIUM|HIGH|MAX} ]  
        [ MEMORY_LIMIT='memory_units' ]  

解释

1、ACTIVE_STATEMENTS ,允许同时运行(active状态)的SQL数。 -1不限。

2、MEMORY_LIMIT 'memory_units kB, MB or GB' , 设置资源队列中所有SQL允许的最大内存使用量。 -1不限(但是受前面提到的数据库或系统参数限制,触发OOM错误。)。

SQL的内存使用限制不仅受资源队列限制,同时还受到参数限制:

2.1 参数gp_resqueue_memory_policy=none时,限制同Greenplum Database releases prior to 4.1。

2.2 参数gp_resqueue_memory_policy=auto时,如果设置了会话的statement_mem参数,或者设置了statement_mem参数时,单条QUERY允许申请的内存将突破资源队列的MEMORY_LIMIT限制。

例子

=> SET statement_mem='2GB';  
=> SELECT * FROM my_big_table WHERE column='value' ORDER BY id;  
=> RESET statement_mem;  

注意,还有一个系统参数max_statement_mem,这个可以理解为SEGMENT级别的内存使用安全控制阀,单个QUERY申请的memory不能超过max_statement_mem。

意思是你可以随便改会话级的statement_mem参数,但是不要随便改max_statement_mem参数。

建议的max_statement_mem设置:

(seghost_physical_memory) / (average_number_concurrent_queries)  

2.3 参数gp_resqueue_memory_policy=eager_free时,表示数据库在评估SQL对内存的申请渴望时,分阶段统计,也就是说一个SQL可能总共需要申请1G内存,但是每个阶段只申请100MB,所以需要的内存实际上是100MB。

使用eager_free策略,可以降低QUERY报内存不足的可能性。

3、MAX_COST float,设置为浮点或指数((for example 100.0),(for example 1e+2)),-1不限制。

表示资源组允许同时执行的QUERY加起来的COST上限。COST是SQL执行计划中的总成本。

4、COST_OVERCOMMIT boolean,当系统空闲时,是否允许(TRUE)超过max_cost的限制。

5、MIN_COST float,(资源超限时,是需要排队的)但是,当QUERY的成本低于min_cost时,不需要排队,直接运行。(也就是说小查询,就让他跑吧。)

6、PRIORITY={MIN|LOW|MEDIUM|HIGH|MAX},指当前资源队列的优先级,当资源紧张时,优先将CPU资源分配给高优先级的资源队列。(处于高优先级的资源队列中的SQL,可以获得更高优先级的CPU资源)。建议将实时性要求高的查询对应的用户分配到高优先级的资源队列中。

类似LINUX CGROUP中的CPU资源组,real time task和普通task的时间片策略。

二、修改资源队列限制举例:

ALTER RESOURCE QUEUE myqueue WITH (MAX_COST=-1.0, MIN_COST= -1.0);  

三、如何将用户放到资源队列中,举例:

ALTER ROLE sammy RESOURCE QUEUE poweruser;  

四、资源队列相关参数

1、gp_resqueue_memory_policy,资源队列的内存管理策略,前面讲了用法。

2、gp_resqueue_priority,是否使用资源队列的优先级。ON使用,OFF不使用。不使用资源队列优先级时,所有队列公平对待。

3、gp_resqueue_priority_cpucores_per_segment,每个SEGMENT可以使用的CPU核数,例如8核的机器,跑了2个PRIMARY SEGMENT,则配置为4。master 上面如果没有其他节点,配置为8。

当发生CPU抢占时,优先级高的资源组中运行的SQL,优先分配CPU资源。

4、gp_resqueue_priority_sweeper_interval,CPU时间片统计间隔,SQL执行时,计算它的share值(根据优先级以及计算gp_resqueue_priority_cpucores_per_segment出来)。

越小越频繁,优先级设置带来的效果越好。但是overhead越大。

五、建议的资源队列使用方法:

1、GPDB默认的资源队列为pg_default,如果不创建队列,那么所有的用户都会被指定给pg_default。这是非常不建议的。

建议的做法是为每个用户创建一个资源队列。(因为通常一个数据库用户对应一个业务。不同的数据库用户可能对应不同的业务或者使用者(例如业务用户、分析师用户、开发者、DBA等)。)

2、超级用户发起的SQL请求不受资源队列的限制,仅仅受前面讲到的参数的限制。因此如果要使用resource queue来限制资源的使用,那么就不建议业务使用超级用户来执行QUERY。

3、ACTIVE_STATEMENTS表示资源队列中,允许同时执行的SQL。(注意当QUERY的成本低于min_cost时,不需要排队,直接运行。)

4、MEMORY_LIMIT,设置资源队列中所有SQL允许的最大内存使用量。前面讲了突破方法,statement_mem设置的优先级更高,可以突破resource queue的限制。

注意所有资源队列的内存加起来不要超过gp_vmem_protect_limit的限制。

5、通过配置资源队列的优先级,可以区分不同的业务。例如出报表的业务优先级最高,其次是普通业务,其次是分析师。这样的情况,我们可以创建3个资源队列,分别使用MEDIUM|HIGH|MAX的优先级。

6、如果每个时间段的资源需求不一样,可以写一个CRONTAB任务,定时的调整资源队列的限制。

例如白天分析师的优先级更高,晚上处理报表的队列优先级更高。

目前Greenplum还不支持按时间段来设置资源限制,所以只能外部部署任务,alter resource queue来实现。

7、通过gp_toolkit提供的视图,可以观察资源队列的资源使用。

gp_toolkit.gp_resq_activity              
  
gp_toolkit.gp_resq_activity_by_queue     
  
gp_toolkit.gp_resq_priority_backend      
  
gp_toolkit.gp_resq_priority_statement    
  
gp_toolkit.gp_resq_role                  
  
gp_toolkit.gp_resqueue_status  

参考

http://greenplum.org/docs/best_practices/workloads.html

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
17天前
|
运维 算法 安全
深入理解操作系统的内存管理:原理与实践
【4月更文挑战第25天】 在现代计算机系统中,操作系统扮演着至关重要的角色,它负责协调和管理硬件资源,为上层应用提供必要的服务。其中,内存管理是操作系统的核心功能之一,它不仅关乎系统性能,也直接影响到系统的稳定性和安全性。本文将深入探讨操作系统内存管理的关键原理,包括虚拟内存、物理内存分配、分页机制以及内存保护等,并结合Linux操作系统实例,分析其内存管理的实现细节。通过理论与实践的结合,旨在为读者提供一个全面、深入的操作系统内存管理视角。
|
19天前
|
算法 调度 UED
深入理解操作系统内存管理:原理与实践
【4月更文挑战第23天】 在现代计算机系统中,操作系统的内存管理是保证系统高效、稳定运行的关键组成部分。本文旨在深入探讨操作系统中内存管理的理论基础、关键技术以及实际操作过程,通过对内存分配策略、虚拟内存技术、分页与分段机制等核心概念的详细解析,为读者提供一个清晰、全面的内存管理视角。此外,文章还将通过案例分析,展示内存管理在解决实际问题中的应用,以期加深读者对操作系统内存管理复杂性的认识和理解。
|
11天前
|
存储 弹性计算 固态存储
阿里云服务器CPU内存配置详细指南,如何选择合适云服务器配置?
阿里云服务器配置选择涉及CPU、内存、公网带宽和磁盘。个人开发者或中小企业推荐使用轻量应用服务器或ECS经济型e实例,如2核2G3M配置,适合低流量网站。企业用户则应选择企业级独享型ECS,如通用算力型u1、计算型c7或通用型g7,至少2核4G配置,公网带宽建议5M,系统盘可选SSD或ESSD云盘。选择时考虑实际应用需求和性能稳定性。
118 6
|
14天前
|
Cloud Native 关系型数据库 OLAP
云原生数据仓库产品使用合集之阿里云云原生数据仓库AnalyticDB PostgreSQL版的重分布时间主要取决的是什么
阿里云AnalyticDB提供了全面的数据导入、查询分析、数据管理、运维监控等功能,并通过扩展功能支持与AI平台集成、跨地域复制与联邦查询等高级应用场景,为企业构建实时、高效、可扩展的数据仓库解决方案。以下是对AnalyticDB产品使用合集的概述,包括数据导入、查询分析、数据管理、运维监控、扩展功能等方面。
|
1天前
|
安全 Devops 测试技术
深入了解阿里云云效DevOps:构建高效软件开发实践
阿里云云效DevOps,集成CI/CD与自动化测试,提升开发效率。支持持续集成确保代码质量,自动化测试加速交付,多环境及灰度发布保障安全可靠性。助团队构建高效开发实践,增强竞争力。
7 1
|
6天前
|
存储 监控 Apache
查询提速11倍、资源节省70%,阿里云数据库内核版 Apache Doris 在网易日志和时序场景的实践
网易的灵犀办公和云信利用 Apache Doris 改进了大规模日志和时序数据处理,取代了 Elasticsearch 和 InfluxDB。Doris 实现了更低的服务器资源消耗和更高的查询性能,相比 Elasticsearch,查询速度提升至少 11 倍,存储资源节省达 70%。Doris 的列式存储、高压缩比和倒排索引等功能,优化了日志和时序数据的存储与分析,降低了存储成本并提高了查询效率。在灵犀办公和云信的实际应用中,Doris 显示出显著的性能优势,成功应对了数据增长带来的挑战。
查询提速11倍、资源节省70%,阿里云数据库内核版 Apache Doris 在网易日志和时序场景的实践
|
8天前
|
算法 安全 Linux
深入理解操作系统的内存管理:原理与实践
【5月更文挑战第4天】 在现代计算领域,操作系统的内存管理是保证系统稳定、高效运行的关键。本文旨在深入剖析操作系统内存管理的基本原理,包括虚拟内存、物理内存、分页机制和内存交换等概念。同时,文章将探讨如何通过优化内存分配策略,提升系统性能及响应速度。此外,还将讨论当前流行的操作系统(如Linux和Windows)中内存管理的创新技术及其应用案例。
|
12天前
|
缓存 算法 内存技术
深入理解操作系统内存管理:原理与实践
【4月更文挑战第30天】本文旨在深入探讨操作系统中的内存管理机制,包括物理内存的分配与回收、虚拟内存技术、分页系统以及内存优化策略。通过对内存管理概念的详细解读和实际案例分析,读者将获得对操作系统如何处理内存资源的全面认识,并了解如何在实践中应用这些知识以提高系统性能和稳定性。
|
12天前
|
测试技术 块存储 开发者
阿里云块存储团队软件工程实践
本文介绍了阿里云团队软件工程实际开发流程,并简述了开发过程中遇到的一些问题。且附带案例,以及遇到案例中出现的情况应当如何应对。
|
13天前
|
存储 算法 安全
深入理解操作系统内存管理:原理与实践
【4月更文挑战第29天】 在现代计算机系统中,操作系统的内存管理是其核心功能之一。有效的内存管理不仅关乎系统性能,也直接影响到用户程序的稳定性和安全性。本文将详细探讨操作系统内存管理的基本原理、关键技术以及当前的挑战和创新方向。通过对页式管理、段式管理和段页式管理等技术的深入分析,我们旨在为读者提供一个清晰、系统的内存管理知识框架,并讨论虚拟内存技术如何帮助解决物理内存不足的问题。同时,考虑到安全性日益成为关注焦点,文中还将介绍内存保护机制和内存隔离技术。最后,结合最新的硬件发展趋势,如非易失性内存(NVM)的出现,本文也将对内存管理的未来发展方向进行展望。

相关产品

  • 云原生数据库 PolarDB