返回

文章详情

我们将 PgBouncer 的吞吐量提升了 4 倍

Hacker News2026年7月11日 15:28

PgBouncer 是单线程的。一个进程使用一个 CPU 核心,无论机器有多少个核心。在一台 16 个 vCPU 的机器上,这意味着一个核心负责所有的连接池,而其他十五个核心则闲置,连接池在 Postgres 运行到极限之前就开始限制吞吐量。在 ClickHouse 管理的 Postgres 中,我们运行一组 PgBouncer 进程,进程的数量与可用核心成比例。每个进程都绑定相同的端口,并启用了 so_reuseport。内核会在各个进程之间负载均衡传入的连接,因此客户端仍然连接到单个端点,并且从不知道后面有不止一个 PgBouncer。这是 PgBouncer 自身文档中提到的使用多个核心的机制:每个进程是单线程的,而 so_reuseport 是让每个核心都能工作的方式。Postgres 取消请求通过一个全新的连接到达,携带一个取消密钥,与运行查询的连接分开。通过 so_reuseport,内核可以将这个新连接分配给不同于持有会话的进程。取消请求会落到一个从未听说过该查询的进程上,因此什么都不会发生。对等机制解决了这个问题。进程彼此之间相互了解,因此降落在错误进程上的取消请求会转发到实际拥有会话的进程。取消请求在整个队列中有效,尽管任何特定的请求都可以到达任何位置。池化在事务模式下运行,因此一旦事务提交,服务器连接就会返回到连接池。连接预算在整个队列中分配:max_client_conn 和 max_db_connections 被进程数除,以确保整个队列从不超额订阅 Postgres。我们在相同的 AWS EC2 实例上运行了这两种配置:一个用于连接池的 16 个 vCPU c7i.4xlarge,一个单独的机器用于 Postgres,以及一个驱动负载的第三台机器,使用 pgbench 以仅选择、事务池化模式。一个连接池机器运行一个 PgBouncer 进程;另一个则运行一组 16 个进程。相同的实例类型,相同的 Postgres,相同的工作负载。唯一的变量是一个进程对比十六个进程。我们将客户端连接数从 8 提高到 256,并测量吞吐量以及每个连接池实际上使用的 16 核心机器的 CPU。单个进程的峰值约为 87k 事务/秒,而在更大的负载下降低到 256 个客户端时为 77k,因为所有请求都争夺一个核心。这一组继续攀升到大约 336k 事务/秒,约为 4 倍,因为它有更多的核心可以使用。单个进程工作量最多只能达到一个核心:在负载下,pidstat 显示 PgBouncer 进程被卡在 ~97% CPU,即一个完整的核心,而 16 个 vCPU 的机器整体使用率仍低于 10%。这一组在机器上分散,达到大约 8 个核心忙碌,当 Postgres 和负载生成器成为瓶颈时,仍然有头部空间。保持 256 个客户连接在每台机器上:单进程的机器在整个运行过程中 CPU 使用率接近 9%,而这一组则保持在约 52%。相同的实例类型,相同的 Postgres,相同的工作负载。一个配置使机器闲置,另一个配置则促使它全面工作。EC2 自家的 CloudWatch 指标也呈现出相同的结果:在负载期间,单进程实例平均约 16% 的 CPU 利用率,而这一组为约 60%。CloudWatch 的读取结果略高于内部数据,但差距相同:在一台你支付了 16 个 vCPU 的机器上,单个 PgBouncer 几乎将所有资源都闲置。连接上限的表现也是如此。单个进程自己强制执行 max_client_conn,一旦超过这个限制,新客户端便会被拒绝:FATAL: no more connections allowed (max_client_conn)。在这一组上拆分预算才使得你可以提高总上限,同时保持每个进程和 Postgres 都在安全范围内。客户端 单个 TPS 单个机器 CPU 这一组 TPS 这一组机器 CPU 8 8,910 0.8% 6,450 2.9% 32 54,203 5.2% 64,244 12.3% 64 86,570 8.3% 219,439 31.9% 128 83,463 8.1% 320,547 45.9% 256 76,893 7.7% 336,469 48.9% 在少量连接情况下,单个进程实际上运行良好,甚至略快,因为没有什么可以并行化,连接池的连接也被分散开。差距正是在关键地方显现出来:在真实的并发环境中,一个核心成为了瓶颈。单个 PgBouncer 是个不错的默认值,直到连接池(而非 Postgres)限制了你的吞吐量。将队列的规模与核心相匹配,与 so_reuseport 共享端口,并通过对等将进程连接起来,使连接池重新成为管道,而不是瓶颈。每个 ClickHouse 管理的 Postgres 服务器默认便携带这一设置。配置一个 Postgres,看看它的运行情况。

赞助内容

NordVPN Next-gen Antivirus

本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。

请我喝杯咖啡