PgBouncer是什么
PgBouncer是为PostgreSQL数据库提供的一个开源的轻量级连接池。对比应用程序直接连接PostgreSQL数据库,PgBouncer不需要为每一个新连接克隆(linux下通过fork系统调用)出一个服务进程,而是会和后端PostgreSQL数据库建立连接缓存,当应用程序需要建立新连接时,只需PgBouncer分配一个空闲连接,这种复用连接可以显著减少数据库服务器的负载,提高应用程序的响应速度和并发性能。
PgBouncer使用C语言编写,实现非常精巧,采用Libevent进行Socket通信,通信方式效率很高。PgBouncer中每一个数据库对应的连接池是一个PgPool结构体,主要包含以下四个链表:活跃客户端连接链表、等待客户端连接链表、活跃服务端连接链表、空闲服务端连接链表。
- 当客户端连接到PgBouncer后,连接会增加到active_client_list
- 如果此时服务端连接已经达到了设置的最大连接池数量,那么新的客户端查询,就会从active_client_list进入到waiting_client_list
- 当客户端在执行某一个事务,此时正在执行事务的服务端连接就处于active_server_list
- 当客户端结束事务,会执行release_server函数,正在执行事务的服务端连接会从active_server_list释放,进入到idle_server_list
- 当客户端有新的查询,会优先复用idle_server_list中的连接
- 当超过一定时间,idle_server_list中的连接会自动释放掉
以上四个链表分别对应RDS PostgreSQL提供监控的client_connections_active、client_connections_waiting、server_connections_active和server_connections_idle四个指标。
structPgPool { structStatListactive_client_list; structStatListwaiting_client_list; structStatListactive_server_list; structStatListidle_server_list; }
应用场景
适用于短连接较多,频繁创建和销毁连接的场景。使用PgBouncer连接池,PgBouncer会将与后端PostgreSQL数据库的连接缓存,从而能有效避免频繁创建、销毁进程带来的资源耗费。
适用于数据库存在空闲连接数较多以及需要限制最大空闲时间的场景。有助于控制数据库服务器的负载和资源使用情况,避免大量空闲连接对系统内存的占用。由于PgBouncer采用c语言编写,每个连接仅消耗2KB内存,因此无需担心PgBouncer本身对系统的资源消耗问题。
性能对比
客户端配置:系统centos 7.8,32c128g,使用sysbench工具
服务端配置:系统centos 7.8,8c32g,对比直接连接PostgreSQL和PgBouncer
Threads/Client |
TPS |
||||
直连 数据库 |
Default_Pool_Size |
||||
8 |
16 |
32 |
64 |
||
8 |
812 |
7253 |
7234 |
7250 |
7250 |
16 |
1255 |
11174 |
11083 |
11176 |
11154 |
32 |
1387 |
13858 |
13792 |
13753 |
13762 |
64 |
1370 |
14362 |
14765 |
14622 |
14521 |
128 |
1356 |
14301 |
14425 |
15022 |
15218 |
结论:对比直接连接PostgreSQL,使用PgBouncer连接池在不同客户端数量和不同默认连接池大小的情况下,每秒事务处理数(TPS)是直连PostgreSQL的10倍左右
如何使用
对于自建PostgreSQL,需要用户下载、编译、安装、配置和启动后才能使用。而使用RDS PostgreSQL,可以在控制台界面一键开启和关闭,具体可以参考阿里云官方文档:
开启PgBouncer后,并不会影响到之前直连 RDS PostgreSQL的链路,系统会自动为PgBouncer分配默认端口6432(支持用户后续修改),同时支持提供VPC私网和公网连接到PgBouncer,即用户可以同时直连到PostgreSQL和连接到PgBouncer两种互不影响的方式连接到RDS PostgreSQL实例,具体的链路如图所示。图中显示为多可用区部署的高可用架构主实例,并且挂有一个单节点的只读实例,只读实例也支持开启PgBouncer,需要用户在主实例开启PgBouncer后,单独为只读实例开启。从图中可以看出PgBouncer是和节点部署在一起,放发生HA切换后,被库提升为主库,此时被库上的PgBouncer也开始对外服务,从而满足PgBouncer和主实例相同的高可用要求。
RDS PostgreSQL开启PgBouncer后,系统会自动生成pgbouncer.ini配置文件,默认客户端连接到PgBouncer时数据库名和PostgreSQL数据库名相同,认证方式auth_type采用hba的方式,不限制客户端使用的用户名和要连接到PostgreSQL的数据库名。系统会在pgbouncer.ini设置PgBouncer默认参数,并开放部分参数给用户查看和修改,具体如下表所示。关于PgBouncer配置更多信息,可以参考PgBouncer官方文档。
PgBouncer提供三种连接模式,分别是:
- 会话级别连接(Session),当客户端端开,数据库连接会放回到连接池中;
- 事务级别连接(Transaction),当一个事务执行完毕后,数据库连接会放回到连接池中;
- 语句级别连接(Statement),当执行完一个SQL语句时,数据库连接会放回到连接池中。
RDS PostgreSQL默认提供的连接池模式是transaction级别,用户可以根据业务需求来修复连接池模式。需要注意的是:Transaction和statement模式不支持prepare statement,更多关于不同连接池的功能和限制可以参考PgBouncer文档。
参数名 |
参数类型 |
默认值 |
描述 |
pgbouncer.pool_mode |
string |
transaction |
连接池模式,指定客户端在什么情况下可以重用连接。
|
pgbouncer.default_pool_size |
int |
20 |
连接池默认允许连接数。 |
pgbouncer.max_client_conn |
int |
100 |
连接池允许的最大客户端连接数。 |
pgbouncer.min_pool_size |
int |
0 |
连接池允许的最小客户端连接数。 |
pgbouncer.query_wait_timeout |
int |
120 |
允许查询等待执行的最长时间。单位:秒。 如果在此期间未将查询分配给服务器,则客户端将断开连接。 如果配置为0,则表示禁用。此时客户端将无限期排队。 |
pgbouncer.ignore_startup_parameters |
string |
extra_float_digits |
启动参数,您可以在此参数中指定PgBouncer启动跟踪参数,使用英文逗号(,)分隔。 |
pgbouncer.stats_users |
string |
"" |
允许连接到PgBouncer虚拟库上运行只读查询的数据库用户,使用英文逗号(,)分隔。 |
RDS PostgreSQL对于PgBouncer提供6个监控指标,主要包客户端连接、服务端连接和连接池数量等信息,用户可以在控制台上实时查看PgBouncer的监控指标信息。另外,用户也可以通过修改pgbouncer.stats_users参数,指定查询PgBouncer连接池提供的默认库pgbouncer的用户,通过该用户连接到pgbouncer后,执行相关查询。
RDS PostgreSQL支持PgBouncer使用TLS连接,用户不需要单独为PgBouncer开启TLS,当PostgreSQL实例开启TLS后,PgBouncer也会同步开启。需要注意,PgBouncer本身不支持ACL为verify-ca或verify-full的连接验证,也不支持客户端证书吊销文件,具体详情可以参考RDS PostgreSQL的SSl链路加密:
总结
PgBouncer作为一款开源的轻量级数据库连接管理工具,能显著降低较多短连接时PostgreSQL数据库建立和销毁进程的资源消耗,可以对PostgreSQL数据库可能存在大量空闲连接导致内存占用过高的场景起到有效的限制作用。当您使用RDS PostgresSQL数据库时,仅需一键开启和关闭PgBouncer,省去相对复杂的安装和配置PgBouncer的过程,并且RDS PostgresSQL支持控制台PgBouncer参数查看和修改、同步主实例TLS相关配置、监控指标可视化等。欢迎用户体验和使用RDS PostgresSQL的内置PgBouncer连接池功能!