我有一些基于gevent的管理命令。由于我的管理命令可以处理数千个请求,因此我可以使用Gevent将所有套接字调用转换为非阻塞调用。因为我可以同时发出请求,所以这确实加快了我的应用程序的速度。
当前,我的应用程序中的瓶颈似乎是Postgres。似乎这是因为用于连接到Django的Psycopg库是用C编写的,并且不支持异步连接。
我还读到使用pgBouncer可以使Postgres速度提高2倍。这听起来不错,但是如果有人可以解释pgBouncer的工作原理和帮助会很棒。
谢谢
除了节省连接和断开连接的开销(在其他情况下对每个请求执行此操作),连接池还可以将大量客户端连接简化为少量实际数据库连接。在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设置可以通过多种方式帮助查询,但是该设置是 每个连接的每个计划节点 的限制,因此,对于大量连接,您需要将其设置得很小,以避免刷新缓存或甚至导致交换,这导致计划变慢或哈希表溢出到磁盘等情况。
work_mem
一些数据库产品有效地在服务器中建立了一个连接池,但是PostgreSQL社区已经采取了这样的立场,因为最好的连接池是在靠近客户端软件的地方完成的,所以它们将留给用户来管理。大多数池管理器将通过某种方式将数据库连接限制为一个硬数字,同时允许更多并发客户端请求,并根据需要对它们进行排队。这就是您想要的,应该在 事务 基础上完成,而不是按语句或连接完成。