pgBouncer如何帮助加速Django

问题描述 投票:19回答:2

我有一些基于gevent的管理命令。由于我的管理命令使成千上万的请求,我可以使用Gevent将所有套接字调用转换为非阻塞调用。这真的加快了我的应用程序,因为我可以同时提出请求。

目前我应用程序的瓶颈似乎是Postgres。这似乎是因为用于连接Django的Psycopg库是用C语言编写的,不支持异步连接。

我还读到使用pgBouncer可以将Postgres加速2倍。这听起来不错,但如果有人能解释pgBouncer如何工作和帮助会很棒吗?

谢谢

python django postgresql connection-pooling pgbouncer
2个回答
75
投票

除了节省连接和断开的开销,否则在每个请求上执行此操作,连接池可以将大量客户端连接汇集到少量实际数据库连接。在PostgreSQL中,活动数据库连接的最佳数量通常在某处((2 * core_count)+ effective_spindle_count)。超过这个数字,吞吐量和延迟都会变得更糟。

有时人们会说“我想支持2000个用户,响应时间快”。几乎可以肯定的是,如果你试图用2000个实际的数据库连接做到这一点,性能将是可怕的。如果您的计算机具有四个四核处理器并且活动数据集已完全缓存,那么通过约35个数据库连接汇集请求,您将看到2000个用户获得更好的性能。

要理解为什么这是真的,这个思想实验应该有所帮助。考虑一个假设的数据库服务器机器,只有一个资源可以共享 - 一个核心。该核心将在所有并发请求中平均分时计时,无需开销。假设100个请求都在同一时刻进入,每个请求都需要一秒的CPU时间。核心适用于所有这些核心,在它们之间进行时间切片,直到它们都在100秒后完成。现在考虑如果你在前面放置一个连接池会接受100个客户端连接,但一次只向数据库服务器发出一个请求,将连接繁忙时到达的任何请求放入队列中会发生什么。现在当100个请求同时到达时,一个客户端在1秒内得到响应;另一个客户端在2秒内获得响应,最后一个客户端在100秒内获得响应。没有人必须等待更长时间才能得到响应,吞吐量是相同的,但平均延迟是50.5秒而不是100秒。

真正的数据库服务器有更多的资源可以并行使用,但同样的原则一旦它们已经饱和,你只会通过添加更多的并发数据库请求来伤害事物。它实际上比示例更糟糕,因为随着更多任务,您有更多的任务切换,锁和缓存的争用增加,L2和L3缓存线争用,以及许多其他问题,这些问题都会导致吞吐量和延迟。最重要的是,虽然高work_mem设置可以通过多种方式帮助查询,但该设置是每个连接的每个计划节点的限制,因此对于大量连接,您需要将其保留为非常小以避免刷新缓存甚至导致交换,这会导致计划速度变慢或哈希表溢出到磁盘等事情。

一些数据库产品有效地在服务器中建立了一个连接池,但是PostgreSQL社区已经采取了这样的立场:由于最好的连接池是在靠近客户端软件的情况下完成的,因此他们会将它留给用户来管理它。大多数的poolers都会有一些方法来限制数据库与硬编号的连接,同时允许更多的并发客户端请求,并根据需要对它们进行排队。这是你想要的,它应该在事务的基础上完成,而不是每个语句或连接。


9
投票

PgBouncer通过充当维护连接池的代理来减少建立连接的延迟。如果您打开与Postgres的许多短暂连接,这可能有助于加快您的应用程序。如果你只有少量的连接,你将看不到多少胜利。

© www.soinside.com 2019 - 2024. All rights reserved.