首页 > 其他分享 >GaussDB(DWS)集群通信:详解pooler连接池

GaussDB(DWS)集群通信:详解pooler连接池

时间:2024-03-11 10:12:19浏览次数:31  
标签:DWS postgres GaussDB 线程 pooler 连接 连接池 CN

本文分享自华为云社区《GaussDB(DWS) 集群通信系列一:pooler连接池》,作者:半岛里有个小铁盒。

1.前言

适用版本:【8.1.0(及以上)】

GaussDB(DWS) 为MPP型分布式数据库,使用Share Nothing架构,数据分散存储在各个DN节点,而CN不存储数据,作为接收查询的入口,生成的计划会尽量下推到DN并行执行以提升性能,此过程中会产生大量的建连操作,使得通信开销变得很大。因此在大数据时代,集群规模越来越大,业务并发越来越高,数据库集群各节点间的通信压力也越来越大。GaussDB(DWS)集群通信技术,在大规模集群中可以承载高并发业务,能够实现高性能分布式通信系统。

2.背景

GaussDB(DWS) 中客户端执行查询流程如上图所示,其中具体的如下:

  1. 客户端向CN的监听端口发起连接;
  2. CN postmaster主线程accept连接,创建 postgres线程并将连接交给此线程处理;
  3. 客户端下发query到CN;
  4. CN的postgres线程将查询计划下发给其他 CN/DN,查询结果沿原路径返回到客户端;
  5. 客户端查询结束,关闭连接;
  6. CN上对应的postgres线程销毁退出;

CN与DN建连立流程,和客户端与CN建连立流 程基本相同。因此为了减少CN与DN建立连接,以及DN进程中postgres线程创建、销毁的开销,CN端实现了Pooler连接池。

3.Pooler连接池

img

如上图所示,CN的pooler连接池中会保存与其他CN/DN的连接,每一个连接在对端会对应一个postgres工作线程。

postgres工作线程是带状态属性的,如database,所以可以认为pooler连接池中的连接也是带属性的。不同属性间的连接是不能复用的,如上图所示,按不同属性切分为pool A/B/C等连接池。每个连接池中会存有连接往不同节点的空闲连接的数组,提供接口给外部使用或放入连接。

CN上的postgres工作线程在需要连接其他节点时,会创建一个本地agent,尝试从pooler连接池取跟本线程相同属性的空闲连接,pooler如果没有空闲连接,就会新建一个连接。连接交给agent后,可以视为线程私有。在线程退出时,agent才会将连接还给pooler。

接下来,我们从数据结构上来看看Pooler连接池实现原理:

空闲连接池

DatabasePool

/* All pools for specified database */
typedef struct databasepool
{
    char    *database;
    char    *user_name;
    char    *pgoptions; /* Connection options */
    HTAB    *nodePools; /* Hashtable of PGXCNodePool, one entry for each node */
    MemoryContext mcxt;
    struct databasepool *next; /* Reference to next to organize linked list */
} DatabasePool;

DatabasePool *databasePools = NULL;

进程级别数据结构

DatabasePool用于存储空闲连接,根据database,user_name,pgoptions三者来确定
如果通过三者查找到了,那么就取其中对应的nodePools,找不到则新加

nodePools中对应的数据结构为PGXCNodePool,用于存储本节点与其他每个cn/dn的连接,具体的保存如下

cn1[0,1,2,3,4,…]

dn1[0,1,2,3,4,…]

NodePool

typedef struct NodePool
{
    Oid nodeoid; /* Hash key (must be first!) */
    bool valid;
    ArrayLockFreeQueue pool;
} PGXCNodePool;

进程级别数据结构

连接到某一节点的空闲连接的集合,通过无锁队列(数组)实现
从这里拿到对应的连接,直接复用

正在使用连接池

AgentPool

typedef struct
{
    ArrayLockFreeQueue pool;
    AgentSlot* slots;
}AgentPool;

进程级别的数据结构

存放一个进程中的所有的连接

其中slots为一个数组,表明一个槽位,与pool为一一对应的状态
用于保存所有线程持有的连接,即poolAgent数据结构

AgentSlot

typedef struct
{
    int index;
    volatile AgentStatus status;
    PoolAgent* agent;
}AgentSlot;

进程级别数据结构

存放进程中的某一个连接

index与AgentPool->pool相关联

status状态为,标识该连接是否正在使用/空闲/持有

agent中为某个线程的信息(也就是每个session),都是在全局数组poolAgents中保存的

PoolAgent

typedef struct
{
    /* Agent members */
    ThreadId        pid;
    DatabasePool*   pool;
    int             index;

    /* param members */ 
    char*           user_name;
    char*           pgoptions;
    char*           paramsStr;
    char*           localParams;   /* params temporarily saved before commit */
    char*           tempNamespace; /* temp namespace name of session */
    List*           paramsList;    /* save session params, for build paramsStr */
    int             paramsReady;    /* param is set, need rebuild paramsStr */

    /* Connection members */
    int             dnNum;
    int             cnNum;
    PoolSlot**      dnConn;
    PoolSlot**      cnConn;
    NodeConnDef*    cnDef;
    NodeConnDef*    dnDef;

    /* handles members */
    NodeHandle** dnHandles;
    NodeHandle** cnHandles;
    int dnUsed;
    int cnUsed;
} PoolAgent;

对于每起一个线程session(即连接),都会有一个PoolAgent与之对应,即从DatabasePool->NodePool->pool取出来的连接

  • cnDef、dnDef:初始化时从pgxc_node中拿到,即cn定义、端口、ip
  • (session级别)dnConn、cnConn:从databasePools->nodePools-> pool拿真正对应的连接
  • (query级别)dnHandles、cnHandles:从dnConn、cnConn里边dop出来使用,确保两者是一一对应的状态,当query结束时,只需要close handles就行,cnConn不需要close

Pooler连接池具体的复用流程如下:

  1. session需要连接时,通过DB+USER为key找到正确的pooler连接池,优先从中取走现有连接,如果连接池中没有连接的话,则新建连接;
  2. query结束后,CN的postgres线程并不会归还连接,连接可以用于当前session的下一个查询;
  3. session结束后,CN的postgres线程会将连接还到对应的pooler,连接对应的DN上的postgres线程并不会退出,处于ReadCommand中,等待复用后CN新的postgres线程发起任务;

4.Pooler连接池相关的视图

pg_pooler_status视图

pg_pooler_status视图记录了pooler连接池中的所有连接信息,每一行表示本CN发起的一个连接,对应对端进程的一个postgres线程

postgres=# select * from pg_pooler_status;
 database | user_name | tid |  node_oid  |  node_name   | in_use | node_port | fdsock |   remote_pid    | session_params
----------+-----------+-----+------------+--------------+--------+-----------+--------+-----------------+----------------
 postgres |   user1   |     | 2147483650 | datanode1    | f      |     37110 |     94 | 140259241618584 | none
 postgres |   user1   |     | 2147483650 | datanode1    | f      |     37110 |    101 | 140259241619432 | none
 postgres |   user1   |     | 2147483650 | datanode1    | f      |     37110 |     91 | 140259241618160 | none
 postgres |   user1   |     | 2147483650 | datanode1    | f      |     37110 |     95 | 140259241619008 | none
 postgres |   user1   |     | 2147483650 | datanode1    | f      |     37110 |     59 | 140259241562192 | none
 postgres |   user1   |     | 2147483650 | datanode1    | f      |     37110 |    106 | 140259241619856 | none
 postgres |   user1   |     | 2147483650 | datanode1    | f      |     37110 |    108 | 140259241620280 | none
 postgres |   user1   |     | 2147483650 | datanode1    | f      |     37110 |    117 | 140259241621128 | none
 postgres |   user1   |     | 2147483650 | datanode1    | f      |     37110 |    114 | 140259241620704 | none
  • in_use为‘t’表示这个连接正在某线程使用,为‘f’表示空闲连接等待复用
  • tid列为本CN的持有此连接的线程号
  • node_name列为对端进程号,remote_pid列为对端线线程号
  • 在query_id为0或CN/DN不一致时,通过pooler视图查找CN与DN连接关系

一般pooler连接池中的连接会非常多,可以按不同字段group by查看某个db pool池中的连接情况,或连往某个node的连接情况,如:

select database,user_name,node_name,in_use,count(*) from pg_pooler_status group by 1, 2, 3 ,4 order by 5 desc limit 50;

5.Pooler连接清理

清理Session持有的连接

  • cache_connection,是否使用pooler连接池缓存连接,默认开
  • session_timeout,客户端连接空闲超时后报错退出归还连接
  • enable_force_reuse_connections,事务结束后强制归还连接
  • conn_recycle_timeout(8.2.1),CN空闲session超时后归还连接

Pooler空闲连接池中的连接

  • pg_clean_free_conn视图/函数,清理1/4的空闲连接池连接,CM定期调用
  • CLEAN CONNECTION语法,清理对应DB或user的所有空闲连接 clean connection to all for database postgres to USER user1;

6.总结

本文详细介绍了Libcomm通信库及其原理,让我们更好的理解GaussDB(DWS)集群通信中的具体逻辑,对于GaussDB通信运维也具备一定的参考意义。

 

点击关注,第一时间了解华为云新鲜技术~

 

标签:DWS,postgres,GaussDB,线程,pooler,连接,连接池,CN
From: https://www.cnblogs.com/huaweiyun/p/18065439

相关文章

  • 手把手带你认识GaussDB轻量化运维管理工具
    本文分享自华为云社区《GaussDB轻量化运维管理工具介绍》,作者:Gauss松鼠会小助手。一、GaussDB运维管理平台简介开放生态层友好Web界面,多云皮肤个性化定制丰富的原子API公有云、合运营、HCSO、边缘云IES、HCS、轻量化、统一版本基础+智能运维能力丰富的基础运维能力......
  • GaussDB跨云容灾:实现跨地域的数据库高可用能力
    本文分享自华为云社区《GaussDB跨云容灾:实现跨地域的数据库高可用能力》,作者:GaussDB数据库。金融、银行业等对数据的安全有着较高的要求,同城容灾建设方案,在绝大多数场景下可以保证业务数据的安全性,但是在极端情况下,如遇不可抗力因素等,要保证数据的安全性,就需要采取跨地域的容灾......
  • 当打印服务(Print Spooler)自动关闭
    当打印服务(PrintSpooler)自动关闭时,通常会导致无法正常打印。这个问题可能由多种原因引起,以下是一些可能的分析和解决方案:问题分析:损坏的打印队列文件:打印队列中出现损坏的文件可能导致打印服务关闭。冲突的打印机驱动程序:旧的、损坏或不兼容的打印机驱动程序可能导致打印......
  • 数智融合,华为云GaussDB(for MySQL)助力企业释放数据新价值
    2024年2月27日,在“2024年世界移动通信大会”(MobileWorldCongress2024,简称MWC2024)上,以“云原生×AI,跃迁新机遇”为主题的创原会圆桌成功举办。会上,全球企业技术精英面对面交流,围绕云原生×AI技术变革,分享企业在架构、算力、存储、数智、应用开发、媒体技术、安全体系方面的七......
  • 预算有限,资源冗余?DWS集群缩容如何帮你解决烦劳
    本文分享自华为云社区《GaussDB(DWS)华为云数仓使用实践–预算有限,资源冗余?华为云数仓集群缩容帮你解决烦劳》,作者:OneToOne。一、为什么要做缩容?在使用GaussDB(DWS)数仓时,在业务不同的时段,对数仓的计算资源大小有不同的需求。在业务繁忙、流量高峰的时候需要对DWS集群节点扩容,......
  • 华为云峰会2024,GaussDB扬帆出海,给世界一个更优选择
    本文分享自华为云社区《华为云峰会2024,GaussDB扬帆出海,给世界一个更优选择》,作者:GaussDB数据库。2024年2月26~29日,由GSM协会主办的“2024年世界移动通信大会”(MobileWorldCongress2024,简称MWC2024)在西班牙巴塞罗那举行。MWC2024前夕,以“一切皆服务,加速千行万业智能升级”为......
  • 华为云GaussDB支撑农行超级网银业务,性能和稳定性备受认可
    数据库作为数据驱动业务创新和智慧银行建设的关键基础设施,在银行数字化变革中具有举足轻重的作用。在金融科技发展和国家政策引领下,银行纷纷加快推进数字化转型时代,正在经历一场以科技引领、数据赋能、数字经营为目标的智慧银行数字化变革。数据库作为数据驱动业务创新和智慧银......
  • GaussDB_on_kylinV10SP3_单节点安装过程
    GaussDB_on_kylinV10SP3_单节点安装过程背景OpenGauss的搭建和部署非常简单但是GaussDB的就比较复杂.我理解openGauss的简单版本应该就是PG内核直接使用但是GaussDB的版本应该是更换了存储殷勤,所以部署起来比较复杂.自己的理解可能不正确.注意本次只是进行:单节点中......
  • GaussDB(for MySQL) Serverless全面商用:无感弹性,极致性价比
    本文分享自华为云社区《GaussDB(forMySQL)Serverless全面商用:无感弹性,极致性价比》,作者:GaussDB数据库。技术背景对于现代企业级IT系统,数据库往往是作为底座一般的存在,数据库的稳定性、可靠性如果难以保障,整个系统的平稳运行将无从谈起。出于如上考量,在部署数据库资源时,客户......
  • 华为云GaussDB支撑农行超级网银业务,性能和稳定性备受认可
    数据库作为数据驱动业务创新和智慧银行建设的关键基础设施,在银行数字化变革中具有举足轻重的作用。在金融科技发展和国家政策引领下,银行纷纷加快推进数字化转型时代,正在经历一场以科技引领、数据赋能、数字经营为目标的智慧银行数字化变革。数据库作为数据驱动业务创新和智慧银......