PostgreSQL主從流復(fù)制的完整部署指南
引言
數(shù)據(jù)庫(kù)高可用這件事,做與不做,差別在于:做了一切正常時(shí)可能覺(jué)得多余,但出問(wèn)題的時(shí)候你會(huì)慶幸它還在。PostgreSQL 從 9.0 版本開(kāi)始原生支持流復(fù)制機(jī)制,主從架構(gòu)部署成熟穩(wěn)定,配置鏈路清晰,是中小企業(yè)搭建數(shù)據(jù)庫(kù)高可用方案的首選路徑之一。
流復(fù)制的原理不復(fù)雜:主庫(kù)產(chǎn)生 WAL 日志,通過(guò)流復(fù)制協(xié)議實(shí)時(shí)推送給從庫(kù),從庫(kù)接收后重放日志完成數(shù)據(jù)同步。主庫(kù)故障時(shí),從庫(kù)可以快速提升為主庫(kù)繼續(xù)提供服務(wù),整個(gè)切換過(guò)程業(yè)務(wù)中斷時(shí)間可以控制在分鐘級(jí)別甚至更短。這套機(jī)制不依賴第三方工具,原生集成在 PostgreSQL 本身,維護(hù)成本低,文檔充分,遇到問(wèn)題容易排查。
具體落地需要關(guān)心的細(xì)節(jié)不少:postgresql.conf 和 pg_hba.conf 的參數(shù)怎么調(diào)、主庫(kù)備份用什么工具、復(fù)制槽怎么保證穩(wěn)定、復(fù)制延遲怎么看、故障切換的步驟是什么。本文以 PostgreSQL 14 為例,覆蓋從環(huán)境規(guī)劃、主從配置到復(fù)制驗(yàn)證和故障轉(zhuǎn)移的完整閉環(huán),幫你在真實(shí)環(huán)境中把主從流復(fù)制跑通。硬件需求不挑,兩臺(tái)普通服務(wù)器加千兆網(wǎng)絡(luò)就能跑起來(lái),適合有一定 Linux 操作基礎(chǔ)的技術(shù)團(tuán)隊(duì)落地實(shí)施。
本文將摒棄空泛理論,以CentOS/Ubuntu 環(huán)境下的PostgreSQL 14為例,手把手帶你完成從零搭建、配置調(diào)優(yōu)到故障演練的完整流程。無(wú)論你是DevOps工程師、DBA,還是希望提升系統(tǒng)容災(zāi)能力的開(kāi)發(fā)者,都能通過(guò)本指南,真正掌握PostgreSQL高可用的核心實(shí)踐。
讓數(shù)據(jù)多一份副本,讓服務(wù)少一分風(fēng)險(xiǎn)。
從今天起,告別單點(diǎn)故障,構(gòu)建屬于你的高可用數(shù)據(jù)庫(kù)基石。
1.環(huán)境準(zhǔn)備
1.1 基礎(chǔ)環(huán)境要求
| 節(jié)點(diǎn)類型 | 服務(wù)器地址 | 系統(tǒng)版本 | PostgreSQL 版本 | 核心要求 |
|---|---|---|---|---|
| 主庫(kù)(Master) | 192.168.42.140(示例) | CentOS 7/8/9或Ubuntu 20.04+ | 14 | 開(kāi)啟網(wǎng)絡(luò)端口、關(guān)閉防火墻 / 放行5432端口 |
| 從庫(kù)(Slave/Standby) | 192.168.42.145(示例) | 與主庫(kù)一致 | 與主庫(kù)完全一致 | 與主庫(kù)網(wǎng)絡(luò)互通、磁盤(pán)空間不小于主庫(kù) |
1.2 安裝PostgreSQL
還沒(méi)安裝PostgreSQL的小伙伴可以去cpolar官網(wǎng)參考《誰(shuí)說(shuō)沒(méi)公網(wǎng)IP不能遠(yuǎn)程連數(shù)據(jù)庫(kù)?PostgreSQL+cpolar打通任督二脈》這篇文章哦~
2.配置教程
2.1 修改PostgreSQL主配置文件
主配置文件路徑:/var/lib/pgsql/14/data/postgresql.conf
vim /var/lib/pgsql/14/data/postgresql.conf
修改以下核心參數(shù)(取消注釋并調(diào)整值):
# 1. 監(jiān)聽(tīng)地址(允許從庫(kù)連接,可指定從庫(kù)IP或0.0.0.0允許所有) listen_addresses = '*' # 2. 開(kāi)啟歸檔模式(主從復(fù)制依賴) archive_mode = on archive_command = 'cp %p /var/lib/pgsql/14/archive/%f' # %p=歸檔文件路徑,%f=歸檔文件名 # 提前創(chuàng)建歸檔目錄 mkdir -p /var/lib/pgsql/14/archive && chown -R postgres:postgres /var/lib/pgsql/14/archive # 3. WAL日志配置(保證復(fù)制可靠性) wal_level = replica # 復(fù)制所需的WAL級(jí)別(replica/archive/logical,replica足夠) wal_buffers = 16MB # 根據(jù)內(nèi)存調(diào)整,默認(rèn)通常足夠 max_wal_senders = 10 # 最大并發(fā)復(fù)制連接數(shù),大于從庫(kù)數(shù)量即可 wal_keep_size = 1GB # 保留WAL日志的大小,防止從庫(kù)同步滯后導(dǎo)致日志被清理 # 4. 同步模式(可選,按需配置) # synchronous_commit = on # 默認(rèn)同步提交,保證主從數(shù)據(jù)一致性;追求性能可設(shè)為off # synchronous_standby_names = 'slave1' # 指定從庫(kù)名稱(需與從庫(kù)recovery.conf對(duì)應(yīng)) # 5. 其他優(yōu)化(可選) max_connections = 1000 # 大于從庫(kù)的max_connections
![]()

2.2 修改客戶端認(rèn)證配置文件
文件路徑:/var/lib/pgsql/14/data/pg_hba.conf
vim /var/lib/pgsql/14/data/pg_hba.conf
添加從庫(kù)的連接授權(quán)(允許從庫(kù) IP 通過(guò)復(fù)制用戶連接):
host replication repl_user 192.168.42.145/32 md5 # 從庫(kù)IP,repl_user為復(fù)制專用用戶 host all all 192.168.42.0/24 md5 # 可選,允許內(nèi)網(wǎng)其他機(jī)器連接

2.3 創(chuàng)建復(fù)制專用用戶
切換到postgres用戶,執(zhí)行 SQL 命令創(chuàng)建用于主從復(fù)制的專用用戶(需授予復(fù)制權(quán)限):
su - postgres psql
執(zhí)行SQL:
-- 創(chuàng)建復(fù)制用戶(密碼自定義,示例:Repl@123456) CREATE ROLE repl_user WITH REPLICATION LOGIN ENCRYPTED PASSWORD '********'; -- 驗(yàn)證用戶(可選) \du repl_user; -- 退出psql \q

2.4 重啟主庫(kù)使配置生效
systemctl restart postgresql-14 systemctl status postgresql-14 sudo -u postgres psql -c "SELECT pg_is_in_recovery();" # 主庫(kù)返回f(非恢復(fù)模式)

2.5 備份主庫(kù)數(shù)據(jù)(供從庫(kù)初始化)
使用pg_basebackup工具備份主庫(kù)數(shù)據(jù),該工具專門(mén)用于PostgreSQL復(fù)制環(huán)境的從庫(kù)初始化:
# 切換到postgres用戶 su - postgres # 執(zhí)行備份(備份到臨時(shí)目錄,后續(xù)拷貝到從庫(kù)) pg_basebackup -h 192.168.42.140 -U repl_user -p 5432 -D /tmp/pg_master_backup -F p -X s -P -R # 參數(shù)說(shuō)明: # -h:主庫(kù)地址 # -U:復(fù)制用戶 # -p:主庫(kù)端口 # -D:備份目錄 # -F p:輸出格式為普通文件(與主庫(kù)數(shù)據(jù)目錄結(jié)構(gòu)一致) # -X s:備份過(guò)程中同步復(fù)制WAL日志,保證備份一致性 # -P:顯示備份進(jìn)度 # -R:自動(dòng)生成復(fù)制所需的standby.signal文件和postgresql.auto.conf配置,簡(jiǎn)化從庫(kù)配置

備份完成后,將備份目錄打包拷貝到從庫(kù)的/var/lib/pgsql/14/目錄下(可通過(guò) scp 傳輸):
tar -zcvf pg_master_backup.tar.gz /tmp/pg_master_backup # 主庫(kù)上打包備份
scp pg_master_backup.tar.gz root@192.168.1.101:/var/lib/pgsql/14 # 傳輸?shù)綇膸?kù)

![]()
到從庫(kù)所在地址查看一下是否傳送成功到/var/lib/pgsql/14:
![]()
3.從庫(kù)配置
3.1 停止從庫(kù)PostgreSQL服務(wù)并清理原有數(shù)據(jù)目錄
# 停止從庫(kù)服務(wù) systemctl stop postgresql-14 # 清理原有數(shù)據(jù)目錄(初始化后的空目錄,需替換為主庫(kù)備份) mv /var/lib/pgsql/14/data /var/lib/pgsql/14/data_bak # 備份原有目錄,防止誤刪 mkdir -p /var/lib/pgsql/14/data

3.2 解壓主庫(kù)備份到從庫(kù)數(shù)據(jù)目錄
# 切換到postgres用戶 su - postgres # 解壓備份包 tar -zxvf /var/lib/pgsql/14/pg_master_backup.tar.gz -C /var/lib/pgsql/14/ # 移動(dòng)備份數(shù)據(jù)到data目錄 mv /var/lib/pgsql/14/tmp/pg_master_backup/* /var/lib/pgsql/14/data/ # 修改目錄權(quán)限(必須為postgres用戶和組) chown -R postgres:postgres /var/lib/pgsql/14/data chmod 700 /var/lib/pgsql/14/data


3.3 驗(yàn)證 / 修改從庫(kù)復(fù)制配置
由于主庫(kù)備份時(shí)使用了-R參數(shù),會(huì)自動(dòng)生成standby.signal(標(biāo)識(shí)從庫(kù)身份)和postgresql.auto.conf(包含復(fù)制連接信息),無(wú)需手動(dòng)創(chuàng)建:
# 查看自動(dòng)生成的復(fù)制配置 cat /var/lib/pgsql/14/data/postgresql.auto.conf ls /var/lib/pgsql/14/data/

若沒(méi)有,則手動(dòng)創(chuàng)建standby.signal并修改postgresql.conf:
# 手動(dòng)創(chuàng)建standby.signal(標(biāo)識(shí)為從庫(kù)) touch /var/lib/pgsql/14/data/standby.signal # 編輯postgresql.conf,添加復(fù)制配置,添加以下參數(shù): vim /var/lib/pgsql/14/data/postgresql.conf # 從庫(kù)專屬配置 hot_standby = on # 允許從庫(kù)處于恢復(fù)模式時(shí)提供查詢服務(wù)(只讀) max_connections = 500 # 小于主庫(kù)的max_connections primary_conninfo = 'user=repl_user password=Repl@123456 host=192.168.42.140 port=5432' # 主庫(kù)連接信息
3.4 啟動(dòng)從庫(kù)服務(wù)
# 啟動(dòng)從庫(kù) systemctl start postgresql-14 systemctl enable postgresql-14 # 驗(yàn)證從庫(kù)狀態(tài) systemctl status postgresql-14
4.驗(yàn)證主從復(fù)制是否生效
4.1 主庫(kù)驗(yàn)證復(fù)制狀態(tài)
su - postgres psql # 查看復(fù)制連接狀態(tài)(可看到從庫(kù)的連接信息) SELECT * FROM pg_stat_replication; # 輸出說(shuō)明: # - usename:repl_user(復(fù)制用戶) # - client_addr:192.168.1.101(從庫(kù)IP) # - state:streaming(表示正在流式復(fù)制) # - sync_state:async(異步復(fù)制)或 sync(同步復(fù)制,需主庫(kù)配置synchronous_commit=on)

從提供的pg_stat_replication查詢結(jié)果來(lái)看,PostgreSQL主從復(fù)制已經(jīng)成功建立,并且處于正常運(yùn)行狀態(tài)。這是一個(gè)非常關(guān)鍵的監(jiān)控視圖,用于查看 主庫(kù)上的復(fù)制連接狀態(tài)。
4.2 從庫(kù)驗(yàn)證復(fù)制狀態(tài)
su - postgres psql # 1. 驗(yàn)證是否處于恢復(fù)模式(從庫(kù)返回t,主庫(kù)返回f) SELECT pg_is_in_recovery();

4.3 驗(yàn)證主從數(shù)據(jù)一致性
# 主庫(kù)創(chuàng)建測(cè)試表并插入數(shù)據(jù) # 主庫(kù)執(zhí)行: CREATE DATABASE test_repl; \c test_repl; CREATE TABLE user_info (id int, name varchar(50)); INSERT INTO user_info VALUES (1, 'test_replication'); # 從庫(kù)執(zhí)行(查看是否同步到數(shù)據(jù)) \c test_repl; SELECT * FROM user_info;
主庫(kù):

從庫(kù):

從上圖我們可以看出,主從復(fù)制成功啦!
5.主從復(fù)制常用操作
5.1 切換主從(故障轉(zhuǎn)移,簡(jiǎn)易版)
當(dāng)主庫(kù)故障時(shí),可將從庫(kù)提升為主庫(kù):
# 從庫(kù)執(zhí)行(停止恢復(fù)模式,提升為主庫(kù)) su - postgres psql -c "SELECT pg_promote();" # 驗(yàn)證:提升后從庫(kù)pg_is_in_recovery()返回f psql -c "SELECT pg_is_in_recovery();"
5.2 監(jiān)控復(fù)制延遲
# 從庫(kù)執(zhí)行,查看復(fù)制延遲(單位:秒) SELECT now() - pg_last_xact_replay_timestamp() AS replication_delay;
5.3新增從庫(kù)
只需重復(fù) “從庫(kù)配置” 步驟,使用主庫(kù)(或現(xiàn)有從庫(kù),需開(kāi)啟級(jí)聯(lián)復(fù)制)的pg_basebackup備份初始化即可。
5.4 拓展
主從復(fù)制已經(jīng)成功搭建,但我們的目標(biāo)遠(yuǎn)不止于此。
回想一下,在開(kāi)發(fā)、測(cè)試,甚至小型項(xiàng)目交付中,你是否也曾陷入這樣的困境:
- “我在家搭了個(gè)PostgreSQL數(shù)據(jù)庫(kù),同事怎么連不上?”
- “客戶急著看Demo,可服務(wù)跑在內(nèi)網(wǎng),根本沒(méi)法訪問(wèn)!”
- “沒(méi)有公網(wǎng)IP,難道只能租云服務(wù)器,或者干脆放棄遠(yuǎn)程演示?”
別焦慮——沒(méi)有公網(wǎng)IP,并不意味著你的服務(wù)只能困在局域網(wǎng)里。借助一個(gè)輕量級(jí)但強(qiáng)大的內(nèi)網(wǎng)穿透工具cpolar,你可以輕松將本地運(yùn)行的PostgreSQL服務(wù)“暴露”到公網(wǎng),自動(dòng)生成一個(gè)安全、可分享的HTTPS隧道地址。無(wú)論你身處家庭寬帶、公司防火墻后,還是校園網(wǎng)深處,外部用戶都能像訪問(wèn)普通網(wǎng)站一樣,通過(guò)標(biāo)準(zhǔn)端口安全連接你的數(shù)據(jù)庫(kù)。本文將手把手帶你完成這一過(guò)程:從零配置cpolar,到安全地將PostgreSQL服務(wù)映射至公網(wǎng),打通內(nèi)網(wǎng)與外部世界的連接通道。從此,“我的數(shù)據(jù)庫(kù)在哪,服務(wù)就在哪” 不再是一句空話。準(zhǔn)備好了嗎?讓我們開(kāi)啟這場(chǎng)高效、安全、低成本的“內(nèi)網(wǎng)突圍”之旅!
6.安裝cpolar實(shí)現(xiàn)隨時(shí)隨地開(kāi)發(fā)
6.1 什么是cpolar?
cpolar是一款安全高效的內(nèi)網(wǎng)穿透工具,無(wú)需公網(wǎng)IP或復(fù)雜配置,只需一條命令,即可將本地服務(wù)器、Web服務(wù)或任意端口映射到公網(wǎng),讓你隨時(shí)隨地遠(yuǎn)程訪問(wèn)內(nèi)網(wǎng)應(yīng)用,特別適合開(kāi)發(fā)調(diào)試、遠(yuǎn)程運(yùn)維和應(yīng)急部署等場(chǎng)景。
6.2 部署cpolar
cpolar 可以將你本地電腦中的服務(wù)(如 SSH、Web、數(shù)據(jù)庫(kù))映射到公網(wǎng)。即使你在家里或外出時(shí),也可以通過(guò)公網(wǎng)地址連接回本地運(yùn)行的開(kāi)發(fā)環(huán)境。
以下是安裝cpolar步驟:
使用一鍵腳本安裝命令:
sudo curl https://get.cpolar.sh | sh

安裝完成后,執(zhí)行下方命令查看cpolar服務(wù)狀態(tài):(如圖所示即為正常啟動(dòng))
sudo systemctl status cpolar

Cpolar安裝和成功啟動(dòng)服務(wù)后,在瀏覽器上輸入虛擬機(jī)主機(jī)IP加9200端口即:【http://ip:9200】訪問(wèn)Cpolar管理界面,使用Cpolar官網(wǎng)注冊(cè)的賬號(hào)登錄,登錄后即可看到cpolar web 配置界面,接下來(lái)在web 界面配置即可:
打開(kāi)瀏覽器訪問(wèn)本地9200端口,使用cpolar賬戶密碼登錄即可,登錄后即可對(duì)隧道進(jìn)行管理。

7.配置公網(wǎng)地址
通過(guò)配置,你可以在本地 WSL 或 Linux 系統(tǒng)上運(yùn)行 SSH 服務(wù),并通過(guò) Cpolar 將其映射到公網(wǎng),從而實(shí)現(xiàn)從任意設(shè)備遠(yuǎn)程連接開(kāi)發(fā)環(huán)境的目的。
- 隧道名稱:可自定義,本例使用了:postgres,注意不要與已有的隧道名稱重復(fù)
- 協(xié)議:tcp
- 本地地址:192.168.42.140:5432
- 端口類型:隨機(jī)臨時(shí)TCP端口
- 地區(qū):China Vip

創(chuàng)建成功后,打開(kāi)左側(cè)在線隧道列表,可以看到剛剛通過(guò)創(chuàng)建隧道生成了公網(wǎng)地址,接下來(lái)就可以在其他電腦或者移動(dòng)端設(shè)備(異地)上,使用任意一個(gè)地址在終端中訪問(wèn)即可。
- tcp 表示使用的協(xié)議類型
- 2.tcp.vip.cpolar.cn是 Cpolar 提供的域名
- 11084是隨機(jī)分配的公網(wǎng)端口號(hào)

通過(guò) Cpolar 提供的公網(wǎng)地址和端口,使用 SSH 協(xié)議從任意一臺(tái)主機(jī)連接到postgres賬號(hào)啦!
psql -h 2.tcp.vip.cpolar.cn -p 11084 -U postgres -d mydb

8.保留固定TCP公網(wǎng)地址
使用cpolar為其配置TCP地址,該地址為固定地址,不會(huì)隨機(jī)變化。

選擇區(qū)域和描述:有一個(gè)下拉菜單,當(dāng)前選擇的是“China VIP”。
右側(cè)輸入框,用于填寫(xiě)描述信息。
保留按鈕:在右側(cè)有一個(gè)橙色的“保留”按鈕,點(diǎn)擊該按鈕可以保留所選的TCP地址。
列表中顯示了一條已保留的TCP地址記錄。
- 地區(qū):顯示為“China VIP”。
- 地址:顯示為“8.tcp.vip.cpolar.cn:13299”。

登錄cpolar web UI管理界面,點(diǎn)擊左側(cè)儀表盤(pán)的隧道管理——隧道列表,找到所要配置的隧道postgres,點(diǎn)擊右側(cè)的編輯。

修改隧道信息,將保留成功的TCP端口配置到隧道中。
- 端口類型:選擇固定TCP端口
- 預(yù)留的TCP地址:填寫(xiě)保留成功的TCP地址
點(diǎn)擊更新。

創(chuàng)建完成后,打開(kāi)在線隧道列表,此時(shí)可以看到隨機(jī)的公網(wǎng)地址已經(jīng)發(fā)生變化,地址名稱也變成了保留和固定的TCP地址。
最后測(cè)試一下固定的地址是否好用,測(cè)試命令:
psql -h 8.tcp.vip.cpolar.cn -p 13299 -U postgres -d mydb

這樣,我們成功打破了“沒(méi)有公網(wǎng) IP 就無(wú)法遠(yuǎn)程訪問(wèn)數(shù)據(jù)庫(kù)”的固有認(rèn)知。
總結(jié)
總結(jié)一下:PostgreSQL 流復(fù)制主從架構(gòu)的核心價(jià)值在于"數(shù)據(jù)多一份副本,服務(wù)少一分風(fēng)險(xiǎn)"。整套方案成本低、依賴少、文檔成熟,生產(chǎn)環(huán)境里該做的故障切換、延遲監(jiān)控、復(fù)制槽管理幾個(gè)關(guān)鍵節(jié)點(diǎn)本文都有覆蓋。落地時(shí)有一點(diǎn)需要記?。簭膸?kù)硬件不要比主庫(kù)差,磁盤(pán)空間和 IO 性能尤其要跟上,這是很多主從復(fù)制出現(xiàn)延遲的根因。跑起來(lái)之后,定期檢查 pg_stat_replication 的狀態(tài)和復(fù)制延遲,這比出問(wèn)題再排查要省心得多。
以上就是PostgreSQL主從流復(fù)制的完整部署指南的詳細(xì)內(nèi)容,更多關(guān)于PostgreSQL主從流復(fù)制的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
用PostgreSQL數(shù)據(jù)庫(kù)做地理位置app應(yīng)用
項(xiàng)目中用到了postgreSQL中的earthdistance()函數(shù)功能計(jì)算地球上兩點(diǎn)之間的距離,中文的資料太少了,我找到了一篇 英文的、講的很好的文章,特此翻譯,希望能夠幫助到以后用到earthdistance的同學(xué)2014-03-03
sqoop 實(shí)現(xiàn)將postgresql表導(dǎo)入hive表
這篇文章主要介紹了sqoop 實(shí)現(xiàn)將postgresql表導(dǎo)入hive表,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12
使用navicat連接postgresql報(bào)錯(cuò)問(wèn)題圖文解決辦法
我們?cè)谌粘i_(kāi)發(fā)中有時(shí)候需要用navicate連接postgresql數(shù)據(jù)庫(kù),有時(shí)候會(huì)連接不上數(shù)據(jù)庫(kù),下面這篇文章主要給大家介紹了關(guān)于使用navicat連接postgresql報(bào)錯(cuò)問(wèn)題圖文解決辦法,需要的朋友可以參考下2023-11-11
postgresql~*符號(hào)的含義及用法說(shuō)明
這篇文章主要介紹了postgresql~*符號(hào)的含義及用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01
Postgresql - 查看鎖表信息的實(shí)現(xiàn)
這篇文章主要介紹了Postgresql 查看鎖表信息的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12
PostgreSQL連接數(shù)過(guò)多的原因分析與連接池方案
在 PostgreSQL 的生產(chǎn)運(yùn)維中,連接數(shù)過(guò)多是最常見(jiàn)且影響深遠(yuǎn)的性能問(wèn)題之一,本文將系統(tǒng)性地剖析 連接數(shù)過(guò)多的根本原因,詳解 PostgreSQL 連接機(jī)制與資源開(kāi)銷,并對(duì)比主流 連接池方案的原理、配置與適用場(chǎng)景,需要的朋友可以參考下2026-02-02
postgresql 實(shí)現(xiàn)獲取所有表名,字段名,字段類型,注釋
這篇文章主要介紹了postgresql 實(shí)現(xiàn)獲取所有表名,字段名,字段類型,注釋操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01

