写点什么

OpenGauss 与 NVM

作者:daydayup
  • 2023-08-09
    北京
  • 本文字数:1554 字

    阅读完需:约 5 分钟

OpenGauss 与 NVM

[openGauss](javascript:void(0);) 2023-08-07 18:00 发表于中国香港


以下文章来源于 yanzongshuaiDBA ,作者 yzshover



yanzongshuaiDBA.


专注于 MySQL、PostgreSQL 等开源数据库


OpenGauss 与 NVM


NVM(非易失性内存),也叫 PM(持久内存)具有可字节寻址、大容量、非易失型和堪比 DRAM 的速度等特性。随着英特尔傲腾产品的出世,现有数据库适配这种新型硬件显得更加有必要。


OpenGauss 在这方面也做了探索,实现了 DRAM-PM-DISK 三层存储架构。当然,实现方式参考了 2018 年 SIGMOD 会议的一篇论文《Managing Non-Volatile Memory in Database Systems》,感兴趣可以查看。我们这里介绍下 OpenGauss 中的 DRAM-PM-DISK 三层存储架构。

1、当前存储架构问题

当前 opengauss 的架构是 DRAM-DISK,也就是面向磁盘的数据库。当数据量大于 shared_buffers 时,共享内存的数据页淘汰流程就会称为瓶颈。甚至于导致共享内存淘汰数据页处的逻辑占用 CPU 较高,进而影响 pagewriter 线程刷写,让淘汰更慢,影响正常工作。


引入持久内存 PM,形成 buffer pool 的三层 DRAM-PM-DISK 架构的设计,利用成本相对较低的 PM 对 shared_buffers 进行扩容,可减少淘汰流程的触发。并且,还通过数据页的访问频率来控制各个缓存层之间的页面迁移,实现热数据在 DRAM,温数据在 PM,冷数据在 DISK。

2、OpenGauss 启用 PM 的相关配置项

1)enable_nvm:启用 nvm buffer 管理。默认是 false


2)nvm_buffers:设置 nvm buffer 大小,即 BLCKSZ 的个数


3)nvm_file_path:指定 NVM 的路径,因为 NVM 以-o dax 方式挂载(跳过操作系统缓存)后,需要将其 map 到内存。


4)bypass_dram:控制 by pass 内存的概率


5)bypass_nvm:控制 by nvm 的概率

3、OpenGauss 的 DRAM-PM-DISK 架构实现机制


整体架构如上图所示,shared buffer pool 由两部分组成:DRAM buffer pool 和 NVM buffer pool,统一由 buffer 管理器进行管理。用户后台线程可以访问 DRAM 也可以访问 NVM。NVM 中的页根据访问热度会迁移到 DRAM。

3.1 buffer pool


Buffer pool 中的 block 分为 3 部分:DRAM 部分、NVM 部分和 SEG buffer blocks。这里我们只关注 DRAM 和 NVM。


(1)buffer pool 的初始化



在共享内存中申请 BufferBlocks,若开启 nvm,则通过 nvm_init 来初始化 NVM 的 BufferBlocks。NVM 通过 mmap 操作将 NVM 设备映射到内存。映射大小由 nvm_buffers 配置项控制:



    #define TOTAL_BUFFER_NUM (SEGMENT_BUFFER_NUM + NORMAL_SHARED_BUFFER_NUM + NVM_BUFFER_NUM)#define NVM_BUFFER_NUM (g_instance.attr.attr_storage.NNvmBuffers):对应nvm_buffers
    复制代码


    这里为什么不适应 pmdk 呢?pmdk 在用户态管理 NVM 可以减少内存上下文的切换,比 mmap 更具有优势。


    (2)BufferAlloc 的申请



    1)ReadBuffer_common 完成数据页的读取。通过 BufferAlloc 来判断是否在内存中命中需要的页,若命中则返回该内存块的描述符。未命中的话,就需要调用 ReadBuffer_common_ReadBlock 将磁盘上的页通过 smgrread 加载到内存。当然这里是加载到 DRAM 还是 NVM,则由 buf 描述符来指定。需要观察 BufferAlloc 函数实现机制


    2)BufferAlloc 函数:开启 NVM 时,通过 NvmBufferAlloc 函数获取 buf 描述符


    3)NvmBufferAlloc 机制:


    (1)因为 NVM 和 DRAM 都是内存,由 t_thrd.storage_cxt.SharedBufHash 哈希表统一管理,所以首先从这个 hash 表中查询需要的页,看下是否在内存


    (2)若在 hash 表中没找到则表示没在内存中命中,则根据是否 bypassnvm 来决定使用哪块的 buf 描述符:bypassnvm:使用 DRAM 块的 buf 描述符;否则使用 NVM 处的描述符。


    (3)若在 hash 表中找到,则表示内存中命中。进一步判断:Buf id 位于[0,NvmBufferStartID)是 DRAM 的块,位于[NvmBufferStartID,SegmentBufferStartID)的是 NVM 的块。


    (4)命中 DRAM 的块,直接使用


    (5)命中 NVM 的块,bypassdram,直接使用


    (6)命中 NVM 的块,非 bypassdram,则需要将 NVM 的块拷贝到 DRAM。这里同样使用 memcpy,使用 pmdk 的函数效果更好。

    用户头像

    daydayup

    关注

    还未添加个人签名 2023-07-18 加入

    还未添加个人简介

    评论

    发布
    暂无评论
    OpenGauss与NVM_daydayup_InfoQ写作社区