HA #1: Cài đặt PostgreSQL Master-Slave Replication
Hướng dẫn thực chiến cài PostgreSQL Master-Slave replication trên Linux, cấu hình WAL streaming và quy trình promote slave khi master gặp sự cố.
Hệ thống database chạy trên một node duy nhất là một quả bom hẹn giờ. Không phải nếu nó chết — mà là khi nào. Bài này ghi lại cách cài đặt mô hình Master-Slave để đọc được phân tải và có sẵn một bản dự phòng khi node chính gặp sự cố.
Bối cảnh
Mô hình này phù hợp khi bạn:
- Có lượng read query nhiều hơn write đáng kể
- Muốn có node dự phòng sẵn sàng promote lên Master khi cần
- Chạy trên 2 server riêng biệt (không phải Docker Compose trên cùng host)
Môi trường bài này:
| Master | Slave | |
|---|---|---|
| IP | 192.168.1.10 |
192.168.1.11 |
| OS | Ubuntu 22.04 | Ubuntu 22.04 |
| PostgreSQL | 15 | 15 |
| Port | 5432 | 5432 |
Phiên bản PostgreSQL trên Master và Slave phải khớp nhau — ít nhất là cùng major version.
Cài đặt PostgreSQL trên cả 2 node
Chạy trên cả Master và Slave:
1
2
3
4
sudo apt update
sudo apt install -y postgresql-15
sudo systemctl enable postgresql
sudo systemctl start postgresql
Kiểm tra version:
1
2
psql --version
# postgresql 15.x
Cấu hình Master
1. Tạo replication user
1
sudo -u postgres psql
1
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'strong_password_here';
2. Chỉnh postgresql.conf
1
sudo nano /etc/postgresql/15/main/postgresql.conf
Tìm và sửa các dòng sau:
1
2
3
4
listen_addresses = '*'
wal_level = replica
max_wal_senders = 3
wal_keep_size = 64
Giải thích:
wal_level = replica— bật WAL ở mức đủ cho streaming replicationmax_wal_senders— số kết nối streaming tối đa cho phép (mỗi Slave cần 1)wal_keep_size— giữ lại WAL segments để Slave có thể catch up nếu lag
3. Chỉnh pg_hba.conf
1
sudo nano /etc/postgresql/15/main/pg_hba.conf
Thêm dòng này vào cuối file (thay IP của Slave):
1
host replication replicator 192.168.1.11/32 scram-sha-256
4. Restart PostgreSQL
1
sudo systemctl restart postgresql
Cấu hình Slave
1. Dừng PostgreSQL và xóa data directory
1
2
sudo systemctl stop postgresql
sudo rm -rf /var/lib/postgresql/15/main/*
Đây là bước quan trọng — Slave phải bắt đầu từ một bản sao chính xác của Master, không phải data cũ.
2. Chạy pg_basebackup
1
2
3
4
5
6
7
sudo -u postgres pg_basebackup \
-h 192.168.1.10 \
-U replicator \
-D /var/lib/postgresql/15/main \
-P \
-Xs \
-R
Flag quan trọng:
-Xs— streaming mode, chuyển WAL real-time trong quá trình backup-R— tự động tạostandby.signalvà ghiprimary_conninfovàopostgresql.auto.conf-P— hiển thị tiến trình
Nhập password khi được hỏi. Quá trình này có thể mất vài phút tùy dung lượng database.
3. Kiểm tra file postgresql.auto.conf
1
sudo cat /var/lib/postgresql/15/main/postgresql.auto.conf
Phải có dòng tương tự:
1
primary_conninfo = 'host=192.168.1.10 port=5432 user=replicator password=strong_password_here'
4. Khởi động Slave
1
sudo systemctl start postgresql
Xác minh replication hoạt động
Trên Master
1
2
SELECT client_addr, state, sent_lsn, write_lsn, flush_lsn, replay_lsn
FROM pg_stat_replication;
Nếu replication đang chạy, bạn sẽ thấy một row với state = streaming và IP của Slave.
Trên Slave
1
2
SELECT status, received_lsn, last_msg_receipt_time
FROM pg_stat_wal_receiver;
Test thực tế
Trên Master, tạo một bảng test:
1
2
CREATE TABLE replication_test (id serial, note text, ts timestamptz default now());
INSERT INTO replication_test (note) VALUES ('hello from master');
Trên Slave, kiểm tra ngay:
1
2
SELECT * FROM replication_test;
-- Phải thấy row vừa insert
Thử ghi trực tiếp lên Slave (phải bị từ chối):
1
2
INSERT INTO replication_test (note) VALUES ('should fail');
-- ERROR: cannot execute INSERT in a read-only transaction
Promote Slave thành Master (khi cần)
Khi Master gặp sự cố và bạn cần Slave tiếp quản:
1
sudo -u postgres pg_ctl promote -D /var/lib/postgresql/15/main
Hoặc dùng psql:
1
SELECT pg_promote();
Sau khi promote, Slave sẽ chấp nhận write queries. Lúc này bạn cần cập nhật connection string của application trỏ sang IP mới.
Lưu ý: Nếu Master cũ phục hồi sau đó, không được để nó tự động kết nối lại. Cần rebuild nó thành Slave mới — chạy lại
pg_basebackuptừ Master mới (node vừa promote).
Những thứ dễ sai
pg_hba.conf sai IP hoặc sai method — Slave kết nối được nhưng bị từ chối auth. Kiểm tra log ở /var/log/postgresql/.
wal_level không đủ — Nếu đang dùng minimal, streaming replication không hoạt động. Phải restart sau khi đổi.
Slave bị lag quá nhiều — Tăng wal_keep_size trên Master. Nếu Slave lag quá threshold thì sẽ mất WAL và phải pg_basebackup lại từ đầu.
Firewall block port 5432 — Kiểm tra ufw hoặc iptables trên cả hai node.
Bước tiếp theo
Mô hình này giải quyết được việc phân tải read và có bản dự phòng. Nhưng application vẫn phải tự quản lý việc kết nối đến đúng node — Master cho write, Slave cho read.
Bài tiếp theo sẽ đặt PgBouncer vào giữa để gom và tái sử dụng connection, tránh tình trạng database bị quá tải kết nối khi traffic tăng.