Skip to content

Latest commit

 

History

History
366 lines (250 loc) · 9.56 KB

Day27.md

File metadata and controls

366 lines (250 loc) · 9.56 KB

[Day27] FastAPI : Primary Replica 架構實作

本次的程式碼與目錄結構可以參考 FastAPI Tutorial : Day27 branch

前言

Day24Day26 我們完成 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

Docker Compose 設定

因為 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

Primary 設定

建立 Replication User

使用 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

docker exec primary
可以看到 repuser 已經建立完成,並標示為 Replication

修改 Primary 的 pg_hba.conf

如果有設定好 volume 的話
應該可以看到 /db_volumes/primary-replica 底下有這 4 個目錄

.
├── primary
├── copy
└── replica

4 directories, 0 files

db_volumes primary
primary 底下可以看到所有 /var/lib/postgresql/data/ 的資料
其中有 postgresql.confpg_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

修改 Primary 的 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

記得要 restart Primary 的 Container 來重新載入設定 !

Replica 設定

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

pg_basebackup

載入 Primary 的資料

stop Primary 和 replica 的 Container

docker stop primary replica

copy 資料夾複製到 replicadata 資料夾

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

測試 Primary 與 Replica 是否同步運作

先進入 Replica 的 Container

docker exec -it primary replica

並嘗試進入 PostgreSQL

psql -U replica_user -d replica_db

會發現跳出 Error :
docker psql replica1 error


嘗試在 Replica Contaier 以 primary_user 進入 PostgreSQL

docker replica1 primary_user

結果發現可以正常進入 PostgreSQL !


我們發現透過 pg_basebackup 載入備份資料的 Replica database 會變成 Primary database 的 User

測試 Primary 與 Replica 是否同步運作


嘗試在 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

docker replica1 test2_table

可以看到 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 : 重置所有 Container
  • setup.sh : 設定 Primary 與 Replica
  • test.sh : 測試 Primary 與 Replica 是否正常運作

這些 script 都在 /primary-replica 底下,這邊也不佔篇幅


primary-replica-copy

總結

今天我們完成了 Primary-Replica 架構中 DB 的設定
透過 pg_basebackup 複製 Primary 的資料到 Replica 中
並且撰寫 shell script 來自動化設定


可以看到在 Primary 中建立的 Table 會自動同步到 Replica 中


接下來我們要來實作 FastAPI + PostgreSQL 的 Primary-Replica 架構
在 CRUD 層面要如何實作 Primary-Replica 架構

Reference