PgCat:用 Rust 重写的 PostgreSQL 连接池,比 PgBouncer 多了路由与故障转移

开源
PostgreSQL
连接池
Rust
数据库
PgBouncer
高可用
2026/10/22
·

阅读时间: 大约 13 分钟

PgCat:用 Rust 重写的 PostgreSQL 连接池,比 PgBouncer 多了路由与故障转移

官方 README 的 Features 状态表:事务池、会话池、多线程运行时、读负载均衡、故障转移等标注为 Stable

PgCat 是 PostgresML 团队用 Rust 编写的 PostgreSQL 连接池与代理(pooler/proxy),自我定位为”like PgBouncer”但额外支持分片、负载均衡、故障转移与镜像。项目采用 MIT 协议,调研时约 4.0k star、267 fork,运行在 Tokio 异步运行时上。官方称其已在生产环境”serve hundreds of thousands of queries per second”,落地用户包括 Instacart、PostgresML、OneSignal。本文回到官方 GitHub README,区分 Stable 与 Experimental,核验它相对 PgBouncer 真正多出来的能力,以及官方没有承诺的部分。

一、背景动机:PostgreSQL 连接模型的天然瓶颈

PostgreSQL 每个后端连接都是一个独立操作系统进程,各自占用内存。成百上千个大多空闲的应用连接会把数据库资源耗在维护进程上,而不是回答查询。连接池的本质,是把大量短寿命客户端连接复用到一组数量可控、稳定的服务器连接上,让数据库在突发流量下保持可预测。PgBouncer 是这个领域的事实标准,但其单进程模型与长期存在的”异常客户端/废弃事务”处理问题,给了 PgCat 切入空间。

二、两种池化模式:会话池与事务池(Stable)

PgCat 完整提供 PgBouncer 的两种模式,默认开启事务池:

  • Session mode(会话池,pool_mode = "session"):一个客户端在整条连接生命周期内独占一台服务器。支持预处理语句(prepared statements)、SET、咨询锁(advisory locks),能力上与直连服务器几乎无差别;
  • Transaction mode(事务池,默认):客户端只在单个事务期间占用服务器,事务结束即归还连接池。官方明确:此模式下不支持预处理语句、SET、咨询锁,替代方案是作用域限于事务的 SET LOCAL 与 pg_advisory_xact_lock。

三、超过传统连接池的四项能力

3.1 多线程运行时(Stable)

PgBouncer 经典上是单进程/协作式模型,PgCat 基于 Tokio 异步运行时,单个进程可利用多核;官方示例部署默认拉起 4 个 worker,建议配 4 颗 CPU,worker 数量可调。

3.2 读查询负载均衡(Stable)

内置查询解析器(sqlparser crate)尽量把 SELECT 路由到副本,把写操作与显式事务路由到主库;读请求在配置的服务器间用 random 或 least open connections(最少开放连接)算法负载均衡。解析器拿不准时,客户端可用扩展 SQL 自己指定:

SET SERVER ROLE TO 'primary';   -- 下一事务走主库
SET SERVER ROLE TO 'replica';   -- 下一事务走副本
SET SERVER ROLE TO 'auto';      -- 交解析器决定
SET SERVER ROLE TO 'any';       -- 随机挑一台
SET SERVER ROLE TO 'default';   -- 恢复默认

该设置持续到再次修改或客户端断开;默认行为由 default_role 控制。

3.3 故障转移(Stable)

每台服务器在交给客户端之前先用一个极快的 ; 查询做健康检查,日常也随每个客户端查询持续探测。不可达服务器被**封禁(ban)**一段时间(ban_time 默认 60 秒),期间不再服务,流量改道剩余健康节点;官方特别说明:若所有服务器都被封禁,会清空封禁列表作为误报(false positive)的安全兜底;主库永远不会被封禁。

3.4 热更新与可观测(Stable)

除 host、port 外,所有配置(含分片与副本配置)都可通过给进程发 SIGHUP,或向管理库执行 RELOAD 动态重载,无需重启。管理上提供兼容 PgBouncer 的 pgbouncer 与 pgcat 两个管理库(沿用熟悉的 SHOW 命令),并通过 HTTP 端点 /metrics 暴露 Prometheus 指标。传输层支持客户端与池之间、池与服务器之间双向 TLS;客户端用 MD5 认证,池连服务端支持 MD5 与 SCRAM-SHA-256;还可用 auth_query 做认证透传,配置文件不落明文密码。

3.5 实验性能力(Experimental,勿用于关键路径)

  • 分片:扩展语法 SET SHARD TO '1' 指定分片、SET SHARDING KEY TO '1234' 让池按值选片;也可在 SQL 注释里携带分片键(配合 ActiveRecord/SQLAlchemy annotate),或由池自动解析查询识别分片键;哈希采用与 PostgreSQL 声明式分区一致的 PARTITION BY HASH;
  • 镜像(Mirroring):把同一条查询同时发给多个数据库,用于把副本预热到可上线,或用真实生产流量测试不同 PostgreSQL 版本。

四、功能状态矩阵(官方 README)

功能官方状态备注
事务池Stable与 PgBouncer 一致,并改进了异常客户端与废弃事务处理
会话池Stable与 PgBouncer 一致
多线程运行时StableTokio,利用多核
读查询负载均衡Stable自动在副本与主库间均衡
故障转移Stable定期健康检查,自动绕开坏副本
管理库统计Stablepgbouncer/pgcat 管理库
Prometheus 指标StableHTTP 端点
SSL/TLSStable客户端与服务器双向 TLS
客户端/服务端认证Stable客户端 MD5;服务端 MD5 + SCRAM-SHA-256
配置热更新Stablehost/port 除外
认证透传Stableauth_query,无需明文密码
扩展语法分片Experimental客户端动态指定分片
注释/正则分片Experimental查询注释携带分片键
自动分片Experimental解析查询自动识别分片键
镜像Experimental多库同时路由以预演/压测

五、口径与局限:官方没有承诺的部分

  1. “数十万 QPS”是项目方自述的生产规模,非独立基准:README 未发布标准化压测,自测仅要求用 pgbench(simple/extended 两种协议)回归协议改动,没有公开的时延、p99 或对比 PgBouncer 的吞吐数字;不能把这句话当成可复现的性能承诺。
  2. 查询解析器是 best-effort:官方明说”解析器会尽力判断去向,但有时做不到”,误判时需客户端用 SET SERVER ROLE 纠正;复杂语句、自定义函数、非标准写法都可能让路由决策落空。
  3. 分片与镜像仍是 Experimental:自动分片依赖 SQL 解析,注释/正则方式侵入查询,生产分片仍建议自行校验路由正确性。
  4. 事务池的语义约束不可忽略:预处理语句、SET、咨询锁在事务池不可用,迁移现有应用时这类用法需要改写成 SET LOCAL / xact 锁,否则会出现跨事务状态串味。
  5. 故障转移是连接层绕行,不是 PostgreSQL 原生高可用:它封禁的是”连不上的副本”,主库永不封禁,本身不实现主从提升(failover promotion),数据库层的选主仍要靠 Patroni/repmgr 等方案。
  6. 封禁全清策略是双刃剑:所有节点被封时清空列表以防误报,极端故障下可能瞬间把流量打给其实不健康的节点。

六、适用与不适用场景

适合:

  • 已有一主多从、希望在连接层做读写分离与读负载均衡,而不想让应用自己判断路由的团队;
  • 需要从 PgBouncer 平滑迁移、兼容 SHOW 管理命令与配置习惯,同时想要多核与热更新的团队;
  • 需要健康检查自动绕开坏副本、用 Prometheus 观测连接池的生产服务;
  • 想用镜像功能拿真实流量预热副本或测试大版本升级。

不适合:

  • 只想要最简单单机连接池、无副本、无路由需求(PgBouncer 更轻更成熟);
  • 把 Experimental 分片/镜像当正式分布式分片方案;
  • 依赖事务池里的预处理语句/会话级 SET/咨询锁而不愿改造的应用;
  • 期待 PgCat 完成主库自动选主与容灾切换的场景。

七、客观分析:优势与局限

优势:

  1. PgBouncer 兼容 + 增量能力:两种池化模式与管理命令延续习惯,迁移成本低,又补上了读均衡、故障转移、热更新;
  2. Rust/Tokio 多核模型,相比单进程池更能吃满机器,且内存安全;
  3. 路由决策内建,应用无需集成读写分离 SDK,扩展 SQL 给了手动兜底手段;
  4. 观测与运维齐全:Prometheus、双管理库、双向 TLS、auth_query;
  5. MIT 协议、有 Instacart 等生产用户背书。

局限:

  1. 无公开独立基准,性能优势主要来自多核模型而非可量化跑分;
  2. 解析路由不保证正确,关键写路径仍需显式指定;
  3. 分片/镜像未成熟,距离”数据库中间件”还有差距;
  4. 不替代数据库高可用组件,定位是池+代理,不是选主系统;
  5. 生态与文档沉淀时间短于 PgBouncer,疑难问题的社区资料相对少。

八、它意味着什么

PgCat 证明连接池正在从”单纯复用连接”演进为”带路由与高可用的轻量代理”。对一主多从、读写分离是刚需的 PostgreSQL 团队,它提供了一条兼容 PgBouncer 的低风险升级路径;但它的护城河是连接层治理,不是性能神话,更不是分片或容灾的全部答案。生产采用前应自行用 pgbench 与真实 SQL 校验解析路由,并把 Experimental 功能隔离在非关键路径。

参考来源