首页 > 数据库 >解锁数据库运维秘籍:掌握AntDB-T动态共享内存,提升进程间通信效率

解锁数据库运维秘籍:掌握AntDB-T动态共享内存,提升进程间通信效率

时间:2023-11-21 11:05:26浏览次数:29  
标签:control AntDB 动态 运维 间通信 dsm 进程 共享内存

动态共享内存是AntDB数据库通信的重要手段,本文主要阐述AntDB-T数据库动态共享内存的实现原理、实现方式与使用方法。

AntDB-T数据库是一款企业级通用分布式关系型数据库,其数据库内核是基于进程模型实现的,因此进程间通信(IPC)是实现分布式架构间进行任务协作和数据共享的关键。 实现进程间通信的方式有多种,例如管道、消息队列、信号量、共享内存等。在程序运行过程中,AntDB-T数据库为了实现进程之间更高效的通信和数据传输,采用了共享内存的方式。例如,AntDB-T数据库在并发任务需要创建多个工作进程的情况下,工作进程与后端进程之间的通信和数据传输将通过动态创建的共享内存来实现。
::: hljs-center

(一)AntDB-T动态共享内存实现原理

:::

那接下来本部分内容就为各位小伙伴慢慢解析AntDB-T数据库动态共享内存的原理。 AntDB-T动态共享内存是什么
动态共享内存(dynamic shared memory):简称 DSM,在数据库运行期间可以动态创建出来的共享内存,动态共享内存允许AntDB-T在运行时动态地分配和释放内存,从而提高系统的性能和可伸缩性。

AntDB-T中动态共享内存实现方式

在AntDB-T中动态共享内存的实现方式有多种,由dynamic_shared_memory_type参数控制,默认是posix是指使用shm_open分配的POSIX shared memory。

640.png ::: hljs-center

图1:dynamic_shared_memory_type 配置参数

:::

dynamic_shared_memory_type参数定义如下表: 屏幕截图 2023-11-21 100921.jpg

启用动态内存共享之后,当AntDB-T数据库启动后会在/dev/shm目录下有所体现,关了AntDB-T数据库之后,这些文件就没有了:

640 (1).png ::: hljs-center

图2:AntDB-T数据库启动后/dev/shm目录情况

640 (2).png 图3:AntDB-T数据库关闭后/dev/shm目录情况 ::: hljs-left

AntDB-T为什么要引入动态共享内存

:::

动态共享内存可以在运行时动态地分配和释放内存,从而使得内存管理更加灵活和高效,并且动态共享内存还可以实现延迟初始化(lazy initialization)和重新配置(reconfiguration)等特性,从而提高了系统的性能和可伸缩性。

在实际AntDB-T数据库中,动态共享内存在很多地方会用到,举个例子比如动态共享内存在并行中会用到,因为对于并行查询而言,执行时创建的DN worker进程与 DN leader进程通过共享内存实现数据交互。但这部分内存无法像普通的共享内存那样在系统启动时预先分配,毕竟直到真正执行时才知道有多少 DN worker进程,以及需要分配多少内存。动态共享内存,即在执行时动态创建,用于 DN leader与 DN worker间通信,执行完成后释放。

::: hljs-center

(二)AntDB-T动态共享内存实现方式

:::

:::

下面将针对动态共享内存机制进行源码说明。本次以AntDB-T的代码为例,来解析动态共享内存的实现方式。

在AntDB-T源码中,dsm.c、dsm_impl.c文件提供了动态共享内存的功能,实现了共享内存的动态申请和释放。动态共享内存通过一个handle(typedef uint32 dsm_handle;)与一块内存进行映射,这个handle是一个32位无符号整数。在创建动态共享内存时,需要指定一个handle作为标识符,而访问动态共享内存时也是通过这个handle进行访问。不同进程之间通过传递handle来告知对方动态共享内存的位置,其他进程则通过handle来访问该动态共享内存。
1.基础数据结构

dsm_control_header和dsm_control_item是动态共享内存里最基础的2个数据结构。定义如下图所示:

640 (3).png ::: hljs-center

图4:dsm_control_header和dsm_control_item数据结构

:::

dsm_control_header是动态共享内存的控制结构头,dsm_control_item记录每个分配的动态共享内存的状态,字段nitems表示动态共享内存当前已经使用的数量,字段maxitems表示动态共享内存的最大数量,字段refcnt表示 /* 2+ = active, 1 = moribund, 0 = gone */,字段impl_private_pm_handle表示仅在Windows上需要,字段pinned表示是否固定动态共享内存段,dsm_handle表示动态共享内存段的名字。 dsm_segment表示申请的一个共享内存段,对于动态共享内存的api来说这是代表共享内存的最小单位,定义如下图所示: 640 (4).png ::: hljs-center

图5:dsm_segment数据结构

:::

每个后端进程都可以通过使用dsm_segment来访问共享内存,dsm_segment包含了内存分配和释放等操作所需的信息,并提供了一组函数来管理和操作共享内存,每个会话(session)可以有一个或多个dsm_segment。其中字段mapped_address代表需要返回的当前映射共享内存的起始地址,字段resowner表示该动态共享内存段资源所有者,control_slot表示在控制动态共享内存段(dsm_control_header)里面的第几个item。
2.初始化AntDB-T动态共享内存(DSM)

在 postmaster 主进程启动时,调用dsm_postmaster_startup(PGShmemHeader *shim)函数,进行动态共享内存相关的初始化,其主要逻辑如下:

1)计算 dsm_control 结构所需要的内存大小: 1>计算所需共享内存的最大数量maxitems, maxitems=PG_DYNSHMEM_FIXED_SLOTS+ PG_DYNSHMEM_SLOTS_PER_BACKEND * MaxBackends = 64+5* MaxBackends 其中:PG_DYNSHMEM_FIXED_SLOTS为64,PG_DYNSHMEM_SLOTS_PER_BACKEND为5 该值(maxitems)与 MaxBackends大小有关,MaxBackends为最大的backend进程的数量,和配置的最大连接数(max_connections)、autovacuum worker进程的最大个数(autovacuum_max_workers)、并发进程的最大数量(max_worker_processes)、wal sender process的最大数量有关。 2>根据maxitems计算dsm_control 结构所需要的内存大小segsize, segsize = dsm_control_bytes_needed(maxitems); 其中函数dsm_control_bytes_needed定义:
static uint64 dsm_control_bytes_needed(uint32 nitems) { return offsetof(dsm_control_header, item) + sizeof(dsm_control_item) * (uint64) nitems; } 2)调用 dsm_impl_op() 函数,该函数根据dynamic_shared_memory_type参数调用不同的接口创建用于dsm_control 结构的动态共享内存,地址赋值给 dsm_control 变量,该变量的类型为 dsm_control_header 。 3)初始化 magic、nitems、maxitems变量,其中maxitems 表示AntDB-T该DN节点所有进程能够申请的动态共享内存的最大数量,nitems 表示当前已使用的动态共享内存数量,每一次动态共享内存申请,对应一个 dsm_control_item。 其函数大致调用关系如下: main(int argc, char *argv[]) PostmasterMain(int argc, char *argv[]) reset_shared(void) CreateSharedMemoryAndSemaphores(void) dsm_postmaster_startup(PGShmemHeader *shim)

3. 清理AntDB-T动态共享内存(DSM) 在 postmaster 主进程关闭时,会调用 dsm_postmaster_shutdown() 函数进行 dsm 的清理,这个函数是在初始化动态共享内存(dsm_postmaster_startup())时就指定了on_shmem_exit(dsm_postmaster_shutdown, PointerGetDatum(shim));

清理动态共享内存的主要逻辑:首先检查动态共享内存段是否已经损坏,如果损坏了就记录错误日志直接返回,如果没有损害时就遍历 dsm_control->nitems 数组,对其中正在使用的 item 对应的动态共享内存(DSM)进行销毁 ,最后再销毁 dsm_control 自身对应的 动态共享内存(DSM) 内存 。

::: hljs-center

(三)AntDB-T动态共享内存实践分享

:::

使用动态共享内存之前,需要先对其进行创建。AntDB-T启动时已经初始化好了动态共享内存,后面使用的时候只需要创建动态共享内存,挂载动态共享内存,解除挂载动态共享内存,销毁共享内存。AntDB-T数据库使用动态共享内存的地方有很多,下面举个最简单的并行查询的例子来解说下如何使用动态共享内存,举例的表字段和并行查询的执行计划如下图所示:

640 (5).png ::: hljs-center

图6:AntDB-T 并行查询的例子

:::

可以从上图的执行计划里面明确看到有使用到了并行查询,并且并行的worker个数是2。先进行简单的并行查询的原理介绍,图如下所示:DN backend主进程拉起从进程,DN backend主进程在处理时,发现需要进行并行处理,就会在启动从进程时,会调用 LaunchParallelWorkers 函数,这个函数会调用RegisterDynamicBackgroundWorker ,此时会给 Postmaster 进程发一个信号,请求 Postmaster 进程启动一个 background 进程,Postmaster 进程收到信号后就会启动一个新后台进程来处理查询。 640 (6).png ::: hljs-center

图7:AntDB-T 并行查询的流程

:::

在 AntDB-T 的源码中,上述SQL例子在并行查询中使用动态共享内存(DSM),其主要逻辑如下: 1.DN backend主进程在判断需要进行并行处理时,就会初始化并行执行计划ExecInitParallelPlan,在ExecInitParallelPlan函数中,会评估共享内存大小:通过使用shm_toc_estimate_chunk、shm_toc_estimate_keys宏定义向estimate中增加数据结构,可以多次调用,然后使用shm_toc_estimate得出需要创建的动态共享内存的总大小,最后调用 dsm_create()函数 创建动态共享内存(DSM)。创建并行的工作进程时,将动态共享内存(DSM)对应的 handle 作为参数传递给 并行的worker 进程,其调用关系如下: ExecGather(PlanState *pstate) ExecInitParallelPlan(PlanState *planstate, EState *estate, Bitmapset *sendParams, int nworkers, int64 tuples_needed) InitializeParallelDSM(ParallelContext *pcxt) dsm_create(Size size, int flags) LaunchParallelWorkers(ParallelContext *pcxt) worker.bgw_main_arg = UInt32GetDatum(dsm_segment_handle(pcxt->seg));

2.并行的子进程(DN worker 进程)先调用 dsm_attach() 函数挂载到动态共享内存,然后调用函数ParallelQueryMain处理查询业务该函数里面使用了动态共享内存,当并行的子进程执行结束时,会调用 dsm_detach() 函数解除挂载的 dsm 共享内存,其大致的调用关系如下:

ParallelWorkerMain(Datum main_arg) seg = dsm_attach(DatumGetUInt32(main_arg)); ParallelQueryMain(dsm_segment *seg, shm_toc *toc) area = dsa_attach_in_place(area_space, seg); dsa_detach(area) dsm_detach(area->segment_maps[i].segment);

::: hljs-center

总结

:::

本文主要讲述了AntDB-T动态共享内存的基本概念、引入动态共享内存带来的能力提升、基本数据结构、动态共享内存机制原理和使用方法。限于篇幅,动态共享内存的其他函数接口比如:dsm_pin_mapping、dsm_unpin_mapping、dsm_pin_segment、其他使用动态共享内存的场景、动态共享内存中涉及的锁等相关内容没有涉及,小伙伴们请持续关注AntDB数据库公众号。

关于AntDB数据库 AntDB数据库始于2008年,在运营商的核心系统上,为全国24个省份的10亿多用户提供在线服务,具备高性能、弹性扩展、高可靠等产品特性,峰值每秒可处理百万笔电信核心交易,保障系统持续稳定运行近十年,并在通信、金融、交通、能源、物联网等行业成功商用落地。

标签:control,AntDB,动态,运维,间通信,dsm,进程,共享内存
From: https://blog.51cto.com/u_15348398/8497712

相关文章

  • Linux - 内存间通信
    进程间通信 Linux下进程通信的方式有管道:管道用于有亲缘关系的进程间通信有名管道:除了管道特性外还能在独立进程间进行通信信号:用于通知进程有某种事件发生消息队列:用于进程间较多数据的通信,有读写权限的进程可以向队列中添加消息。只有读权限则只能读取队列中消......
  • 自助终端联网监控高效运维解决方案
    随着科学技术的发展与生活水平的不断提高,各行各业都在积极探索如何利用智能化技术提升工作效率。自助终端作为现代生活随处可见的智能设备,可以为用户提供各种轻松便捷的自助式操作体验,能够有效帮助服务商减轻运营成本,提高工作效率等,在医院、银行、地铁等场景应用广泛。 由于厂家销......
  • 【开源】基于Vue.js的天然气工程运维系统的设计和实现
    一、摘要1.1项目介绍基于Vue+SpringBoot+MySQL的天然气工程运维系统,包含工程项目模块、材料档案模块、材料领用单模块,还包含系统自带的用户管理、部门管理、角色管理、菜单管理、日志管理、数据字典管理、文件管理、图表展示等基础模块,天然气工程运维系统基于角色的访问控制,给工程......
  • shell运维脚本优化
    我们在平常工作中,你是否感觉shell脚本只是命令的堆砌;很多时候只是为了实现功能而没有好的组织结构;自己的脚本都不想再看一遍;此让你的shell脚本有python一样的美感并且极易维护,真的是shell脚本写到停不下来。现以k8s发版脚本为例,看一下脚本的优化过程:#!/bin/bashset-euns=$......
  • 进程间通信的方式之消息队列和共享内存
    消息队列消息队列就是保存在内核中的消息链表,包括Posix消息队列和SystemV消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。共享内存共享内存的机制,......
  • 同网段及跨网段主机间通信原理
    在以太网络通信中,在 IP 数据包中有两个必不可少的地址,那就是 IP 地址和网卡地址(即 MAC 地址),在数据包中,无论是 IP 地址还是 MAC 地址,都有源地址和目标地址,因为通信是双方的,所以就必须同时拥有双方的地址!在同一 IP 网络中通信,将会发生以下事件:1、同网段主机间通信主机......
  • 混合云运维解决方案,支持公有云、私有云、信创云等环境
        数字时代,政企业务上云已成为大势所趋。虽然上云可为政企用户带来业务应用部署调度更加灵活、资源利用率更高的优点,但因云平台建设处于不同的阶段,且运转过程中包含大量的、不同类型的业务系统和应用场景,在整体云平台的建设中往往会产生如公有云、私有云、信创云、非信......
  • BMS系统如何实现远程监控与高效运维
    BMS系统(电池管理系统)是用来智能化管理各个电池单元,监控电池的状态的系统,通过对电压、电流、温度等参数采集、计算,进而控制电池的充放电过程,能够实现对电池的保护、提升电池的综合性能。 为实现BMS系统的安全稳定工作,就需要加强BMS系统的远程监控运维能力。对此数之能提供高效实用......
  • KubeSphere开源容器自动化运维平台实现远程访问操作,解决本地限制
    KubeSphere是一个基于Kubernetes的开源容器平台,它提供了全栈的IT自动化运维能力,简化了企业的DevOps工作流。KubeSphere采用前后端分离的架构,可以运行在任何Kubernetes、私有云、公有云、VM或物理环境之上。KubeSphere提供了运维友好的向导式操作界面,帮助企业快速构建一个强大和功......
  • Linux进程间通信模式
    管道是一种单向传输数据的机制,它其实是一段缓存,里面的数据只能从一端写入,从另一端读出。如果想互相通信,我们需要创建两个管道才行。管道分为两种类型,“|”表示的管道称为匿名管道,意思就是这个类型的管道没有名字,用完了就销毁了。就像上面那个命令里面的一样,竖线代表的管道随着命令......