1. 程式人生 > >PostgreSql基於Standby的異步流主從復制

PostgreSql基於Standby的異步流主從復制

postgresql postgresql主從

一、概述

PostgreSQl9.0版本之後推出一個類似於Oracleactive dataguardMySql中繼日誌一樣的日誌傳送。我們借助這個功能就可實現PostgreSql的主從復制。

基本原理就是,通常一臺主數據庫提供讀寫,然後把數據同步到另一臺從庫。從庫不斷apply從主庫接收到的數據,從庫不提供寫服務,只對外提供讀服務。在postgresql中提供讀寫全功能的服務器稱為primary databasemaster database,在接收主庫同步數據的同時又能提供讀服務的從庫服務器稱為hot standby server

PostgreSQL在數據目錄下的pg_xlog子目錄中維護了一個

WAL日誌文件,該文件用於記錄數據庫文件的每次改變,這種日誌文件機制提供了一種數據庫熱備份的方案,即:在把數據庫使用文件系統的方式備份出來的同時也把相應的WAL日誌進行備份,即使備份出來的數據塊不一致,也可以重放WAL日誌把備份的內容推到一致狀態。這也就是基於時間點的備份(Point-in-Time Recovery),簡稱PITR。而把WAL日誌傳送到另一臺服務器有兩種方式,分別是:

1. WAL日誌歸檔(base-file

2. 流復制(streaming replication

第一種是寫完一個WAL日誌後,才把WAL日誌文件拷貝到standby數據庫中,簡言之就是通過cp命令實現遠程備份,這樣通常備庫會落後主庫一個

WAL日誌文件。而第二種流復制是postgresql9.x之後才提供的新的傳遞WAL日誌的方法,它的好處是只要master庫一產生日誌,就會馬上傳遞到standby庫,同第一種相比有更低的同步延遲,所以我們肯定也會選擇流復制的方式。

在實際操作之前還有一點需要說明就是standby的搭建中最關鍵的一步——在standby中生成master的基礎備份。postgresql9.1之後提供了一個很方便的工具—— pg_basebackup,關於它的詳細介紹和參數說明可以在官網中查看(pg_basebackup tool),下面在搭建過程中再做相關具體說明

二、基礎環境介紹

系統平臺:CentOS release 6.6 (Final)

Postgresqlpostgresql-9.6.6

SELINUX=disabled

Iptables關閉

主庫(master)IP:192.168.221.161

從庫(standby)IP:192.168.221.160

基礎環境搭建可以參考前一篇文章(Centos6.6Postgresql9.6.6安裝與配置),也就是PostgreSql的基本安裝與配置。

三、主庫配置

1. 在主庫增加同步的用戶名與密碼

[postgres@MidApp ~]$ psql 
psql (9.6.6)
Type "help" for help.
 
postgres=# CREATE ROLE repluser REPLICATION LOGIN PASSWORD '123456';
CREATE ROLE
postgres=#


2. 修改/home/postgres/pgsql/data/pg_hba.conf,最後一行添加

[root@MidApp tmp]# tail -6 /home/postgres/pgsql/data/pg_hba.conf 
# Allow replication connections from localhost, by a user with the
# replication privilege.
#local replication postgres trust
#host replication postgres 127.0.0.1/32 trust
#host replication postgres ::1/128 trust
Host replication repluser  192.168.221.160/32 md5


這行配置意思是允許用戶repluser192.168.221.160這臺主機上以md5 加密的形式發起到本數據庫的流復制連接

3. 在主配置文件下配置下面幾個參數

listen_address = ‘*’(默認localhost)
wal_level = hot_standby(默認是minimal)
max_wal_senders=5(默認是0)
wal_keep_segments=64(默認是0)
synchronous_standby_names = 'standby01'


第一個參數表示監聽所有IP;第二個參數表示啟動hot standby;第三個參數表示主庫可以有多少個並發的standby數據庫,這裏設置為5;第四個參數表示一個WAL日誌文件大小,默認為16M

技術分享圖片

第五個參數指定同步復制的Standby名稱(從庫的recovery.conf中有要定義的地方,不過這一個參數可以不設置

4. 重啟主庫,讓配置生效。

如果啟動有報錯,可以去日誌排查。

四、從庫配置

首先要保證主庫、從庫之間的同步之前的環境的是一致的,這樣才方便做同步。我因為之前就在從庫機器上配置過PG數據庫,所以一開始走了不少彎路。最後把PG的家目錄清空,重新再來一次才算成功。

1. 在從庫上通過pg_basebackup命令行工具生成基礎備份,命令如下,看到100%說明備份成功

[root@DB tmp]# pg_basebackup -h 192.168.221.161 -F p -P -D /home/postgres/pgsql/data -p5432 -U repluser --password
Password: 
22802/22802 kB (100%), 1/1 tablespace
NOTICE:  WAL archiving is not enabled; you must ensure that all required WAL segments are copied through other means to comple


參數說明:-h 指定連接的數據庫IP

-F 指定輸出的格式,支持p(plain原樣輸出)或者t(tar格式輸出)

-P 在備份過程中實時打印備份進度

-D 指定備份的目錄

-U 指定連接的用戶名

-p 指定要連接的端口

--password 指定要連接的用戶密碼

其他參數介紹:

-R 會在備份後自動生成recovery.conf文件,我也是事後才知道這個參數

-l 指定一個備份的標識

具體的參數介紹可以使用pg_basebackup --help查看,也可以查看官網介紹https://www.postgresql.org/docs/current/static/app-pgbasebackup.html

特別備註:我這裏沒有加-R參數,所以要手動拷貝一下recovery.conf

cp /home/postgres/pgsql/share/recovery.conf.sample /home/postgres/pgsql/data/recovery.conf


添加以下信息:

standby_mode = on
primary_conninfo = 'application_name=standby01 user=repluser password=123456 host=192.168.221.161 port=5432 sslmode=disable sslcompression=1'


2. 修改從庫的主配置文件/home/postgres/pgsql/data/postgresql.conf

hot_standby = on


hot_standby改為啟用狀態

3. 接下來可以啟動從庫了

[root@DB tmp]# /etc/init.d/postgresql start
Starting PostgreSQL: -bash: /home/postgres/pgsql/data/serverlog: Permission denied
ok


第一次啟動報錯,這是因為上面生成備份的命令我使用root用戶執行的,導致PG家目錄的屬性變成了root,所以要重新設置權限

chown -R postgres:postgres /home/postgres/pgsql/*


再次啟動正常,查看進程也OK

[root@DB tmp]# /etc/init.d/postgresql start
Starting PostgreSQL: ok
[root@DB tmp]# ps -ef | grep postg
root      52577  82731  0 15:12 pts/0    00:00:00 su - postgres
postgres  52578  52577  0 15:12 pts/0    00:00:00 -bash
postgres  74295      1  0 20:01 ?        00:00:00 /home/postgres/pgsql/bin/postmaster -D /home/postgres/pgsql/data
postgres  74296  74295  0 20:01 ?        00:00:00 postgres: startup process   recovering 000000010000000000000003 
postgres  74297  74295  5 20:01 ?        00:00:00 postgres: wal receiver process   streaming 0/3000140            
postgres  74298  74295  0 20:01 ?        00:00:00 postgres: checkpointer process                                  
postgres  74299  74295  0 20:01 ?        00:00:00 postgres: writer process                                        
postgres  74300  74295  0 20:01 ?        00:00:00 postgres: stats collector process


五、結果驗證

1. 在主庫通過select usename,application_name,client_addr,state from pg_stat_replication查詢一下:

[postgres@MidApp ~]$ psql 
psql (9.6.6)
Type "help" for help.
 
postgres=# select usename,application_name,client_addr,state from pg_stat_replication;
 usename  | application_name |   client_addr   |   state   
----------+------------------+-----------------+-----------
 repluser | standby01        | 192.168.221.160 | streaming
(1 row)
 
postgres=#


可以看到192.168.221.160上的repluser在通過流復制的方式同步主庫的數據

2. 創建表驗證一下

主庫上建表,並插入數據驗證

postgres=# create table test01(id int primary key,note text);
CREATE TABLE
postgres=# \d
         List of relations
 Schema |  Name  | Type  |  Owner   
--------+--------+-------+----------
 public | test01 | table | postgres
(1 row)
 
postgres=# insert into test01 values(1,'1111111');
INSERT 0 1
postgres=# select * from test01;
 id |  note   
----+---------
  1 | 1111111
(1 row)


在從庫上查看:

[postgres@DB data]$ psql 
psql (9.6.6)
Type "help" for help.
 
postgres=# \d
         List of relations
 Schema |  Name  | Type  |  Owner   
--------+--------+-------+----------
 public | test01 | table | postgres
(1 row)
 
postgres=# select * from test01;
 id |  note   
----+---------
  1 | 1111111
(1 row)


嘗試插入數據看一下:

postgres=# insert into test01 values(2,'2222222');
ERROR:  cannot execute INSERT in a read-only transaction


可以看到,從庫可以查看從主庫同步過來的數據,但並不能寫數據。

六、總結

以上是搭建Postgresql主從同步的全過程,一路踩了好多坑,記錄下了,希望能幫助到別人


PostgreSql基於Standby的異步流主從復制