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

数据库节点内存不足

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

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

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

数据库节点内存不足

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

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

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

如何避免 OOM

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

2、使用资源队列(resource queue,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、使用资源队列,限制这个资源组的内存使用上限,将数据库用户加入资源组,控制这些用户共同使用内存的上限。

如何配置内存相关参数

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

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

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

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

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

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

操作系统内核参数

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

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

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

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

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

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

数据库参数

gp_vmem_protect_limit

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

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 的信息。

statement_mem

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

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

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

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

gp_workfile_limit_files_per_query

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

gp_workfile_compress_algorithm

设置 spill file 的压缩算法。有效值如下:

none。默认值,表示不用压缩选项

zlib。使用 zlib 算法压缩

none。默认值,表示不用压缩选项

zlib。使用 zlib 算法压缩

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

内存参数计算例子

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

环境如下:

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

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

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

资源队列的使用

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

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

一、创建资源队列的语法

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

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

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

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

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

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

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

参数 gp_resqueue_memory_policy=eager_free时,表示数据库在评估 SQL 对内存的申请需求时,分阶段统计,也就是说一个 SQL 可能总共需要申请 1G 内存,但是每个阶段只申请 100MB,所以需要的内存实际上是 100MB。使用 eager_free 策略,可以降低 QUERY 报内存不足的可能性。

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

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

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

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

参数 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 的时间片策略。

二、修改资源队列限制

举例如下:

三、如何将用户放到资源队列中

举例如下:

四、资源队列相关参数

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 提供的视图,可以观察资源队列的资源使用。

参考

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

作者介绍

digoal(德哥,周正中),阿里云数据库内核技术架构师,PostgreSQL 中国社区发起人之一、常委、兼任社区大学校长,PostgreSQL 中国社区杭州分会会长,DBA+ 社群联合发起人,DBGeeK 联盟专家团成员。

oom 如何避免 高并发_【转载】如何避免OOM?看Greenplum的最佳实践相关推荐

  1. oom 如何避免 高并发_【高并发】高并发环境下如何防止Tomcat内存溢出?看完我懂了!!...

    [高并发]高并发环境下如何防止Tomcat内存溢出?看完我懂了!! 发布时间:2020-04-19 00:47, 浏览次数:126 , 标签: Tomcat 写在前面 随着系统并发量越来越高,Tomc ...

  2. oom 如何避免 高并发_【面试题】如何设计一个高并发系统?

    面试题 如何设计一个高并发系统? 原文链接:https://github.com/doocs/advanced-java/blob/master/docs/high-concurrency/high- ...

  3. oom 如何避免 高并发_微博短视频百万级高可用、高并发架构如何设计?

    本文从设计及服务可用性方面,详细解析了微博短视频高可用.高并发架构设计中的问题与解决方案. 今天与大家分享的是微博短视频业务的高并发架构,具体内容分为如下三个方面: 团队介绍 微博视频业务场景 &qu ...

  4. oom 如何避免 高并发_如何设计这样一个高并发系统?

    netty处理socket连接,直接用定长协议的decoder即可,可以把你们这个状态数据作为维持长连接的心跳,比如3分钟内无数据连接关闭.这块高并发没什么难度1-2台机器解决问题,毕竟逻辑简单量还好 ...

  5. oom 如何避免 高并发_【面试】如何避免OOM的发生

    小编基础薄弱,发的内容不算是抄袭,但也基本都是借鉴,若有不足的地方还望点评. 内存泄漏(Out Of Memory)俗称OOM,翻了网上一些资料,发生OOM的情况大致有两种,一种是Activity当中 ...

  6. oom 如何避免 高并发_糖尿病并发症真的会致死?又该如何避免它发生?

    目前我国糖尿病患病人数已经达到了1.09亿人,居世界首位,也就是说十个成年人里面就有一个是糖尿病患者.然而糖尿病可怕,糖尿病并发症更可怕.甚至有很多糖尿病患者都死于糖尿病并发症. 苏杏璇,著名的香港演 ...

  7. 1号店11.11:从应用架构落地点谈高可用高并发高性能--转载

    原文地址:http://www.infoq.com/cn/articles/yhd-11-11-high-availability-and-high-performance 1. 背景 1.1 三高是 ...

  8. python访问数据库如何解决高并发_怎样解决数据库高并发的问题

    怎样解决数据库高并发的问题?解决数据库高并发使用缓存式的Web应用程序架构.增加Redis缓存数据库.增加数据库索引.页面静态化.使用存储过程.MySQL主从读写分离.分表分库.负载均衡集群. 解决数 ...

  9. jvm高并发_在JVM上对高并发HTTP服务器进行基准测试

    jvm高并发 在第一篇关于HTTP客户端的文章 (我将您重定向到JVM上的高效HTTP的介绍)之后,现在让我们来谈谈HTTP 服务器 . 有一些关于HTTP服务器的基准测试,但通常受到诸如以下缺点的阻 ...

最新文章

  1. for死循环、怪异字符串、两次return……Python冷知识(三)
  2. 频频曝出程序员被抓,我们该如何避免面向监狱编程?
  3. 中国移动OnetNet云平台 使用以太网传输数据流步骤
  4. HTML5 实现手机拍照上传
  5. 022_Table表格
  6. java代码没错却运行不了_Java代码没错误,tomcat能正常运行,但是我的项目主页却一直显示不了,显示404错误...
  7. permgen_什么是PermGen泄漏?
  8. (教程)2020最新windows10/anaconda/pytorch-gpu环境配置(附CUDA/cuDNN配置)
  9. orchard mysql_Orchard Core创建CMS/Blog站点
  10. 【更新】Navicat Monitor v1.7的新功能说明
  11. 电阻电容串联、并联起来用在电路中,起什么作用?
  12. 中兴智能视觉大数据报道:张学友,你一定要多开演唱会啊!
  13. 如何内置AdobeFlashPlayer.apk
  14. Matplotlib进阶教程:布局讲解
  15. 【C#】Whisper 离线语音识别(微软晓晓语音合成的音频)(带时间戳、srt字幕)...
  16. XMind 常用快捷键(思维导图总结)
  17. OA系统是把无所不能的“万能钥匙”?
  18. IDEA相同变量高亮显示
  19. Processing 网格纹理制作(棋盘格)
  20. 机器学习服务活体检测算法荣获CFCA权威安全认证

热门文章

  1. 如何使用ggplot2绘制左右分布的柱状图
  2. mysql多个字符串连接池_使用Coroutine\Channel实现一个简单的MySQL连接池
  3. 科研文献|中国的肠道微生物群及其与主食类型、民族和城市化的关系
  4. Cell子刊:微生物组学研究的突破与瓶颈
  5. WR:城环所杨军组揭示亚热带水库浮游有壳虫群落构建受随机性过程影响比确定性过程更强...
  6. 中国肠道大会 | 日程及嘉宾(4月16日更新)
  7. 新年开工——相关性分析了解一下?
  8. Microbiome:宏蛋白质组揭示健康人肠道菌群的功能,离真相更近了一步
  9. pandas使用extract函数根据正则表达式从dataframe指定数据列的字符串中抽取出数字并生成新的数据列(extract numbers from column)
  10. python使用matplotlib可视化使用subplots子图、subplots绘制子图并为可视化的子图添加主标题(subplots main title)