2

从根本上讲,这个问题是关于:可以跨多个进程使用相同的数据库连接(因为不同的 map-reduce 作业位于不同的独立进程中)。

我知道这是一个微不足道的问题,但如果有人也能回答这个问题,那就太好了:如果与数据库的最大连接数(在托管数据库的服务器上预先配置)已经用尽并且新进程试图获得新连接?它是否等待一段时间,如果是,是否有办法为此等待期设置超时。在这种特殊情况下,我说的是 PostGres DB,用于与 DB 对话的语言是 java。

为了给你一个问题的背景,我有多个并行运行的 map-reduce 作业(大约 40 个 reducer),每个都想更新一个 PostGres 数据库。我如何有效地管理这些进程中的这些数据库读/写。注意:数据库托管在独立于 map reduce 作业运行位置的单独机器上。

连接池是一种选择,但有时效率非常低,尤其是对于每秒几次读/写。

4

1 回答 1

4

是否可以跨多个进程使用相同的数据库连接

不,不是以任何理智或可靠的方式。您可以使用代理进程,但无论如何您都离发明连接池只有一步之遥。

如果到数据库的最大连接数(在托管数据库的服务器上预先配置)已经用尽并且新进程尝试获得新连接,会发生什么情况?

连接尝试因 SQLSTATE 而失败53300 too_many_connections。如果它等待,服务器可能会耗尽其他限制并开始在为现有客户端提供服务时出现问题。


对于这样的问题,您通常会使用像 C3P0 或 DBCP 这样的工具来进行 JVM 内池化,但是当您有多个 JVM 时,这将不起作用。

您需要做的是使用PgBouncer或PgPool -II 之类的外部连接池来维护一组来自您的工作人员的轻量级连接。然后,pooler 拥有较少数量的真实服务器连接,并在来自客户端的轻量级连接之间共享这些连接。

连接池通常比不池有效,因为它允许您针对硬件和工作负载优化活动 PostgreSQL 工作进程的数量,从而为工作提供准入控制。

另一种方法是让编写器进程具有一个或多个线程(每个线程一个连接),从 reduce 工作人员那里获取完成的工作并写入数据库,因此 reduce 工作人员可以继续他们的下一个工作单元。如果作者落后太远,您需要有一种方法告诉 reduce 工作人员等待。有几个 Java 排队系统实现可以适用于此,或者您可以使用 JMS。

大量小数据见IPC Suggestion

使用以下方法尽可能优化写入 PostgreSQL 的方式也是值得的:

  • 准备好的报表
  • 一种commit_delay
  • synchronous_commit = 'off'如果服务器崩溃,您是否有能力丢失一些交易
  • 将工作批量处理成更大的交易
  • COPY或多值INSERTs 插入数据块
  • 具有有用磁盘子系统的体面硬件,而不是某些具有糟糕 I/O 的 Amazon EC2 实例或具有 5400rpm 磁盘的 RAID 5 盒
  • 具有电池支持的回写缓存的适当 RAID 控制器,以降低 fsync() 的成本。如果你不能做大批量的工作或使用提交延迟,最重要的是;如果由于批处理和组提交而导致 fsync 速率较低,则影响较小。

看:

于 2012-10-29T05:14:45.313 回答