PostgreSQL作為一個近年來才在國內開始發展的國外的開源數據庫產品,無論是數據庫本身的問題還是對數據庫使用不當造成的問題,在一段時間內可能不容易找到或者找不到服務提供商,因此高可用性是使用PostgreSQL的一個非常重要的問題。本節介紹PostgreSQL的高可用Synchronous Replication+HOT STANDBY單活雙機同步熱備方式,這種方式可以保證只有在主備同時奔潰的情況下才會丟失數據,且Standby庫可以提供讀能力供分擔負載。數據保護模式類似Oracle Active DataGuard的最大保護模式。
1 數據庫 HA方式簡介
本節僅對關鍵參數作出說明,其他有大量PG參數配置無法逐一解釋,閱讀前最好對PG有一定了解。
PostgreSQL數據庫本身提供三種HA模式,這里簡單介紹:
1. 基於日志文件的復制
Master庫向Standby庫異步傳輸數據庫的WAL日志,Standby解析日志並把日志中的操作重新執行,以實現replication功能。缺點在於Master庫必須等待每個WAL日志填充完整后才能發給Standby,如果在填充WAL日志的過程中Master庫宕機,未發送的日志內的事務操作會全部丟失。
2. 異步流復制模式
Master庫以流模式向Standby庫異步傳輸數據庫的WAL日志,Standby解析收到的內容並把其中的操作重新執行,以實現replication功能。這種方式和“基於日志文件的復制”相比不需要等待整個WAL日志填充完畢,大大降低了丟失數據的風險,但在Master庫事務提交后,Standby庫等待流數據的時刻發生Master宕機,會導致丟失最后一個事務的數據。同時備庫可以配置成HOT Standby,可以向外提供查詢服務,供分擔負載。
3. 流同步復制模式(Synchronous Replication)
顧名思義,是流復制模式的同步版本。向Master庫發出commit命令后,該命令會被阻塞,等待對應的WAL日志流在所有被配置為同步節點的數據庫上提交后,才會真正提交。因此只有Master庫和Standby庫同時宕機才會丟數據。多層事務嵌套時,子事務不受此保護,只有最上層事務受此保護。純讀操作和回滾不受此影響。同時備庫可以配置成HOT Standby,可以向外提供查詢服務,供分擔負載。采用這種模式的性能損耗依據網絡情況和系統繁忙程度而定,網絡越差越繁忙的系統性能損耗越嚴重。
可以依據實際情況權衡以上三種數據庫復制模式的優缺點決定使用哪一種數據庫高可用模式。這里推薦使用第二種高可用方式(異步流復制模式)實現數據庫高可用。下面以異步流復制模式為例,說明HA環境搭建:
Master:10.19.100.2
Standby:10.19.100.3
注意:
服務器已經安裝好PG 10.3。
下面的例子里為了方便配置和說明,並沒有仔細規划歸檔日志的保存路徑,歸檔日志在主備切換時用完即棄。
2 Master庫
本節所有操作均在10.19.100.2上進行
2.1創建Replication用戶
登陸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
2.2 Master庫網絡策略
修改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
2.3 Master庫數據庫配置
修改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
3 Standby庫
Standby庫需要以Master庫的完整備份+歸檔日志恢復而來,如果Master庫尚未對外提供服務,也可以直接復制Master庫的數據文件目錄,這里采用第一種方法,更貼近實際環境。
本節所有操作均在10.19.100.3上進行。100.3上僅安裝好數據庫軟件,沒有啟動數據庫。
3.1創建Standby數據庫
使用主庫的熱備創建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
4 備庫提升為主庫的方法
流復制搭建完成后,備庫是只讀的,可以利用它進行讀寫分離均衡。如果主庫失效需要提升備庫為主庫可以通過下面的命令。
$ 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。