1. 程式人生 > 其它 >基於docker容器的Postgresql 11主從複製搭建 及切換

基於docker容器的Postgresql 11主從複製搭建 及切換

基於docker容器的Postgresql 11主從複製搭建 及切換

1、背景

由於新專案要用到postgresql,且要求高可用功能,因此做可行性測試研究,並記錄過程,以備查。
映象採用官方postgresl11映象,本地映象只是為了加快部署進度.並無特殊之處。
首次應用,難免有疏漏錯誤之處,歡迎批評指正。

2、環境

192.168.200.153 部署主資料庫

資料盤掛載在 /home目錄

192.168.205.72 部署從資料庫

資料盤掛載在 /data目錄

3、安裝部署

3.1 主伺服器

利用 docker 搭建 postgres 伺服器

mkdir -p  /home/postgresql/data
docker run --name test_pg --restart=always  -v /home/postgresql/data:/var/lib/postgresql/data -e POSTGRES_PASSWORD=123456 -p 5432:5432 -d 192.168.200.153:5000/test_pg:0.2

-v : 建立資料卷,將 docker 內的檔案系統掛載到宿主機上, linux 目錄:/home/postgresql/data, docker 容器對應的路徑 /var/lib/postgresql/data

    1. 進入啟動的 docker 容器內部
docker exec -it test_pg /bin/bash
    1. 進入 postgres 客戶端,新建用於同步資料的使用者
# 切換到 postgres 使用者

su postgres

# 進去 postgres 客戶端

psql

進入 postgres 客戶端

CREATE ROLE replica login replication encrypted password 'replica';

注:注意語句最後新增分號
建立使用者成功之後,控制檯會顯示 “CREATE ROLE”,利用 \du 命令可以檢視 postgres 的使用者列表

postgres=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of 
-----------+------------------------------------------------------------+-----------
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 replica   | Replication                                                | {}

檢視使用者列表

通過 \q 退出 postgres 控制檯,並通過 exit 退出 postgres 使用者

    1. 修改 pg_hba.conf 檔案

修改 pg_hba.conf 檔案,允許剛建立的 replica 使用者從 192.168.205.72 從伺服器上連線主伺服器。

vi /var/lib/postgresql/data/pg_hba.conf

vi 未安裝

如上顯示 vi 命令沒有安裝,通過如下命令進行安裝

apt-get update
apt-get install vim

安裝成功之後,再次修改 pg_hba.conf 檔案,進入最後部分,新增如下:

host   replication      replica       192.168.205.72/32          trust   #允許  205.72 機器使用 replica 使用者來複制
    1. 修改 postgresql.conf
listen_addresses = '*'   # 監聽所有IP
archive_mode = on  # 允許歸檔
archive_command = '/bin/date' # 用該命令來歸檔logfile segment,這裡取消歸檔。
wal_level = replica #開啟熱備
max_wal_senders = 32 # 這個設定了可以最多有幾個流複製連線,差不多有幾個從,就設定幾個
wal_keep_segments = 64 # 設定流複製保留的最多的xlog數目,一份是 16M,注意機器磁碟 16M*64 = 1G
wal_sender_timeout = 60s # 設定流複製主機發送資料的超時時間
max_connections = 200 # 這個設定要注意下,從庫的max_connections必須要大於主庫的
    1. 重啟容器
      通過 exit 命令退出容器,並重啟啟動容器
docker restart test_pg

從伺服器

    1. 啟動從節點資料庫:
mkdir -p /data/postgresql/data
docker run --name test_pg --restart=always  -v /data/postgresql/data:/var/lib/postgresql/data -e POSTGRES_PASSWORD=123456 -p 5432:5432 -d 192.168.200.153:5000/test_pg:0.2
  • 2 通過 docker exec -it test_pg /bin/bash 進入容器內部,拷貝主伺服器資料進入從節點容器並同步(注意按實際情況修改master節點ip地址)
docker exec -it test_pg /bin/bash 
su postgres
rm -rf /var/lib/postgresql/data/*
pg_basebackup -h 192.168.200.153 -U replica -D /var/lib/postgresql/data -X stream -P

執行完上述命令之後,容器自動退出

切換到宿主機的 root 賬戶,進入 /data/postgresql/data目錄。

    1. 新增 recovery.conf 檔案
      通過 vi /data/postgresql/data/recovery.conf新增恢復檔案 (注意按實際情況修改master節點ip地址)。
cd /data/postgresql/data

vi recovery.conf

standby_mode = on
primary_conninfo = 'host=192.168.200.153 port=5432 user=replica password=replica'
recovery_target_timeline = 'latest'
  • 4.修改 postgresql.conf

vi /data/postgresql/data/postgresql.conf

wal_level = replica
max_connections = 1000
hot_standby = on
max_standby_streaming_delay = 30s
wal_receiver_status_interval = 10s 
hot_standby_feedback = on
    1. 啟動容器
      執行docker ps -a
      如果 test_pg容器已經啟動
      則先執行:
docker stop test_pg

否則
通過 docker start test_pg再次啟動容器

4. 校驗主從部署

  • 驗證方法一:
    到 192.168.200.153 主伺服器地址上校驗主從是否部署成功
    通過 docker exec -it test_pg /bin/bash 進入容器內部
su postgres
psql

通過上訴命令進入 postgres 控制檯,然後執行:

select client_addr,sync_state from pg_stat_replication;

得到如下結果:

postgres=# select client_addr,sync_state from pg_stat_replication;
  client_addr   | sync_state 
----------------+------------
 192.168.205.72 | async
(1 row)

主從配置成功

  • 驗證方法二:

主庫上:

postgres@be0f0d5e17f9:/$ ps -ef | grep wal
postgres    50    28  0 14:03 ?        00:00:00 postgres: walwriter  
postgres  8760    28  0 16:04 ?        00:00:00 postgres: walsender replica 192.168.205.72(35476) streaming 0/B000060
postgres 13535 11320  0 16:44 pts/0    00:00:00 grep wal

備庫上:

root@61e3c16652eb:/#  ps -ef | grep wal
postgres    51    28  0 16:01 ?        00:00:01 postgres: walreceiver  
root        91    82  0 16:44 pts/0    00:00:00 grep wal

5.測試同步狀態

當然,穩妥起見,嘗試在主庫上建立並插入資料,觀察備庫上是否同步這些操作,我們再主庫上建立一張表:

postgres=# create table test_ms(id int4);

CREATE TABLE

postgres=# insert into test_ms values(6);

INSERT 0 1

主庫上,我們建立test_ms表,並插入了一條資料,我們就可以在備庫上進行查詢觀察是否同步成功:

postgres=# select * from test_ms;
 id
----
 6
(1 row)

接下來,我們再主庫上,再操作

postgres=# insert into test_ms values(9);
INSERT 0 1

postgres=# delete from test_ms where id=6;
DELETE 1

這個時候,我們發現備庫的資料也都正常同步上了:

postgres=# select * from test_ms;
 id
----
 9
(1 row)

那麼我們如果在備份上進行資料操作,情況會怎樣呢?我們再備份上執行:

postgres=# insert into test_ms values(6);

ERROR: cannot execute INSERT in a read-only transaction
STATEMENT: insert into test_ms values(6);
ERROR: cannot execute INSERT in a read-only transaction

觀察這些錯誤日誌,我們可以瞭解到,非同步流主從結構中,作為從節點的備庫目前處於的是隻讀狀態,它不能進行任何寫入操作。

6. 主備切換測試

    1. 在主伺服器上執行
docker stop test_pg;

關閉主庫

    1. 在備庫上執行pg_ctl promote命令**備庫,如果recovery.conf變成recovery.done表示備庫已切換成主庫
docker exec -it test_pg /bin/bash 
su postgres
/usr/lib/postgresql/11/bin/pg_ctl promote -D $PGDATA promote -D $PGDATA
waiting for server to promote.... done
server promoted

命令執行後,如果原來的 recovery.conf 更名為 recovery.done, 表示切換成功

    1. 這時如果需要將老的主庫切換成備庫,在老的主庫的$PGDATA目錄下也建立recovery.conf檔案(建立方式跟之前介紹的一樣,內容可以和原從庫pghost2的一樣,只是primary_conninfo的IP換成對端pghost2的IP)

例如,主庫上的 recovery.conf 設定為:

recovery_target_timeline = 'latest'
standby_mode = on
primary_conninfo = 'host=192.168.205.72 port=5432 user=replica password=replica'
    1. 啟動老的主庫pghost1,這時觀察主、備進行是否正常,嚴格點可以在新的主庫上對剛才的test_ms表進行操作,觀察資料是否同步成功。

pg_ctl start
我們在新主庫(pghost2)上執行:

postgres=# select pg_is_in_recovery();
 pg_is_in_recovery
-------------------
 f
(1 row)

發現它目前的角色已經是主庫了, 在新備庫(pghost1)上繼續執行:

postgres=# select pg_is_in_recovery();
 pg_is_in_recovery
-------------------
 t
(1 row)

發現它目前的角色也已經切換為備庫了

我們再pghost2上,執行資料插入操作:

postgres=# insert into test_ms values(11);
INSERT 0 1

這時,pghost1上也觀察到資料同步成功:

postgres=# select * from test_ms;
 id
----
 9
 11
(2 rows)

到這裡為止,主從切換的演練基本完成了
參考文件:
https://www.codeleading.com/article/6741340817/
基於 docker 的 postgres 主從流複製部署
Postgresql主從非同步流複製方案的深入探究