postgresql + pgpool 構建容災高可用集群(數據同步流復制/主備自動切換)
本篇主要是postgresql12 安裝配置部分。
pgpool-ii 配置在第二篇:pgpool-ii4.1.2 高可用集群[主備切換]配置部分
整個流程分為以下幾部分:
- postgresql-12 安裝
- postgresql-12 流復制配置以及驗證
- pgpoll-ii-4.1 安裝
- pgpool-ii-4.1 主備機器自動切換配置
- pgpoll-ii-4.1 配置說明
- 方案宕機效果測試
高可用(容災)效果:
先說說這套方案要達到的效果/解決的問題,目的不一致的/沒有想了解的可以不用往下看了.
解決三種宕機
- 某一個 postgresql 數據庫掛掉 (多台數據庫啟動后 其中一台作為主機,其余作為備機 構成一個
數據庫集群
);- 如果是主機primary,集群檢測到掛掉會通過配置的策略重新選一個備機standby切換為主機primary, 整個集群仍舊保證可用, 當原主機恢復服務后, 重新作為一個新備機standby,同步完數據后加入集群
- 如果是備機standby,對整個集群無可見影響, 當備機恢復服務后,從主庫同步完數據后,恢復正常狀態加入集群;
- 某一台機器上的pgpool-ii 程序掛掉;
- 監測每個pgpool-ii進程的狀態, 監測到掛掉之后,及時"切換"虛擬ip所在的主機以保證可用性(有些人叫IP漂移);
- 整個集群始終對外提供一個唯一的,可用的虛擬IP 來提供訪問;
- 監測每個主機postgresql數據庫的狀態, 以即使切換數據庫的主備角色;
- 某一台主機直接宕機;
- 當pgpool-ii監測主機掛掉之后, 需要進行數據庫角色的切換和ip的切換兩個操作(如果需要)
方案結構:
基於兩台裝有postgresql數據庫的服務器,通過每台機器上的pgpool-ii程序來維護一個高可用體系, 從而保證能始終提供一個可用的IP地址
,用於外界數據操作或者訪問
.
發行版 | ip | hostname | 補充說明 |
---|---|---|---|
Cent OS7 | 10.242.111.204 | master | 安裝postgresql 12.1 + pgpool-ii 4.1 並進行配置 |
Cent OS7 | 10.242.111.207 | slave | 安裝postgresql 12.1 + pgpool-ii 4.1 並進行配置 |
/ | 10.242.111.203 | vip | virtual ip, 通過一個虛擬的IP統一對外提供訪問 |
- 2(n)台主機均安裝有
postgresql 12
版本的數據庫和pgpool-ii 4.1
版本的中間件; - 2(n)個數據庫之間可以做到數據同步以(通過流復制來實現, 但同一時刻主機primary只有一台,其余作為備機standby)及
身份切換
; - pgpool-ii 是一個介於postgresql 服務器和postgresql數據庫之間的中間件, 提供了
鏈接池(Connection Pooling)
,看門狗(WatchDog)
,復制
,負載均衡
,緩存
等功能(具體的可以查看官方文檔); - 通過pgpool-ii 維護的虛擬ip, 向外界提供一個始終可用的訪問地址, 屏蔽掉具體的
主機數據庫
地址概念; - 通過pgpool-ii 程序來自動處理宕機后相關方案(后面有講)
- 數據庫down之后需要通過
pcp_attach_node
將節點加入集群
流復制數據同步: 通過postgresql數據庫配置來實現
虛擬ip自動切換: 通過pgpool-ii 配置實現
數據庫主備角色切換: 通過pgpool-ii 監測機 + 執行 postgresql 中的promote
命令來實現
postgreslq-12安裝(2台機器均安裝)
yum 在線安裝
#設置rpm源
curl -O https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
rpm -ivh pgdg-redhat-repo-latest.noarch.rpm
#安裝(這里是版本為12的postgresql)
yum -y install postgresql12 postgresql12-server -O
#如果后續發現連接不上,可以關閉防火牆
systemctl stop firewalld
systemctl disable firewalld
rpm
離線安裝
# ftp下載rpm離線包
curl -O https://yum.postgresql.org/12/redhat/rhel-7-x86_64/postgresql12-12.3-1PGDG.rhel7.x86_64.rpm
curl -O https://yum.postgresql.org/12/redhat/rhel-7-x86_64/postgresql12-contrib-12.3-1PGDG.rhel7.x86_64.rpm
curl -O https://yum.postgresql.org/12/redhat/rhel-7-x86_64/postgresql12-libs-12.3-1PGDG.rhel7.x86_64.rpm
curl -O https://yum.postgresql.org/12/redhat/rhel-7-x86_64/postgresql12-server-12.3-1PGDG.rhel7.x86_64.rpm
#contrib 是安裝擴展的 沒有這個包就沒有 ossp-uuid的插件
#server 是數據庫的安裝文件
#libs 用來客戶端進行連接.
#注意 如果是centos8 的話,修改為 rhel-8 進行下載就可以了.
# 上傳文件到服務器之后, 執行安裝命令
rpm -ivh postgresql*.rpm
執行完安裝之后(查看狀態可跳過, 直接進行數據庫初始化):
- 會幫我們創建一個
postgresql-12
服務, 此時未進行數據庫初始化, 還無法訪問. - 會幫我們創建一個
postgres
/postgres
的用戶,密碼相同.
此時使用systemctl status postgreslq-12
查看服務狀態:
● postgresql-12.service - PostgreSQL 12 database server
Loaded: loaded (/usr/lib/systemd/system/postgresql-12.service; disabled; vendor preset: disabled)
Active: inactive (dead)
Docs: https://www.postgresql.org/docs/12/static/
我們可以找到默認配置文件地址: /usr/lib/systemd/system/postgresql-12.service
如果cat
命令查看配置文件, 我們可以得到一些基礎信息:
數據庫數據目錄
: Environment=PGDATA=/var/lib/pgsql/12/data/
postgresql安裝目錄
: PGHOME=/usr/pgsql-12/
數據庫初始化
# 切換到postgres用戶
su - postgres
cd /usr/pgsql-12/bin
./initdb -D /var/lib/pgsql/12/data
**退回root用戶, 重啟postgrersql-12
服務, 並設置開機自啟 **
systemctl enable postgresql-12 && systemctl restart postgresql-12
**本機測試訪問 **
su - postgres
-bash-4.2$ psql
postgres=# (這里就可以開始寫查詢語句了)
**配置遠程訪問 **
修改數據目錄下配置文件: pg_hba.conf
vim /var/lib/pgsql/12/data/pg_hba.conf
# 在文件中添加:
host all all 0.0.0.0/0 md5
修改數據目錄下配置文件: postgresql.conf
vim /var/lib/pgsql/12/data/postgresql.conf
# 在文件中修改(此配置僅用於遠程訪問, 流復制后續還有額外配置):
listen_addresses = '*'
port = 5432
max_connections = 100
修改完成重啟服務, 使用遠程命令或者遠程客戶端測試訪問即可
-- 使用遠程命令訪問
psql -h 10.242.111.204 -p 5432 -U postgres
-- 登陸成功可以執行操作
-- 如修改密碼 (引號中為新密碼)
postgres=# alter role postgres with password 'postgres';
postgresql-12 流復制(replication)/數據同步配置
流復制原理簡述
-
流復制大約是從pg9版本之后使用, 流復制其原理為:備庫不斷的從主庫同步相應的數據,並在備庫apply每個WAL record,這里的流復制每次傳輸單位是WAL日志的record。(關於預寫式日志WAL,是一種事務日志的實現)
-
圖中可以看到流復制中日志提交的大致流程為:
- 事務commit后,日志在主庫寫入wal日志,還需要根據配置的日志同步級別,等待從庫反饋的接收結果。
- 主庫通過日志傳輸進程將日志塊傳給從庫,從庫接收進程收到日志開始回放,最終保證主從數據一致性。
-
流復制同步級別
通過在postgresql.conf
配置synchronous_commit
參數來設置同步級別synchronous_commit = off # synchronization level; # off, local, remote_write, or on
- remote_apply:事務commit或rollback時,等待其redo在primary、以及同步standby(s)已持久化,並且其redo在同步standby*(s)已apply。
- on:事務commit或rollback時,等待其redo在primary、以及同步standby(s)已持久化。
- remote_write:事務commit或rollback時,等待其redo在primary已持久化; 其redo在同步standby(s)已調用write接口(寫到 OS, 但是還沒有調用持久化接口如fsync)。
- local:事務commit或rollback時,等待其redo在primary已持久化;
- off:事務commit或rollback時,等待其redo在primary已寫入wal buffer,不需要等待其持久化;
配置時需要注意的點:
- postgresql-12版本不再支持通過recovery.conf的方式進行主備切換,如果數據目錄中存在recovery.conf,則數據庫無法啟動;
- 新增 recovery.signal 標識文件,表示數據庫處於 recovery 模式;
- 新增加 standby.signal 標識文件,表示數據庫處於 standby 模式(這個需要重點關注一下);
- 以前版本中 standby_mode 參數不再支持;
- recovery.conf文件取消, 合並到了
postgresql.conf
文件中; - 配置中
war_level
存儲級別, postgresql-9.6以后有改變:等級 說明 minimal 不能通過基礎備份和wal日志恢復數據庫 replica 9.6新增,將之前版本的 archive 和 hot_standby合並, 該級別支持wal歸檔和復制 logical 在replica級別的基礎上添加了支持邏輯解碼所需的信息
流復制配置過程
主庫(10.242.111.204)
- 創建一個賬戶
repuser
用戶, 提供給備庫遠程訪問, 用來獲取流:su - postgres -bash-4.2$ psql postgres=# create role repuser login replication encrypted password 'repuser'; CREATE ROLE postgres=# \q
- 修改數據目錄下配置文件:
pg_hba.conf
vim /var/lib/pgsql/12/data/pg_hba.conf # 在文件中添加: host replication repuser 0.0.0.0/0 md5
- 修改數據目錄下配置文件:
postgresql.conf
vim /var/lib/pgsql/12/data/postgresql.conf # 在文件中修改(此配置僅用於遠程訪問, 流復制后續還有額外配置): listen_addresses = '*' port = 5432 max_connections = 100 # 最大連接數,據說從機需要大於或等於該值 # 控制是否等待wal日志buffer寫入磁盤再返回用戶事物狀態信息。同步流復制模式需要打開。 synchronous_commit = on # *=all,意思是所有slave都被允許以同步方式連接到master,但同一時間只能有一台slave是同步模式。 # 另外可以指定slave,將值設置為slave的application_name即可。 synchronous_standby_names = '*' wal_level = replica max_wal_senders = 2 #最多有2個流復制連接 wal_keep_segments = 16 wal_sender_timeout = 60s #流復制超時時間
修改完成重啟postgresql-12服務systemctl restart postgresql-12
從庫(10.242.111.204)
- 關閉備庫postgresql服務
systemctl stop postgresql-12
- 如果備庫機器上沒有 PGDATA(/var/lib/pgsql/12/data)目錄(恢復出故障數據目錄消失同樣操作)
mkdir /var/lib/pgsql/12/data chmod 0700 data chown postgres.postgres data
- 把主庫整個備份到從庫
其實后續的pgpool的主庫掛了, 從庫升級主庫之后, 主庫恢復為從庫的過程就是: 備份data目錄,然后重復這里的第2,3步驟
額外需要注意的是:# 切換到postgres用戶,否則備份的文件屬主為root, 導致啟動出錯 su – postgres pg_basebackup -h 10.242.111.204 -p 5432 -U repuser -Fp -Xs -Pv -R -D /var/lib/pgsql/12/data # -h 的ip是當前的主庫, -U 就是前面個船艦的用來復制的那個用戶
- 如果主庫的pg_hba.conf中配置的策略為trust, 這里不需要口令, 如果為md5模式,需要輸你創建用戶時的那個密碼;
- 這里 -R 參數一定要加, 拷貝完在$PGDATA目錄下生成standby.signal標志文件(用於表示此庫為備庫);
- 使用命令同步完之后, 在data目錄下會自動生成
postgresql.auto.conf
文件中, 優先級是大於postgresql.conf的; - 這里面的參數請嚴格參照官網釋義;
- 啟動備庫postgresql-12 服務
systemctl restart postgresql-12
流復制驗證
使用命令或者遠程客戶端工具登入postgresql主(primary)數據庫
# 切換垂直顯示
postgres=# \x
Expanded display is on.
# 查詢備機連接
postgres=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 27132
usesysid | 16384
usename | repuser
application_name | walreceiver
client_addr | 10.242.111.207
client_hostname |
client_port | 34726
backend_start | 2020-06-19 16:23:01.309172+08
backend_xmin |
state | streaming
sent_lsn | 0/11000148
write_lsn | 0/11000148
flush_lsn | 0/11000148
replay_lsn | 0/11000148
write_lag |
flush_lag |
replay_lag |
sync_priority | 1
sync_state | sync
reply_time | 2020-06-19 18:39:43.346062+08
# 可以發現207的那台備機已經連接上, 並且使用的是 sync 同步模式(async 為異步)
# 此時可以在主庫上創建數據庫/表/添加數據, 然后去備庫上查詢 以顯示效果, 如:
postgres=# create database test_204;
postgres=# \test_204
postgres=# create table test_table(name text);
postgres=# insert into test_table(name) values ('china');
# 補充基礎查詢命令
# \list 列出可用數據庫
# \db_name 選擇數據庫
# \dt 查詢關系表
至此, 流復制(數據同步)策略完成.
postgresql 主從切換(primary->standby)
- 主數據庫是讀寫的,備數據庫是只讀的。
- 使用
/usr/pgsql-12/bin/pg_controldata /var/lib/pgsql/12/data/
可以查看數據庫運行狀態- Database cluster state: in production (主庫為運行中)
- Database cluster state: in archive recovery (從庫為正在歸檔回復)
- 當主庫primary 出現故障, 我們需要將從庫standby提升為主庫primary;
- pg12版本以前的切換方式有兩種:
- pg_ctl 方式: 在備庫主機執行 pg_ctl promote shell 腳本
- 觸發器文件方式: 備庫配置 recovery.conf 文件的 trigger_file 參數,之后在備庫主機上創建觸發器文件
- pg12開始新增了一個
pg_promote()
函數, 支持知用promote指令進行切換 pg_promote(wait boolean DEFAULT true, wait_seconds integer DEFAULT 60)
- wait: 表示是否等待備庫的 promotion 完成或者 wait_seconds 秒之后返回成功,默認值為 true
- wait_seconds: 等待時間,單位秒,默認 6
- pg12版本以前的切換方式有兩種:
- 切換舉例
# 關閉主庫primary systemctl stop postgresql-12 # 從庫上執行切換 # 第一種 /usr/pgsql-12/bin/pg_ctl promote -D /var/lib/pgsql/12/data # 第三種 su postgres psql postgres=# select pg_promote(true,60); # 此時從庫會提升為主庫接管集群中的讀寫操作
pgpool-ii 中默認的 failover_command 切換數據庫主備角色腳本, 是通過pg_ctl promote
來實現的
后續pgpool操作見下一篇文章
參考資料: