java - 在多个 Map-Reduce 作业之间传递数据库连接对象

标签 java database postgresql hadoop mapreduce

从根本上来说,这个问题是关于:同一个数据库连接是否可以跨多个进程使用(因为不同的 Map-Reduce 作业位于真正不同的独立进程中)。

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

为了给您提供问题的背景信息,我有多个并行运行的 Map-Reduce 作业(大约 40 个 reducer ),每个作业都想要更新 PostGres 数据库。如何有效地管理这些进程中的数据库读/写。注意:数据库托管在独立的计算机上,与运行 MapReduce 作业的位置无关。

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

最佳答案

Can the same DB connection be used across multiple processes

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

What happens in case if the maximum number of connections to the DB(which is preconfigured on the server hosting the DB) have exhausted and a new process tries to get a new connection?

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


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

您需要做的是使用外部连接池,如 PgBouncerPgPool-II与您的工作人员保持一组轻量级连接。然后,池化器拥有较少数量的真实服务器连接,并在来自客户端的轻量级连接之间共享这些连接。

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

另一种方法是使用一个或多个线程(每个线程一个连接)的编写器进程,该进程从reduce 工作线程中获取已完成的工作并将其写入数据库,以便reduce 工作线程可以继续执行下一个工作单元。如果作者落后太多,您需要有一种方法告诉归约工作人员等待。有几种 Java 排队系统实现适合于此,或者您可以使用 JMS。

参见IPC Suggestion for lots of small data

还值得尽可能优化写入 PostgreSQL 的方式,使用:

  • 准备好的声明
  • 一个commit_delay
  • synchronous_commit = 'off' 如果您可以承受在服务器崩溃时丢失一些事务的损失
  • 将工作分批处理为更大的事务
  • COPY 或多值 INSERT 用于插入数据 block
  • 具有实用磁盘子系统的体面硬件,而不是具有糟糕 I/O 的 Amazon EC2 实例或具有 5400rpm 磁盘的 RAID 5 盒
  • 适当的 RAID Controller ,具有电池支持的回写式缓存,可降低 fsync() 的成本。如果您无法进行大批量工作或使用提交延迟,则最重要的是;如果您的 fsync 速率由于批处理和组提交而较低,则影响较小。

参见:

关于java - 在多个 Map-Reduce 作业之间传递数据库连接对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13116160/

相关文章:

java - 我如何使用 Spring 的 RestTemplate 执行与此 curl 命令等效的操作?

java - 正则表达式模式验证重复字符的计数

java - mahout - 运行 grouplens 示例错误

java - 当我用 openCsv 再次写入文件时,这个文件被覆盖

sql - mysql查询复杂分组

mysql - 如何添加 'created_at' 和 'updated_at' 列?

hibernate - org.postgresql.Driver 上的 Tomcat7 ClassNotFoundException

php - 在 SQL 注入(inject)中使用嵌套 SQL 子查询

database - 在PostgreSQL中联接两个表,其中一个内容为Array字段,另一个为该数组的主表

postgresql - Docker 容器无法访问端口 5432