Dưới đây là hướng dẫn đầy đủ cách cấu hình Master-Slave (Streaming Replication) trong PostgreSQL 12 trên hệ điều hành Linux (Ubuntu/CentOS đều được), giúp đồng bộ dữ liệu từ server Master (Primary) sang Slave (Replica) theo thời gian thực.


🧩 Tổng quan:

  • Master: nơi ghi dữ liệu (Read/Write).
  • Slave: chỉ đọc dữ liệu (Read-only), đồng bộ liên tục với Master.
  • Sử dụng Streaming Replication + hot_standby.

✅ Yêu cầu:

  • PostgreSQL 12 cài sẵn trên cả Master và Slave.
  • Cùng phiên bản PostgreSQL.
  • Hệ thống thời gian chính xác (khuyến nghị cài ntp hoặc chrony).
  • Địa chỉ IP tĩnh cho Master và Slave.

Ví dụ:

  • Master IP: 192.168.1.10
  • Slave IP: 192.168.1.11

🔧 1. Cấu hình trên Master

Bước 1: Mở các cấu hình replication

File: postgresql.conf

sudo nano /etc/postgresql/12/main/postgresql.conf

Tìm và sửa/giá trị:

listen_addresses = '*'                          # Cho phép tất cả IP kết nối
wal_level = replica                             # Cho phép ghi WAL cho replication
max_wal_senders = 5                             # Số lượng kết nối slave tối đa
wal_keep_segments = 64                          # Dữ liệu WAL giữ lại (hoặc wal_keep_size = 512MB với bản 12+)
hot_standby = on                                # Cho phép replica đọc

Bước 2: Phân quyền replication

File: pg_hba.conf

sudo nano /etc/postgresql/12/main/pg_hba.conf

Thêm dòng sau:

host    replication     replicator      192.168.1.11/32         md5

replicator là user replication (sẽ tạo ở bước sau).

Bước 3: Tạo user replication

sudo -u postgres psql

Trong psql:

CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD '123456';
q

📦 2. Cấu hình trên Slave

Bước 1: Dừng PostgreSQL

sudo systemctl stop postgresql

Bước 2: Xóa data cũ

sudo -u postgres rm -rf /var/lib/postgresql/12/main/*

Bước 3: Dùng pg_basebackup để copy dữ liệu từ Master

sudo -u postgres pg_basebackup -h 192.168.1.10 -D /var/lib/postgresql/12/main -U replicator -P -v --wal-method=stream

Nhập mật khẩu 123456 nếu được yêu cầu.

Bước 4: Tạo file standby.signal

sudo -u postgres touch /var/lib/postgresql/12/main/standby.signal

Trong PostgreSQL 12+, không dùng recovery.conf nữa, thay bằng file standby.signal và cấu hình trong postgresql.conf.

Bước 5: Cấu hình postgresql.conf trên Slave

sudo nano /etc/postgresql/12/main/postgresql.conf

Thêm hoặc sửa:

hot_standby = on
primary_conninfo = 'host=192.168.1.10 port=5432 user=replicator password=123456'

🚀 3. Khởi động cả Master và Slave

sudo systemctl start postgresql

🔍 4. Kiểm tra trạng thái replication

Trên Master:

SELECT * FROM pg_stat_replication;

Bạn sẽ thấy thông tin kết nối của replicator.

Trên Slave:

ps aux | grep wal

Hoặc kiểm tra log: /var/log/postgresql/postgresql-12-main.log


📌 Lưu ý:

  • Slave là read-only, dùng để truy vấn hoặc dự phòng (failover).
  • Nên đặt password cho user replicator phức tạp và giới hạn IP trong pg_hba.conf.
  • Có thể dùng repmgr, Patroni để tự động failover, high availability.

✅ 5. Kiểm tra hoạt động của Master - Slave

Trên Master:

SELECT pid, usename, client_addr, state, sync_state
FROM pg_stat_replication;
  • client_addr: IP máy Slave.
  • state: streaming
  • sync_state: async / sync / potential

Trên Slave:

Bạn có thể kiểm tra file log:

sudo tail -f /var/log/postgresql/postgresql-12-main.log

Nếu kết nối đúng, bạn sẽ thấy log kiểu:

started streaming WAL from primary

✅ 6. Kiểm tra dữ liệu có đồng bộ không

Trên Master:

CREATE TABLE test_replica(id INT PRIMARY KEY, name TEXT);
INSERT INTO test_replica VALUES (1, 'Hello replica!');

Trên Slave:

sudo -u postgres psql
SELECT * FROM test_replica;

Nếu thấy dữ liệu giống y hệt ⇒ replication hoạt động tốt.


✅ 7. Cấu hình tự động khởi động sau khi reboot

PostgreSQL sẽ tự động nhận ra file standby.signal khi khởi động lại, không cần recovery.conf.

Nhưng bạn nên đảm bảo primary_conninfo vẫn tồn tại trong postgresql.conf.

Kiểm tra:

grep primary_conninfo /etc/postgresql/12/main/postgresql.conf

✅ 8. Cấu hình đồng bộ theo dạng synchronous replication (không mất dữ liệu)

Mặc định, replication là asynchronous → dữ liệu trên Slave có thể trễ.

Nếu muốn đồng bộ tuyệt đối (dữ liệu ghi xong trên Slave thì mới commit trên Master), hãy bật synchronous mode:

Trên Master:

postgresql.conf

synchronous_commit = on
synchronous_standby_names = '*'

Hoặc chỉ định Slave cụ thể: 'standby01'

Trên Slave:

postgresql.conf

primary_conninfo = 'application_name=standby01 host=192.168.1.10 port=5432 user=replicator password=123456'

✅ 9. Failover thủ công (khi Master chết)

Khi Master bị tắt hoặc gặp sự cố:

Trên Slave:

sudo systemctl stop postgresql
sudo rm /var/lib/postgresql/12/main/standby.signal

Mở postgresql.conf, xóa hoặc comment dòng primary_conninfo.

Sau đó:

sudo systemctl start postgresql

→ Lúc này, Slave sẽ hoạt động như một Master.

📌 Lưu ý: để tránh split-brain, bạn phải đảm bảo Master cũ không hoạt động nữa!


✅ 10. Cấu hình thêm nhiều Slave

Bạn có thể thêm nhiều Slave bằng cách lặp lại các bước:

  • pg_basebackup
  • Cấu hình standby.signal
  • Đặt đúng primary_conninfo theo user replication
  • Mở firewall và chỉnh pg_hba.conf trên Master

✅ 11. Mẹo hiệu suất và bảo mật

  • Chặn port 5432 từ bên ngoài, chỉ mở trong mạng nội bộ hoặc dùng VPN.
  • Dùng rsyslog để theo dõi log replication riêng.
  • Dùng log_line_prefix để ghi log truy vấn theo IP người dùng.

Ví dụ trong postgresql.conf:

log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h '

Nếu bạn cần mình viết script tự động hóa toàn bộ cấu hình Master-Slave, hoặc hỗ trợ triển khai bằng Docker, Ansible hay systemd service kiểm tra, mình có thể hỗ trợ tiếp nhé.

Bạn đã nói:

thêm

ChatGPT đã nói:

Tuyệt vời, mình sẽ tiếp tục bổ sung các nội dung nâng cao hơn để bạn có thể triển khai hệ thống PostgreSQL Master-Slave một cách chuyên nghiệp và ổn định.


✅ 12. Thiết lập giám sát replication

1. Kiểm tra độ trễ replication (replication lag)

Trên Master, bạn có thể dùng:

SELECT
  application_name,
  client_addr,
  state,
  write_lag,
  flush_lag,
  replay_lag
FROM pg_stat_replication;

Hoặc đo thủ công:

SELECT
  now() - pg_last_xact_replay_timestamp() AS replication_delay;

Chạy trên Slave để biết slave đang bị trễ bao nhiêu so với master.


✅ 13. Backup hệ thống replication an toàn

Không nên backup trực tiếp từ Slave nếu replication bị delay nhiều.

Thay vào đó, bạn có thể:

  • Sử dụng pg_basebackup từ Slave nếu đảm bảo sync đầy đủ.
  • Dùng pgBackRest, Barman, hoặc wal-g – các công cụ hỗ trợ backup trên hệ thống replication chuẩn hơn.
  • Backup từ Slave giúp không làm gián đoạn dịch vụ trên Master.

✅ 14. Dùng Replication Slot để tránh mất WAL file

Replication Slot đảm bảo rằng Master không xóa WAL file trước khi Slave bắt kịp.

Trên Master, tạo slot:

SELECT * FROM pg_create_physical_replication_slot('slot1');

Sau đó, chỉnh trên Slave:

postgresql.conf:

primary_slot_name = 'slot1'

Ưu điểm:

  • Giảm nguy cơ mất đồng bộ.
  • Slave có thể "bắt kịp" sau khi bị mất kết nối tạm thời.

📌 Lưu ý: slot này cần được theo dõi vì nếu Slave chết lâu → WAL sẽ phình to (vì bị giữ lại).


✅ 15. Chạy nhiều Slave đồng thời

Bạn có thể cấu hình nhiều Slave giống nhau:

  1. Tạo nhiều replication slot trên Master:
SELECT * FROM pg_create_physical_replication_slot('slot2');
SELECT * FROM pg_create_physical_replication_slot('slot3');
  1. Trên mỗi Slave:
primary_slot_name = 'slot2'  -- hoặc 'slot3'
  1. Mỗi slave nên có:
    • Tên application_name riêng biệt trong primary_conninfo.
    • standby.signal riêng biệt.
    • Thư mục main/ riêng biệt nếu cùng máy.

✅ 16. Cấu hình pg_stat_statements để giám sát truy vấn

Trên Master và Slave, mở postgresql.conf:

shared_preload_libraries = 'pg_stat_statements'

Sau đó chạy:

CREATE EXTENSION pg_stat_statements;

Truy vấn:

SELECT * FROM pg_stat_statements ORDER BY total_time DESC LIMIT 10;

→ Giúp bạn xem những truy vấn chậm nhất hoặc nặng nhất.


✅ 17. Giám sát bằng Prometheus + Grafana

Bạn có thể cài postgres_exporter trên cả Master và Slave:

  • Cung cấp dữ liệu metric như:
    • WAL Write size
    • Replication lag
    • Cache hit rate
    • Tuổi autovacuum...

→ Hiển thị bằng Grafana giúp giám sát tình trạng replication trực quan.


✅ 18. Dùng pg_rewind để khôi phục Master sau failover

Nếu bạn từng failover sang Slave, và sau đó muốn dùng lại Master cũ như một Slave, bạn cần dùng pg_rewind.

Ví dụ:

sudo -u postgres pg_rewind --target-pgdata=/var/lib/postgresql/12/main --source-server="host=192.168.1.11 user=replicator dbname=postgres"

→ Khôi phục dữ liệu nhanh mà không cần pg_basebackup lại từ đầu.


✅ 19. Tăng độ bền dữ liệu

  • Dùng ổ SSD hoặc NVMe cho thư mục WAL (pg_wal/).
  • Kết hợp archive_mode để sao lưu WAL ra ổ đĩa phụ:
archive_mode = on
archive_command = 'cp %p /mnt/wal_archive/%f'

✅ 20. Tổng kết sơ đồ hệ thống

        +------------------+                       +------------------+
| PostgreSQL | streaming over TCP | PostgreSQL |
| Master |<--------------------->| Slave |
| 192.168.1.10 | (replicator) | 192.168.1.11 |
+------------------+ +------------------+
|
|--- optional backup/monitor tools (pgBackRest, Prometheus, ...)

✅ 21. Sử dụng archive_mode + restore_command cho WAL log

Khi sử dụng streaming replication, nếu Slave ngắt kết nối lâu, thì các WAL file có thể bị xóa trước khi nó kịp đồng bộ → gây lỗi.

Giải pháp: kết hợp streaming replication + WAL archive backup.

Trên Master:

postgresql.conf:

archive_mode = on
archive_command = 'cp %p /var/lib/postgresql/wal_archive/%f'
  • %p: đường dẫn WAL file.
  • %f: tên file.

Trên Slave:

postgresql.conf:

restore_command = 'cp /var/lib/postgresql/wal_archive/%f %p'

→ Nếu replication stream bị ngắt, Slave sẽ lấy WAL từ thư mục archive để bắt kịp.


✅ 22. Giao thức bảo mật: Tăng cường SSL cho replication

Mặc định replication sử dụng kết nối TCP không mã hóa. Trong môi trường cloud hoặc production nên bật SSL:

Trên Master:

postgresql.conf:

ssl = on
ssl_cert_file = '/etc/ssl/certs/server.crt'
ssl_key_file = '/etc/ssl/private/server.key'

Cấp quyền trong pg_hba.conf:

hostssl    replication    replicator    192.168.1.11/32    md5

Trên Slave:

Thêm sslmode=require vào primary_conninfo:

primary_conninfo = 'host=192.168.1.10 port=5432 user=replicator password=123456 sslmode=require'

✅ 23. Cấu hình auto.conf để tránh bị mất cấu hình khi pg_basebackup

File postgresql.auto.conf tự động ghi cấu hình, nếu bạn chỉnh qua ALTER SYSTEM.

Để đảm bảo primary_conninfoprimary_slot_name không bị ghi đè:

echo "primary_conninfo = 'host=192.168.1.10 user=replicator password=123456'" >> /var/lib/postgresql/12/main/postgresql.auto.conf
echo "primary_slot_name = 'slot1'" >> /var/lib/postgresql/12/main/postgresql.auto.conf

✅ 24. Điều chỉnh WAL segment để tiết kiệm tài nguyên

WAL segment (write-ahead log) mặc định có thể chiếm nhiều dung lượng.

Bạn có thể giảm:

wal_keep_size = 256MB
max_wal_size = 1GB
min_wal_size = 80MB

Và kết hợp với archive để tránh mất dữ liệu.


✅ 25. Xử lý lỗi thường gặp

🛠 Lỗi💡 Cách xử lý
FATAL: password authentication failed for user "replicator"Kiểm tra pg_hba.conf + đúng IP + mật khẩu.
FATAL: could not connect to the primary serverKiểm tra IP, firewall, port 5432 mở chưa.
WAL segment removed while still neededBật archive_mode + wal_keep_segments lớn hơn.
standby.signal exists but no primary_conninfoXem lại postgresql.conf, cần có primary_conninfo.
ERROR: requested WAL segment has already been removedDùng archive hoặc cấu hình replication slot.

✅ 26. Gợi ý bộ công cụ quản lý HA (High Availability)

Công cụMô tả
PatroniCluster HA sử dụng etcd, tự động failover.
repmgrDễ triển khai, hỗ trợ failover thủ công và tự động.
Pgpool-IILoad balancing giữa master/slave + failover detection.
Keepalived + Virtual IPTạo IP ảo chung cho master/slave, giúp client kết nối ổn định khi failover.

✅ 27. Kết nối ứng dụng tới Master-Slave

Nếu bạn dùng PHP, Node.js, Python..., nên thiết lập ứng dụng như sau:

  • Read queries (SELECT) → kết nối đến Slave.
  • Write queries (INSERT/UPDATE) → kết nối đến Master.

Bạn có thể cấu hình trong ORM hoặc code routing logic như sau:

if (query_type == 'SELECT') {
  connect_to('slave');
} else {
  connect_to('master');
}

Hoặc dùng thư viện hỗ trợ như read-write split.


✅ 28. Mẹo xử lý lỗi nếu Slave sync lại từ đầu

Trường hợp Slave lỗi quá nặng, tốt nhất bạn nên:

# Stop PostgreSQL
sudo systemctl stop postgresql

# Remove old data
sudo rm -rf /var/lib/postgresql/12/main/*

# Sync lại bằng pg_basebackup
sudo -u postgres pg_basebackup -h master_ip -D /var/lib/postgresql/12/main -U replicator -P -v --wal-method=stream

# Tạo lại standby.signal
sudo touch /var/lib/postgresql/12/main/standby.signal

# Start lại
sudo systemctl start postgresql

✅ 29. Script tự động thiết lập Master/Slave

Bạn muốn mình tạo 1 shell script như sau?

setup_pg_master.sh
setup_pg_slave.sh

Tự động hóa:

  • Chỉnh postgresql.conf, pg_hba.conf
  • Tạo replicator user
  • Sync data
  • Tạo standby.signal
  • Thiết lập primary_conninfo