GaussDB(DWS)通信库libpq重构介绍(一)

网友投稿 629 2022-05-30

通信库libpq重构解决两点问题:

针对大并发短查询场景下,CN与DN建立/复用/归还/释放连接时争抢全局锁PoolerLock,造成的性能问题进行Pooler锁优化;

针对当前代码仓中libpq代码冗余度高、复用性差、可维护性差、可读性差问题,对libpq代码进行整合以符合clean code要求。

GaussDB(DWS)通信库libpq重构介绍(一)

在现网多个局点,在高并发短查询场景下,CN与DN建连时等待PoolerLock锁耗时,导致环境CPU资源无法进一步使用,严重影响此场景下查询性能。Poller锁优化旨在高并发短查询场景下优化CN与DN建连性能,pooler建连不再制约环境CPU资源使用,全面提升高并发短查询性能。

libpq代码合并旨在提高libpq代码的复用性、可读性、可维护性,符合clean code要求。

一、pooler锁优化

Pooler连接总体分两大类:一类空闲连接,存储在某个DBPool的NodePool中;一类是使用中的连接,存储在每个线程独立的poolAgent数据结构中,因为遍历需求,所有线程的poolAgent指针又存储在全局的poolAgents数组中。

Pooler锁优化总体方案是使用无锁ringbuffer存储空闲连接和可用的agent index,实现并发空闲连接的存取不需加锁,并发agent index的存取不需加锁。

针对全局的DBPool链表和NodePool Hash表,仅在新增时加互斥锁,正常查找时加共享锁。

针对CleanConnection、pg_pooler_status、pv_total_memory_detail、pgxc_pool_reload、pg_pool_validate需遍历NodePool中所有空闲连接的场景,使用ringbuffer的pop接口将连接取到本线程,操作完后再push回ringbuffer,实现无锁遍历。

针对以上视图接口需遍历poolAgents数组中所有正在使用连接的场景,在Agents数组中增加status标志位,做短暂的读保护。

二、libpq代码合并

libpq代码从功能角度可以划分为3部分:

基础公共模块

通信建连、断连

应用层定义的通信协议

除去通信协议部分,基础公共模块、通信建连及断连模块的代码实现大体相同,完全可以合并成1份,以动态库的形式提供给其他模块使用,对外只提供必要的通信建连、断连等接口,隐藏内部具体实现。

首先梳理并确定3个模块公用的建连、断连流程,如图 3‑1、图 3‑2所示。在此基础上,确定建连、断连流程的内部接口与外部接口、使用的数据结构,外部接口声明、结构体前置声明位于libpq-fe.h头文件中,内部接口声明、结构体定义位于libpq-int.h头文件中。其他模块使用libpq时,只需要libpq-fe.h头文件与libpq.so,不需要关注libpq内部实现。

合并过程中,对于相似的代码,提炼出公共函数,提高代码的复用性、可读性;对于差异较大的代码,采用注册回调函数的方式(startupPacket构建、result成员内存释放),保留差异逻辑。

合并完成后,3个模块各自目录下的冗余代码或者冗余文件都被删除。合并以后的代码实现存放在interfaces/libpq目录下,头文件存放在include/libpq目录下。

图 2‑1 公用建连流程

图 2‑2 公用断连流程

图 2‑3 libpq合并文件结构

libpq重构的详细设计,将在后面具体介绍。

想了解GuassDB(DWS)更多信息,欢迎微信搜索“GaussDB DWS”关注微信公众号,和您分享最新最全的PB级数仓黑科技,后台还可获取众多学习资料~

EI企业智能 Gauss AP 数据仓库服务 GaussDB(DWS) 数据通信

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

上一篇:自动网络搜索(NAS)在语义分割上的应用(二)
下一篇:云原生之路02之Kubernetes快速入门
相关文章