使用客户端驱动程序实现故障转移和读写分离-九游平台
从postgresql 10(libpq.so.5.10)开始,libpq驱动层开始支持故障转移和读写分离,jdbc驱动层则支持读写分离、故障转移和负载均衡。
postgresql客户端连接程序向下兼容,对于rds for postgresql 9.5及9.6版本,使用新版本的libpq驱动程序也可以实现故障转移。

本章节中故障转移指的是读业务的故障转移。
- libpq是postgresql的c应用程序接口,包含一组库函数,允许客户端程序将查询请求发送给postgresql后端服务器并接收这些查询的结果。
- jdbc是java语言中用来规范客户端程序如何访问数据库的应用程序接口,在postgresql中jdbc支持故障转移和负载均衡。
驱动 |
读写分离 |
负载均衡 |
故障转移 |
---|---|---|---|
libpq驱动 |
√ |
× |
√ |
jdbc驱动 |
√ |
√ |
√ |
libpq实现故障转移和读写分离
通过libpq函数连接多个数据库,当出现故障时会自动切换到可用的数据库。
postgresql://[user[:password]@][netloc][:port][,...][/dbname][?param1=value1&...]
示例:连接1个rds for postgresql主实例数据库和对应的2个只读实例数据库,只要确保至少有一个数据库可用,读请求就不会失败。
postgres://
参数 |
说明 |
取值样例 |
---|---|---|
|
数据库的主机ip。 |
如果通过内网连接,“instance_ip”是主机ip,即“概览”页面该实例的“内网地址”。 如果通过连接了公网的设备访问,“instance_ip”为该实例已绑定的“弹性公网ip”。 |
|
数据库端口。 |
默认5432,当前端口,参考“概览”页面该实例的“数据库端口”。 |
|
数据库名,即需要连接的数据库名。 |
默认的管理数据库是postgres,可根据业务实际情况填写数据库名。 |
target_session_attrs |
允许连接到指定状态的数据库。 |
|
更多libpq的使用方法和参数说明请参见。
您还可以在应用程序中结合pg_is_in_recovery()函数,判断连接的数据库是主实例数据库(结果为“f”表示主数据库)还是只读实例数据库,进而实现读写分离。
使用python代码的示例如下(psycopg2使用的为libpq):
// 认证用的用户名和密码直接写到代码中有很大的安全风险,建议在配置文件或者环境变量中存放(密码应密文存放,使用时解密),确保安全。 // 本示例以用户名和密码保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量(环境变量名称请根据自身情况进行设置)example_username_env和example_password_env。 import psycopg2 import os username = os.getenv("example_username_env") password = os.getenv("example_password_env") conn = psycopg2.connect(database=,host= , user=username, password=password, port= , target_session_attrs="read-write") cur = conn.cursor() cur.execute("select pg_is_in_recovery()") row = cur.fetchone() print("recovery =", row[0])
jdbc实现故障转移和读写分离
您可以在连接url中定义多个数据库(主机和端口),并用逗号分隔,驱动程序将尝试按顺序连接到它们中的每一个,直到连接成功。如果没有成功,会返回连接异常报错。
jdbc:postgresql://node1,node2,node3/${database}?targetservertype=prefersecondary&loadbalancehosts=true
示例:
jdbc:postgresql://
jdbc连接实例java实现代码请参考:通过jdbc连接rds for postgresql实例。
参数 |
说明 |
取值样例 |
---|---|---|
targetservertype |
允许连接到指定状态的数据库。 |
|
loadbalancehosts |
尝试连接数据库的顺序。 |
|

区别数据库主从的方式是通过查询数据库是否允许写入,允许写入数据的判断为主数据库,不允许写入数据的判断为从数据库。参考libpq实现故障转移和读写分离中通过pg_is_in_recovery()函数来判断,结果为“f”表示为主数据库。
为实现读写分离,需要在配置jdbc时设置2个数据源,首先设置targetservertype=primary,用于写操作。另一个可以根据以下情况进行设置:
- 有一个只读实例,为实现高可用设置targetservertype=prefersecondary,用于读操作。假设主实例ip为10.1.1.1,只读实例ip为10.1.1.2。
jdbc:postgresql://10.1.1.2:5432,10.1.1.1:5432/${database}?targetservertype=prefersecondary
- 有两个以上只读实例,可设置targetservertype=any,用于读操作。假设只读实例ip分别为10.1.1.2、10.1.1.3。
jdbc:postgresql://10.1.1.2:5432,10.1.1.3:5432/${database}?targetservertype=any&loadbalancehosts=true
相关文档
意见反馈
文档内容是否对您有帮助?
如您有其它疑问,您也可以通过华为云社区问答频道来与我们联系探讨