本次的程式碼與目錄結構可以參考 FastAPI Tutorial : Day27 branch
在 Day24 到 Day26 我們完成 FastAPI + Redis 的 Server Cache 實作
今天我們要來實作 FastAPI + PostgreSQL 的 Primary Replica 架構
Primary Replica 架構:
Primary
負責寫入資料和讀取資料 ( Create, Update, Delete, Read )Replica
只進行讀取資料 ( Read )Primary
會與 Replica
自動同步資料架構圖如下 :
Write Read
| |
| ├──------------┐
| | |
v v v
+------------+ +------------+
| Primary | | Replica |
| Database | | Database |
+------------+ +------------+
| ^
| |
└──-- sync data ---┘
但我們並不需要在後端同步 Primary 與 Replica 的資料
因為 PostgreSQL 在設定完 Replica 後會自動幫我們同步
今天會將 PostgreSQL 的 Replica 環境設定好
會使用 1 個 Primary 與 1 個 Replica
Primary-Replica 環境設定都是參考 twtrubiks : postgresql note - master slave
在 PostgreSQL 中 只有支援 1 個 Replica
因為 Postgresql 設定 Replica connection 需要使用 IP
所以需要為 service 分被固定的 IP
這邊使用特別為 network
加上 ipam
的方式來設定
ipam
: IP Address Management
可以參考 Docker Compose : IPAM configuration reference
並為每個 service 設定ipv4_address
來指定 IP
docker-compose-primary-replica.yml
services:
primary:
# ...
networks:
my_network:
ipv4_address: 172.22.0.100
# ...
networks:
my_network:
driver: bridge
ipam:
config:
- subnet: 172.22.0.0/24
gateway: 172.22.0.1
完整的 docker-compose-primary-replica.yml
在: /primary-replica/docker-compose-primary-replica.yml
使用 docker exec -it primary bash
進入 Primary 的 Container
可以使用 psql
進入 Primary 的 PostgreSQL
進入 PostgreSQL 後下以下指令
-- 進入 PostgreSQL
psql -U primary_user -d primary_db
-- 建立 Replication User
CREATE ROLE repuser WITH LOGIN REPLICATION PASSWORD 'repuser_password';
-- 查看所有 User
\du
可以看到 repuser
已經建立完成,並標示為 Replication
pg_hba.conf
如果有設定好 volume 的話
應該可以看到 /db_volumes/primary-replica
底下有這 4 個目錄
.
├── primary
├── copy
└── replica
4 directories, 0 files
在 primary
底下可以看到所有 /var/lib/postgresql/data/
的資料
其中有 postgresql.conf
與 pg_hba.conf
等設定檔案
可以直接在本機端修改 /primary-replica/primary/pg_hba.conf
在檔案最後加上以下設定
/primary-replica/primary/pg_hba.conf
# ...
# Add replication user
host replication repuser 172.22.0.101/32 md5
host replication repuser 172.22.0.102/32 md5
也可以直接以 command line 完成
echo "host replication repuser 172.22.0.101/32 md5" >> db_volumes/primary-replica/primary/pg_hba.conf
echo "host replication repuser 172.22.0.102/32 md5" >> db_volumes/primary-replica/primary/pg_hba.conf
postgresql.conf
只需要在 postgresql.conf
修改以下幾個設定
/primary-replica/primary/postgresql.conf
archive_mode = on
archive_command = '/bin/date'
max_wal_senders = 10
wal_keep_size = 16
synchronous_standby_names = '*'
在 Primary Contaienr 中以 psql
進入 Postgresql 並加入測試資料
psql -U primary_user -d primary_db
-- 建立測試資料表
CREATE TABLE test2_table (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
-- 插入測試資料
INSERT INTO test_table (name) VALUES ('test1');
-- 列出所有 table
\dt
記得要 restart Primary 的 Container 來重新載入設定 !
pg_basebackup
複製 Primary 的資料進入 replica
的 Container
docker exec -it replica bash
在 replica
底下執行以下指令
pg_basebackup -R -D /var/lib/postgresql/copy -Fp -Xs -v -P -h primary -p 5432 -U repuser
先 stop Primary 和 replica 的 Container
docker stop primary replica
將 copy
資料夾複製到 replica
的 data
資料夾
rm -r db_volumes/primary-replica/replica/*
cp -r db_volumes/primary-replica/copy/* db_volumes/primary-replica/replica/
再 restart Primary 和 Replica 的 Container
docker compose -f docker-compose-primary-replica.yml restart
先進入 Replica 的 Container
docker exec -it primary replica
並嘗試進入 PostgreSQL
psql -U replica_user -d replica_db
會發現跳出 Error :
嘗試在 Replica
Contaier 以 primary_user
進入 PostgreSQL
結果發現可以正常進入 PostgreSQL !
我們發現透過 pg_basebackup
載入備份資料的 Replica database 會變成 Primary database 的 User
嘗試在 Primary 的 PostgreSQL 建立一個新的 Table
docker exec -it primary bash
加上 test2_table
-- 進入 PostgreSQL
psql -U primary_user -d primary_db
-- 建立測試資料表 2
CREATE TABLE test2_table (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
-- 插入測試資料
INSERT INTO test2_table (name) VALUES ('test2');
再進入 Replica 的 PostgreSQL
docker exec -it replica bash
進入 PostgreSQL
psql -U primary_user -d primary_db
-- 列出所有 table
\dt
可以看到 test2_table
已經被同步到 Replica 的 PostgreSQL 中 !
我們發現透過 pg_basebackup
載入備份資料的 Replica database 會變成 Primary database 的 User
所以我們統一將 Primary 與 Replica 都以 primary-replica/db.env
來載入設定
/primary-replica/db.env
POSTGRES_PASSWORD=postgresql_password
POSTGRES_USER=postgresql_user
POSTGRES_DB=postgresql_db
這樣就可以避免不同的 User 造成的問題
以上的設定都是手動設定的
但我們可以透過 shell script 來自動化設定
這邊分為 3 個 script :
reset.sh
: 重置所有 Containersetup.sh
: 設定 Primary 與 Replicatest.sh
: 測試 Primary 與 Replica 是否正常運作這些 script 都在 /primary-replica
底下,這邊也不佔篇幅
今天我們完成了 Primary-Replica 架構中 DB 的設定
透過 pg_basebackup
複製 Primary 的資料到 Replica 中
並且撰寫 shell script 來自動化設定
可以看到在 Primary 中建立的 Table 會自動同步到 Replica 中
接下來我們要來實作 FastAPI + PostgreSQL 的 Primary-Replica 架構
在 CRUD 層面要如何實作 Primary-Replica 架構