PostgreSQL连接池(PgBouncer)TPS性能优化及相关技术问询
背景信息
硬件规格
- Postgres数据库(GCP SQL):8核CPU、64GB内存,
max_connections=800,初始shared_buffers=22GB,后调整为40GB - PgBouncer虚拟机:16核CPU、64GB内存,与数据库同区域部署
PgBouncer配置
[databases] reader = host=ip dbname=noname password=nopassword [pgbouncer] max_client_conn = 100000 default_pool_size = 40 max_db_connections = 43 pool_mode = "transaction"
- 运行16个PgBouncer实例(端口1001-1016),通过HAProxy分发负载
- 单实例后端最大连接数43,总后端连接数
16×43=688,远低于Postgres的max_connections(800)
pgbench测试结果(测试语句:SELECT 1;)
max_client_conn=10000
| -c | -T | TPS |
|---|---|---|
| 500 | 120 | 60k |
| 1000 | 120 | 56k |
| 1500 | 120 | 55k |
max_client_conn=100000
| -c | -T | TPS |
|---|---|---|
| 500 | 120 | 47k |
| 1000 | 120 | 62k |
| 1500 | 120 | 63k |
| 2000 | 120 | 44k |
| 2500 | 120 | 38k |
| 3000 | 120 | 46k |
| 4000 | 120 | 46k |
| 5000 | 120 | 44k |
shared_buffers调整为40GB后
| -c | -T | TPS |
|---|---|---|
| 2000 | 120 | 69k |
| 5000 | 120 | 62k |
| 7000 | 120 | 60k |
| 10000 | 120 | 64k |
注:测试期间无连接失败,PgBouncer虚拟机CPU最高使用率50%,内存占用低;切换pool_mode至
statement对测试结果影响不大
问题解答
1. 扩缩容前的性能优化手段
Postgres层面
- 调优内存参数:除
shared_buffers外,优化work_mem(降低单操作排序/哈希内存阈值,避免内存浪费)、maintenance_work_mem(提升维护操作内存),并将effective_cache_size设为物理内存的70%-80%(如64GB内存设为45GB),帮助Postgres生成更高效的执行计划。 - 清理闲置连接:设置
idle_in_transaction_session_timeout,自动回收空闲事务连接,避免占用连接资源;当前总后端连接688,离800的上限仍有冗余,可优先利用这部分资源。 - GCP SQL专属优化:检查是否开启GCP SQL自带的连接池(需与PgBouncer兼容),同时确认CPU配额是否充足,避免资源瓶颈。
PgBouncer层面
- 优化连接池参数:
- 配置
reserve_pool_size=5和reserve_pool_timeout=5,为高优先级请求预留连接,减少并发峰值时的等待; - 设置
server_idle_timeout=30(秒)、client_idle_timeout=60(秒),及时回收空闲连接,降低连接管理开销; - 测试
max_client_conn的最优值:从结果看,100000的取值会导致高并发下TPS波动,可在2000-5000区间测试,找到并发支撑与资源开销的平衡点。
- 配置
- 启用多进程模式:每个PgBouncer实例设置
worker_processes=2,充分利用16核CPU的多核能力,提升单实例处理效率。
HAProxy层面
- 切换负载策略:将默认轮询改为
leastconn(最少连接数)策略,确保客户端连接均匀分布到16个PgBouncer实例,避免部分实例过载、部分闲置; - 优化超时配置:调整
timeout client、timeout server参数,与PgBouncer的超时设置匹配,减少连接超时导致的性能损耗;开启tcp-check,自动剔除异常实例。
系统层面
- 优化TCP参数:在PgBouncer虚拟机上调整Linux内核参数:
net.ipv4.tcp_tw_reuse=1:复用TIME_WAIT状态套接字net.ipv4.tcp_fin_timeout=30:缩短FIN_WAIT超时时间net.core.somaxconn=65535:增大监听队列长度,避免连接被拒绝
- 精简后台服务:关闭虚拟机上不必要的进程,确保CPU、内存资源集中在PgBouncer和HAProxy上。
2. 调整shared_buffers后TPS提升的原因
虽然SELECT 1不涉及业务数据磁盘读取,但Postgres处理请求依赖共享内存中的系统元数据(如系统表缓存、连接状态):
- 更大的
shared_buffers可让这些元数据稳定驻留内存,避免频繁从磁盘加载,减少累积的IO开销; - GCP SQL调整
shared_buffers时会自动配套优化effective_cache_size,帮助Postgres生成更高效的查询计划; - 充足的共享内存降低了Postgres内存不足时的内核swap概率,避免内存交换带来的性能波动;
- 高并发场景下,更大的共享内存可容纳更多连接状态结构,减少内存碎片化,提升进程调度效率。
3. 后端连接数优化方式不止新增实例或提升单实例连接数
当前总后端连接688,距离800的上限仍有112的冗余,可通过以下方式优化:
- 利用冗余提升单实例连接数:无需新增实例,将
max_db_connections从43提升至48(16×48=768),仍低于800上限,充分利用数据库连接资源; - 优化连接池复用效率:调整
default_pool_size至45,同时max_db_connections设为48,让连接池在高并发时更高效复用后端连接,减少闲置; - 启用连接预留机制:通过
reserve_pool_size在连接池满时为紧急请求预留连接,降低等待时间; - 均衡负载分布:通过HAProxy的
leastconn策略确保客户端连接均匀分配,避免部分PgBouncer实例的后端连接闲置; - 回收空闲连接:通过
server_idle_timeout及时清理长期空闲的后端连接,释放资源给活跃请求。
内容的提问来源于stack exchange,提问作者Uday Reddy
相关产品推荐
相关产品推荐

