GaussDB(DWS)CBB组件之SysCache、RelCache、PartCache内存管控介绍

网友投稿 709 2022-05-29

在之前的文章中,详细介绍了Cache的工作原理:当用户连续执行SQL时,DWS内核会将该SQL所需要用到的元数据加载到SysCache、RelCache和PartCache中,以牺牲内存空间为代价,减少磁盘操作,提高查询性能。然而DWS内存空间并非无穷大,为保证数据库的高可用性,需要在内存空间紧张时主动清理Cache缓存,以有效释放内存占用。因此,这里产生了一个tradeoff:

何时失效Cache?

失效哪些Cache?

在本文中,我们将围绕这两个问题进行分析,介绍DWS是如何实现Cache内存管控的。

原始的内存降低手段--全失效

图1 Cache主动全失效流程图

如图所示,为Cache全失效流程图,每个CN线程和DN线程在接收到新请求或事务开始时,将做一次Cache占用判断,如果Cache占用超过256MB,则执行一次全失效,清空Cache。

该方法简单粗暴,能有效降低内存占用,凡是内存超过256MB的线程都会得到清理,但有以下几个问题:

该清理只在接收到新请求时才开始生效,若线程执行SQL过程较长,或SQL执行完毕以后,没有后续SQL执行,内存占用有可能无法得到及时释放。一旦该线程占用的内存资源无法释放,可能导致其他线程发生OOM错误。

在这里,结合一个现场例子进行理解:

在局点XXX的环境中,用户现场有个超大分区表,在用户业务脚本执行分区表查询操作后,单个线程的内存占用从0增长至200+MB,根据当时环境部署,一个节点包括一个CN进程和4个DN进程,也就是说共5个进程,每个进程都有200MB的内存无法及时回收,导致其他线程报OOM错误。

分析该问题的原因,共有两点:

其一是,在线程执行SQL过程中,内存需要进行及时释放,不要等到线程结束才统一释放;其二是,线程执行SQL结束以后,重新回归线程池,根据图一中Cache内存释放原理,此时回归线程池以后,内存并没有释放,需要等到该线程开始执行其他SQL时,才能进行内存释放。

GaussDB(DWS)CBB组件之SysCache、RelCache、PartCache内存管控介绍

Cache全失效对性能有一定影响,有可能失效掉访问频繁的Cache,降低性能。

在该方案中,内存失效方式比较暴力,不管Cache的访问频率,直接失效掉所有cache,然而这是不合理的,会影响性能。

比如,对于pg_class中pg_attribute记录,该记录必然会频繁访问,失效掉该记录是不合理的,因为下一条SQL必然会加载该Cache。

为解决以上问题,我们在迭代过程中,逐渐实现了以下几个Cache内存管控机制。

定时内存降低手段--idle线程内存回收

为解决a)中的问题,我们设计了idle线程内存回收机制,其主要工作原理如下:

图2 内存清理信号发送流程图

图中左侧和右侧为两个线程,其中左侧线程在执行SQL过程中,在线程palloc内存过程中如果发生OOM错误,则该线程开始扫描其他线程的内存占用,对于内存占用超过64MB的线程,将发送内存清理信号,在其他线程(右侧线程)接收到信号以后,若该线程处于空闲状态,则执行内存清理。该方式有效解决了a)中线程结束后,无法清理的问题。

这里有几个关键点:

在该内存释放机制中,为避免信号发送过于频繁,会在发送信号前将进行检测,60s内最多发送一次信号,防止信号爆炸。

发送内存清理信号时机需要优化:其实该回收机制的主要目的是,在内存紧张时,主动通知(唤醒)其他idle线程执行内存清理,然而若等到palloc失败才开始通知,可能此时已经严重阻塞业务执行,应该更早通知其他线程进行缓存清理。

待实现的内存降低手段--LRU / Global Cache

这两种内存管控手段暂时还未实现,但作为内存管控方式之一,我们也可以单独拿出来分析一下。

LRU:该内存管控主要目的是末尾淘汰不常用的缓存,对于SysCache,其本质上就是一个队列;对于RelCache和PartCache,其实现逻辑是哈希表,通过对象的Oid进行哈希。综合考虑SysCache、RelCache和PartCache,可以发现,LRU内存管控是可能的,但实现LRU的前提是:1)如何评价Cache使用率;2)LRU性能影响分析。

Global Cache:DWS当前Cache为ThreadLocal类型,也就是说,每个线程维护自身Cache,然而在用户SQL任务并发较高的情况下,Cache会在线程间重复存储,占用额外的内存。因此,Global Cache的想法应运而生,该想法的主要目标是,取消掉Cache线程间的存储,所有Cache都通过指针,指向GlobalCache,以降低内存。然而,经过调查发现,Global Cache实现起来相对比较麻烦,其主要原因是,加锁频繁,在DDL频繁的情况下,严重影响性能。

至此,DWS内核Cache内存管控手段已经介绍完毕,如果小伙伴还有其他内存降低想法,欢迎留言讨论!

Gauss AP SQL 数据仓库服务 GaussDB(DWS) 运维

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:编程基本功训练:流程图画法及练习
下一篇:4┃音视频直播系统之浏览器中通过 WebRTC 进行桌面共享
相关文章