我需要帮助来了解此错误的原因以及如何解决它。
我有一台运行 PostgreSQL 9.3 的服务器。该集群有大约1.000 个数据库。我使用 pgBouncer 来池连接,并且我为每个数据库设置了一个只有 1 个连接的 pool_size。任何时候的活动连接总数为 ~80 。这是因为大多数数据库几乎没有任何活动。
在过去的几个月里,我的应用程序负载一直在缓慢增加,在过去的几天里,我开始看到 postgres 日志文件中间歇性地出现错误。记录错误的时间对应于负载比平时稍高的短暂时刻。请注意,当 postgres 尝试分叉一个新进程以进行连接甚至是 autovacuum 进程时,会发生错误:
2020-05-07 07:16:16 -03 LOG: main could not fork new process for connection: Cannot allocate memory
2020-05-07 07:16:17 -03 LOG: could not fork autovacuum worker process
这些是我的一些 PostgreSQL 设置:
max_connections = 300
shared_buffers = 2GB
effective_cache_size = 2GB
maintenance_work_mem = 1GB
work_mem = 288MB
wal_buffers = 8MB
checkpoint_segments = 16
该服务器有 64GB 的总 RAM,16 个 CPU 内核,运行 CentOS 7。我的堆栈是:Nginx、uWSGI、Redis、pgBouncer 和 PostgreSQL。它们都安装在同一台服务器上,因此必须在堆栈的元素之间共享资源。Redis 设置为使用不超过 30GB 的 RAM。Nginx ~8GB 内存。uWSGI 使用约 10GB 的 RAM。PostgreSQL 使用约 8GB 的 RAM。
我不是 PostgreSQL 方面的专家。我一直在阅读有关内存消耗的文档,考虑到我的设置,我最好的猜测是我需要为 shared_buffers 和 Effective_cache_size 设置更高的值。我得出这个结论是因为这些设置已经存在了很长时间(当我的服务器资源少得多时)。但在过去的几年里,我一直在向我的服务器添加资源,但与此同时它变得更加繁忙。所以我认为shared_buffers 至少应该是8gb,你怎么看?
此外,对于我所读到的内容,我认为我应该使 Effective_cache_size 高于 shared_buffers(考虑到服务器可用的 RAM 量)。我对吗?
还有一件事:你觉得我的 work_mem 设置怎么样?我打算减少它(我不确定为什么将它设置为 288MB)。我知道绝大多数查询都非常简单和快速。这是因为所有数据库都对应于简单的博客应用程序,其中大多数查询都是 SELECT,而 UPDATE 涉及更改特定行的某些值,并不复杂。所以你怎么看?我打算减少work_mem,我的方向正确吗?
非常感谢您!热烈的问候,丽山卓。
我认为你的机器过载了。你没有说你的
max_connection
设置是什么,但根据你所说的,我认为它大约是 1000。只要活动会话的数量在 80 左右,你的内存就不会耗尽,但我假设有更多活动会话的峰值,并且你的 RAM 已经耗尽。
我很惊讶你的机器运行良好,有 80 个活动会话,因为你只有 16 个核心(你没有说任何关于存储的事情)。
1000 个数据库似乎很多;我假设他们每个人都很小。
由于您有这么多数据库,我建议您将一些数据库移动到不同机器上的其他集群。这是分配负载的简单方法。
使用较低的值
max_connections
将减少过载和内存耗尽的危险。