PostgreSQL做为一个近年来才在国内开始发展的国外的开源数据库产品,不管是数据库自己的问题仍是对数据库使用不当形成的问题,在一段时间内可能不容易找到或者找不到服务提供商,所以高可用性是使用PostgreSQL的一个很是重要的问题。本节介绍PostgreSQL的高可用Synchronous Replication+HOT STANDBY单活双机同步热备方式,这种方式能够保证只有在主备同时奔溃的状况下才会丢失数据,且Standby库能够提供读能力供分担负载。数据保护模式相似Oracle Active DataGuard的最大保护模式。sql
本节仅对关键参数做出说明,其余有大量PG参数配置没法逐一解释,阅读前最好对PG有必定了解。数据库
PostgreSQL数据库自己提供三种HA模式,这里简单介绍:安全
1. 基于日志文件的复制服务器
Master库向Standby库异步传输数据库的WAL日志,Standby解析日志并把日志中的操做从新执行,以实现replication功能。缺点在于Master库必须等待每一个WAL日志填充完整后才能发给Standby,若是在填充WAL日志的过程当中Master库宕机,未发送的日志内的事务操做会所有丢失。网络
2. 异步流复制模式app
Master库以流模式向Standby库异步传输数据库的WAL日志,Standby解析收到的内容并把其中的操做从新执行,以实现replication功能。这种方式和“基于日志文件的复制”相比不须要等待整个WAL日志填充完毕,大大下降了丢失数据的风险,但在Master库事务提交后,Standby库等待流数据的时刻发生Master宕机,会致使丢失最后一个事务的数据。同时备库能够配置成HOT Standby,能够向外提供查询服务,供分担负载。dom
3. 流同步复制模式(Synchronous Replication)异步
顾名思义,是流复制模式的同步版本。向Master库发出commit命令后,该命令会被阻塞,等待对应的WAL日志流在全部被配置为同步节点的数据库上提交后,才会真正提交。所以只有Master库和Standby库同时宕机才会丢数据。多层事务嵌套时,子事务不受此保护,只有最上层事务受此保护。纯读操做和回滚不受此影响。同时备库能够配置成HOT Standby,能够向外提供查询服务,供分担负载。采用这种模式的性能损耗依据网络状况和系统繁忙程度而定,网络越差越繁忙的系统性能损耗越严重。socket
能够依据实际状况权衡以上三种数据库复制模式的优缺点决定使用哪种数据库高可用模式。这里推荐使用第二种高可用方式(异步流复制模式)实现数据库高可用。下面以异步流复制模式为例,说明HA环境搭建:post
Master:10.19.100.2
Standby:10.19.100.3
注意:
服务器已经安装好PG 10.3。
下面的例子里为了方便配置和说明,并无仔细规划归档日志的保存路径,归档日志在主备切换时用完即弃。
本节全部操做均在10.19.100.2上进行
登录Master库,建立具备用于传递数据的具备replication权限的用户(也能够直接用Super user看成replication用户,但不推荐)
$ psql -U postgres -d postgres Password for user postgres: psql.bin (10.3) Type "help" for help. postgres=# CREATE ROLE replicator login replication password '123456'; CREATE ROLE
修改Master库的pg_hba.conf,把Master库和Standby库的IP地址添加进Master库网络策略白名单中,使Standby库能够连上Master库,同时便于主备切换。
$ cd /PostgreSQL/10/data/ $ vi pg_hba.conf # TYPE DATABASE USER ADDRESS METHOD # "local" is for Unix domain socket connections only local all all md5 # IPv4 local connections: host all all 127.0.0.1/32 md5 host all all 10.19.100.0/24 md5 # IPv6 local connections: host all all ::1/128 md5 # Allow replication connections from localhost, by a user with the # replication privilege. #local replication postgres md5 host replication replicator 10.19.100.2/32 md5 host replication replicator 10.19.100.3/32 md5 #host replication postgres 127.0.0.1/32 md5 #host replication postgres ::1/128 md5
修改Master库的配置文件postgresql.conf,在原配置文件postgresql.conf的基础上修改,修改内容以下:
$ cd /PostgreSQL/10/data/ $ mkdir arch_dir $ mkdir arch_dir_master $ vi postgresql.conf wal_level= logical max_wal_senders = 10 # at least the number of standby archive_mode = on archive_command = 'test ! -f /PostgreSQL/10/data/arch_dir/%f && cp %p /PostgreSQL/10/data/arch_dir/%f' synchronous_standby_names = '' #standby application name, in recover.conf hot_standby=on
说明:
synchronous_standby_names参数对应的参数为同步复制保障节点,若是该参数非空,则任何一个最上层的事务都会等待被同步到该参数指明的节点后才会在Master库提交,若是Standby库无响应Master库会被hung住。若是该参数为空,则表示采用异步复制方式。该参数能够配置多个保障节点,以逗号分隔,PG会从第一个开始尝试。开启同步复制存虽然能最大限度保证数据安全,可是会影响应用可用性。同步模式下,若是Master和Standby之间的网络情况很糟糕,那么同步复制会极大的拉低整个系统的性能;若是Standby宕机,主库会被hang住,虽然这里只记录异步复制,但具体采用何种复制请按自身业务场景选择。
修改后的postgresql.conf配置文件既能做为Master库的配置文件使用,也能做为Standby库的配置文件使用。
建立切换为Standby库时的同步配置文件recovery.done
$ cd /PostgreSQL/10/data/ $ vi recovery.done standby_mode=on restore_command = 'cp /PostgreSQL/10/data/arch_dir_master/%f %p' primary_conninfo='application_name=pg2 host=10.19.100.3 port=5432 user=replicator password=123456' archive_cleanup_command ='pg_archivecleanup /PostgreSQL/10/data/arch_dir_master %r' recovery_target_timeline = 'latest'
重启数据库
$ pg_ctl restart -D /PostgreSQL/10/data/ -l /PostgreSQL/10/data/pglog.log
Standby库须要以Master库的完整备份+归档日志恢复而来,若是Master库还没有对外提供服务,也能够直接复制Master库的数据文件目录,这里采用第一种方法,更贴近实际环境。
本节全部操做均在10.19.100.3上进行。100.3上仅安装好数据库软件,没有启动数据库。
使用主库的热备建立standby库
$ psql -h 10.19.100.2 -p 5432 -U postgres -d postgres Password for user postgres: psql.bin (10.3) Type "help" for help. postgres=# select pg_start_Backup('backuptag',true); pg_start_backup ----------------- 0/3000060 (1 row)
复制主库数据目录
$ scp -r postgres@10.19.100.2:/PostgreSQL/10/data /PostgreSQL/10/data
中止主库的热备锁定
$ psql -h 10.19.100.2 -p 5432 -U postgres -d postgres Password for user postgres: psql.bin (10.3) Type "help" for help. postgres=# select pg_stop_backup(); NOTICE: pg_stop_backup complete, all required WAL segments have been archived pg_stop_backup ---------------- 0/3000168 (1 row)
清理复制过来的主库文件
$ rm -rf /PostgreSQL/10/data/pg_wal $ rm -rf /PostgreSQL/10/data/postmaster.pid $ rm –rf /PostgreSQL/10/data/arch_dir/*
修改备库的recovery文件
$ cd /PostgreSQL/10/data/ $ mv recovery.done recovery.conf $ vi recovery.conf standby_mode=on restore_command = 'cp /PostgreSQL/10/data/arch_dir_master/%f %p' primary_conninfo='application_name=pg3 host=10.19.100.2 port=5432 user=replicator password=123456' archive_cleanup_command ='pg_archivecleanup /PostgreSQL/10/data/arch_dir_master %r' recovery_target_timeline = 'latest'
准备恢复须要的完整的归档文件和wal文件
$ scp -r postgres@10.19.100.2:/PostgreSQL/10/data/pg_wal /PostgreSQL/10/data/ $ scp -r 10.19.100.2:/PostgreSQL/10/data/arch_dir /PostgreSQL/10/data/arch_dir_master
启动备库,观察备库日志
$ pg_ctl start -D /PostgreSQL/10/data -l /PostgreSQL/10/data/pglog.log waiting for server to start..... done server started $ more /PostgreSQL/10/data/log/postgresql-2018-03-08_142945.log 2018-03-08 14:29:47.685 CST [21790] LOG: started streaming WAL from primary at 0/4000000 on timeline 1
流复制搭建完成后,备库是只读的,能够利用它进行读写分离均衡。若是主库失效须要提高备库为主库能够经过下面的命令。
$ pg_ctl promote -D /PostgreSQL/10/data/
观察日志能够看到,数据库结束recovery模式,开始提供服务
LOG: archive recovery complete LOG: database system is ready to accept connections LOG: autovacuum launcher started
而且能够看到recovery.conf文件被数据库自动改名为recovery.done。