我有两个安装了A
数据库的Linux服务器(B
和PostgreSQL 9.5
)。我按照documentation中的说明配置了热备用模式。在此设置中,A
在热备用模式下配置为主设备B
。这样做效果很好,并且表现得像预期的那样。
现在,我想通过Java EE
/ Hibernate
通过JDBC
数据源将独立的TomEE
应用程序(在不同的计算机上运行)连接到此数据库设置。
PostgreSQL driver文档指出,可以在jdbc连接URL中指定多个主机:
jdbc:postgresql://host1:port1,host2:port2/database
所以我的问题是:
A
关闭并且B
被手动切换到正常操作模式,我的应用程序是否仍然可以使用jdbc连接URL继续进行数据库操作,如上所述?注意:从我学到的各种来源,PostgreSQL
不支持自动故障转移(除非第三方软件参与了此过程 - 请参阅下面的评论)。因此,需要手动执行故障转移,这对于此特定用例是可以的。
修改-1:
我决定测试pgBouncer
(如评论中所示)以获得解决方法。它适用于我的用例。我编写了一个监视程序脚本,它自动执行手动步骤:
A
仍然存在,则继续检查并侦听传入的连接。B
切换到正常运行模式,然后让它成为新主服务器并重新启动服务。pgBouncer
设置更改为指向B
而不是A
,然后重新启动服务。但是,如果有人没有第三方软件的经验,我仍然会感兴趣吗?
答案 0 :(得分:10)
在这种情况下,最好进行测试和测量。
我没有亲自动手的'使用PostrgeSQL热备用模式的经验,但我已经为Java应用程序完成了数据库故障转移。
首先,在PostgreSQL driver文档页面上测试声明
关于?targetServerType=master
参数(在页面底部提到)。
写一个小Java" PgHsm"使用main方法的类,该方法通过DriverManager.getConnection
使用PostgreSQL JDBC驱动程序并运行简单的更新查询。
它应该使用服务器A来进行更新查询。在服务器A上停止PostgreSQL,运行PgHsm:它应该无法连接,因为服务器B不是主服务器。
使服务器B成为主服务器,运行PgHsm:它应该运行正常。
数据源由TomEE中的数据库连接池支持。 This page列出了TomEE中可用的内容。 但并不是所有的数据库连接池都是相同的,我现在更喜欢HikariCP,因为根据我的经验,它可以处理"数据库down"场景更可预测。 另请参阅HikariCP' handling database down页面上的结果测试。
不幸的是,HikariCP使用JDBC的get/setNetworkTimeout
来表现可预测性
和PostgreSQL JDBC驱动程序does not implement this(*)。
因此,为了确保(JavaEE)应用程序线程不会永远挂起数据库操作,您需要设置connectTimeout
和socketTimeout
JDBC驱动程序选项。设置socketTimeout
是不稳定的,因为它会自动为数据库的所有查询设置时间限制。
(*)更新:由于版本42.2.x
网络超时为implemented。
要执行的第二项测试涉及更新Java" PgHsm"类使用您选择的数据库连接池实现
并且(至少)启动(至少)两个在循环中连续运行简单更新查询的线程(在循环中,从池中获取数据库连接并在提交/回滚后返回到池)。
当您关闭服务器A并将服务器B切换到" master"模式,监控" PgHsm"以及线程在执行数据库操作时等待/挂起的时间。
测试结果可用于更新JDBC驱动程序选项和池设置。专注于以下结果:
第二个测试依赖于服务器A不可用,因此连接测试查询(由数据库连接池执行)失败。
在两个服务器仍然可用但主交换机和从交换机的情况下,连接测试查询将无济于事
并且数据库连接池将提供与应用程序的错误(现在只读)数据库连接。
在这种情况下,需要人工干预。 A"故障转移模式"对于HikariCP的描述here
(仅适用于configuration页面上描述的选项allowPoolSuspension
):
第三个测试将使用JavaEE应用程序,到现在为止,您应该知道会遇到什么问题。 应用程序在这些测试之后进行更新以改善处理和数据库传输并不常见。场景 (例如设置(默认)query-timeouts)。 在您的情况下,"暂停,刷新和恢复数据库连接池"在手动故障转移期间使用的功能(上述模式)也是可取的。