如何在PostgreSQL中确定池大小和数据库连接之间的最有效点


14

我们在高峰时段无法处理到数据库服务器的流量。我们正在考虑改进硬件(有关此方面的信息,请参阅此问题),但我们还希望进行池配置和服务器调整。

我们正在开发的应用程序是一款适用于智能手机的基于回合的多人游戏,其后端由带有独角兽RailsPostgreSQL 9.1作为数据库。我们目前有60万注册用户,并且由于游戏状态存储在数据库中,因此每隔几秒钟就会进行数千次写入。我们已经使用PgBadger分析了PostgreSQL的日志文件,在关键时刻,我们得到了很多

FATAL: remaining connection slots are reserved for non-replication superuser connections

解决此问题的简单方法是增加postgresql.conf中的max_connections(当前为100) 。我已经阅读了http://wiki.postgresql.org/wiki/Number_Of_Database_Connections,这表明这可能不是正确的选择。在前面的文章中,它指的是在max_connections和pool size之间找到最佳位置。

为了找到这个最佳位置,可以做什么?有没有什么好的工具可以测量max_connections池大小的不同值的I / O性能?

我们当前的设置是4个游戏服务器,每个服务器有16名独角兽工作者,池大小为5。

这是我们使用的非默认postgres设置:

version                      | PostgreSQL 9.1.5 on x86_64-unknown-linux-gnu,compiled by gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3, 64-bit
checkpoint_completion_target | 0.9
checkpoint_segments          | 60
checkpoint_timeout           | 6min
client_encoding              | UTF8
effective_cache_size         | 2GB
lc_collate                   | en_US.UTF-8
lc_ctype                     | en_US.UTF-8
log_destination              | csvlog
log_directory                | pg_log
log_filename                 | postgresql-%Y-%m-%d_%H%M%S.log
log_line_prefix              | %t
log_min_duration_statement   | 200ms
log_rotation_age             | 1d
log_rotation_size            | 10MB
logging_collector            | on
max_connections              | 100
max_stack_depth              | 2MB
server_encoding              | UTF8
shared_buffers               | 1GB
ssl                          | on
TimeZone                     | localtime
wal_buffers                  | 16MB
work_mem                     | 8MB

您是过去几周在邮件列表中询问此问题的人吗?如果是这样,我将向该讨论添加反向链接。另外:您的数据库服务器硬件和配置是什么?wiki.postgresql.org/wiki/Slow_Query_Questions。包括非默认设置:wiki.postgresql.org/wiki/Server_Configuration。您已阅读wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server吗?您是否在可能的情况下将工作批量处理成更大的交易?您使用缓存层吗?您在使用synchronous_commit = off还是commit_delay
Craig Ringer

因此,您与PostgreSQL服务器总共有20个连接?每个游戏服务器5个?每个游戏服务器上的那5个conns在16位独角兽工作者之间共享?
Craig Ringer

哦,您正在记录慢查询吗?如果是这样,您的热点是什么?简单INSERT的?您的架构是什么样的-是否已分区?什么explain analyze是一些示例查询?您的检查站多久检查一次?(请参阅检查点日志记录选项)。认真地说,您的PostgreSQL版本是什么?(更新:似乎您在此处列出了硬件:dba.stackexchange.com/questions/28061/…
Craig Ringer

无论如何,对于特定的池大小调整,唯一真正的答案是建立负载和数据库服务器吞吐量的可靠度量,然后开始上下调整直到找到最佳位置。
Craig Ringer

@CraigRinger不,我不是那个人。但是感谢您的反向链接!我已经阅读了“ 优化PostgreSQL服务器”,并遵循了一些提到的技巧。我现在包含了非默认设置。我们正在研究进行更大的交易和测试synchronous_commit = off
lorgartzor 2012年

Answers:


14

简短的答案是“由监视和性能指标指导的尝试和错误”。

有一些一般的经验法则可以帮助您找到应该开始的模糊区域,但是它们非常普遍。通常会引用广泛的准则“ CPU数量加上独立的具有磁盘的数量”,但这只是一个令人难以置信的粗略起点。

您真正需要做的是为您的应用程序建立可靠的性能指标。开始记录统计信息。

为此,集成工具的方式并不多。诸如nagios check_postgres脚本,Cacti系统性能计数器日志记录,PostgreSQL统计信息收集器等之类的东西……但是并没有太多东西可以将它们放在一起。可悲的是,您必须自己做一点。对于PostgreSQL方面,请参见PostgreSQL手册中的监视。存在一些第三方选项,例如EnterpriseDB的Postgres Enterprise Monitor

对于此处提到的应用程序级指标,您将需要将它们记录在共享数据结构中或外部非持久性数据库(如Redis)中,并在记录它们时或在将它们写入PostgreSQL数据库之前对其进行聚合。尝试直接登录到Pg将使您的测量结果与记录测量结果而产生的开销失真,并使问题更严重。

最简单的选项可能是您用来记录应用程序状态的每个应用程序服务器中的一个单例。您可能想要保持不断更新的最小值,最大值,n,总数和均值;这样,您不必存储每个统计点,而只需存储汇总。此单例可以每x分钟将其总计统计信息写入Pg,这是一种足够低的速率,因此对性能的影响将最小。

从...开始:

  • 什么是请求延迟?换句话说,从收到客户端的请求到响应客户端之前,该应用需要多长时间。在一段时间内汇总记录,而不是单独记录。按请求类型分组;按页面说。

  • 应用程序执行的每个查询或查询类型的数据库访问延迟是多少?从数据库询问信息/存储信息到完成需要多长时间,并且可以继续进行下一个任务?同样,在应用程序中汇总这些统计信息,仅将汇总信息写入数据库。

  • 您的吞吐量如何?在给定的x分钟内,数据库为您的应用执行的每个主要类的查询有多少次?

  • 在x分钟的同一时间范围内,有多少个客户请求?

  • 每隔几秒钟进行一次采样,并在数据库中相同的x分钟窗口中进行汇总,那里有多少个数据库连接?他们中有多少人闲着?有多少人活跃?在插入?更新?选择?删除?在那段时间内有多少笔交易?请参阅统计信息收集器文档

  • 再次在相同的时间间隔内采样和聚合,主机系统的性能指标是什么样的?每秒有多少读取磁盘和多少写入磁盘IO?每秒磁盘读取和写入兆字节?CPU使用率?平均负载?RAM使用?

现在,您可以通过关联数据,对其进行图形绘制等方式来开始了解应用程序的性能。您将开始看到模式,开始发现瓶颈。

您可能会发现,尽管磁盘I / O每秒的兆字节数非常低,但系统却处于瓶颈INSERTUPDATE以高事务速率运行。这暗示您需要使用电池支持的回写式高速缓存RAID控制器或某些高质量的受电源保护的SSD来提高磁盘刷新性能。如果还可以,synchronous_commit = off则可以在服务器崩溃时丢失一些事务,并且/或者使用commit_delay,以减轻一些同步负载。

当根据并发连接数对每秒事务进行图形化处理并更正应用程序所看到的不同请求速率时,您将能够更好地了解吞吐量的最佳位置。

如果您没有快速刷新存储(BBU RAID或快速耐用的SSD),那么您将不希望有更多数量的活动写入连接,最多不超过所拥有磁盘数量的2倍,根据RAID的排列可能会更少,磁盘性能等。在这种情况下,甚至不值得反复试验;只需使用快速磁盘刷新将存储子系统升级到一个

请参阅参考资料pg_test_fsync,以找到可以帮助您确定是否存在问题的工具。大多数PostgreSQL软件包都将该工具安装为contrib的一部分,因此您无需编译它。如果你不是两三千OPS /获得较少的第二次在pg_test_fsync迫切需要升级你的存储系统。我配备SSD的笔记本电脑的容量为5000-7000。我的工作站正在使用7200rpm SATA磁盘的4磁盘RAID 10阵列,并且直写(非写缓存)的f_datasync速度为每秒80 ops ,而每秒的速度为20 ops fsync()。它慢了数百倍。比较:笔记本电脑,SSD VS 工作站直写(非写入缓存)RAID 10。这款笔记本电脑的SSD很便宜,我不一定相信它会在功耗下降时刷新其写缓存。我会保留良好的备份,并且不会将其用于我关心的数据。高质量的SSD表现出色,即使不是更好,也可以持久耐用。

对于您的申请,我强烈建议您研究:

  • 一个具有快速冲洗功能的良好存储子系统。我不能太强调这一点。具有电源保护写回缓存的高质量电源故障保护固态硬盘和/或RAID控制器。
  • 使用UNLOGGED表存储数据可能会造成损失。定期将其聚合到日志表中。例如,将进行中的游戏保留在未记录的表中,并将比分写入普通的持久表。
  • 使用commit_delay(对于快速刷新的存储不太有用-提示)
  • 关闭synchronous_commit您可能会损失的交易(对于快速刷新的存储而言,它没什么用-提示提示)
  • 对表进行分区,尤其是对数据“老化”并进行清理的表。删除分区而不是从分区表中删除。
  • 部分索引
  • 减少您创建的索引数。每个索引都有写入成本。
  • 将工作分批处理成更大的交易
  • 使用只读热备用副本减轻主数据库的读取负荷
  • 使用诸如memcached或redis之类的缓存层来处理那些更改频率较低或可能过时的数据。您可以使用PostgreSQL表上的触发器来使用LISTENNOTIFY执行缓存无效化。

如有疑问:http : //www.postgresql.org/support/professional_support/

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.