Thiết lập PostgreSQL streaming replication trên 2 VPS

Bạn đang chạy PostgreSQL trên một VPS và lo lắng về rủi ro hỏng hóc phần cứng, hoặc muốn có một bản sao dữ liệu thời gian thực để vừa dự phòng vừa giảm tải đọc? Streaming replication chính là giải pháp bạn cần. Bài này sẽ hướng dẫn bạn thiết lập PostgreSQL streaming replication giữa 2 VPS chạy Ubuntu 24.04 LTS, từ cấu hình primary, chuẩn bị standby bằng pg_basebackup, cho đến kiểm tra replication hoạt động và xử lý các lỗi thường gặp. Kết quả bạn nhận được là một hệ thống dữ liệu dự phòng liên tục, sẵn sàng thay thế khi primary gặp sự cố.
Yêu cầu trước khi bắt đầu
Trước khi bắt tay vào làm, bạn cần chuẩn bị những thứ sau:
- Hai VPS chạy Ubuntu 24.04 LTS, mỗi máy tối thiểu 2 GB RAM và 2 vCPU. Bạn có thể sử dụng VPS Linux NVMe của thueVPS cho cả hai máy để đảm bảo hiệu năng I/O ổn định.
- User có quyền
sudotrên cả hai máy. Các lệnh dưới đây giả định bạn đang dùng user này. - Hai địa chỉ IP tĩnh riêng biệt cho từng VPS. Bạn cần biết IP của primary và standby.
- PostgreSQL 16 hoặc 17 được cài đặt trên cả hai máy. Bài viết dùng PostgreSQL 17, nhưng các bước tương tự cho phiên bản 16.
- Mở port 5432 trên firewall của primary để standby có thể kết nối. Nếu dùng
ufw, lệnh sẽ làsudo ufw allow from to any port 5432.
Vì sao nên dùng streaming replication?
Khi dữ liệu của bạn chỉ nằm trên một VPS, mọi thứ phụ thuộc vào một máy chủ riêng biệt. Ổ cứng hỏng, nhà cung cấp gặp sự cố, hay bạn thao tác sai lệnh DROP DATABASE đều có thể khiến bạn mất dữ liệu hoặc phải dừng dịch vụ một thời gian dài. Streaming replication giải quyết vấn đề này bằng cách sao chép liên tục các bản ghi WAL (Write-Ahead Log) từ primary sang standby.
Standby luôn ở trạng thái sẵn sàng, áp dụng mọi thay đổi dữ liệu gần như theo thời gian thực. Nếu primary gặp sự cố, bạn có thể chuyển standby thành primary mới chỉ trong vài phút, giảm thiểu thời gian gián đoạn dịch vụ. Ngoài ra, bạn có thể bật hot_standby để cho phép các truy vấn đọc chạy trên standby, giúp giảm tải cho primary trong các hệ thống có tỷ lệ đọc/ghi cao.
Bước 1 - Cài đặt PostgreSQL trên cả hai VPS
Đầu tiên, bạn cần cài PostgreSQL trên cả hai máy. Các lệnh dưới đây chạy trên cả primary và standby. Bạn nên cài đúng cùng một phiên bản PostgreSQL để tránh các vấn đề tương thích định dạng dữ liệu.
sudo apt update
sudo apt install -y postgresql postgresql-contrib
sudo systemctl enable --now postgresql
Lệnh trên sẽ cài đặt PostgreSQL 17 (bản mặc định trên Ubuntu 24.04) và kích hoạt dịch vụ chạy nền. Sau khi cài, kiểm tra trạng thái dịch vụ:
sudo systemctl status postgresql
Bạn sẽ thấy output có dạng active (running) hoặc active (exited) (chế độ cluster mode). Để chắc chắn, hãy kiểm tra xem PostgreSQL đang lắng nghe trên port nào:
sudo ss -tlnp | grep 5432
Nếu thấy dòng LISTEN 0.0.0.0:5432 hoặc 127.0.0.1:5432 nghĩa là PostgreSQL đã chạy. Mặc định, PostgreSQL chỉ lắng nghe trên localhost, ta sẽ cấu hình lại ở bước sau.
Bước 2 - Cấu hình PostgreSQL trên primary
Đây là bước quan trọng nhất. Trên primary, bạn cần sửa hai file cấu hình chính: postgresql.conf và pg_hba.conf. File cấu hình nằm trong thư mục dữ liệu, thường là /etc/postgresql/17/main/.
Mở file postgresql.conf:
sudo nano /etc/postgresql/17/main/postgresql.conf
Tìm và sửa (hoặc thêm nếu chưa có) các dòng sau:
listen_addresses = 'localhost,'
wal_level = replica
max_wal_senders = 5
wal_keep_size = 128
hot_standby = on
Giải thích từng tham số:
listen_addresses: Cho phép PostgreSQL lắng nghe cả trên IP public của primary để standby có thể kết nối. Bạn cũng có thể dùng'*'để nghe tất cả các interface, nhưng nên giới hạn cho bảo mật.wal_level = replica: Bắt buộc phải có để bật streaming replication. Đây là mức tối thiểu cần thiết, ghi đủ thông tin vào WAL để phục hồi và sao chép.max_wal_senders: Số lượng kết nối replication tối đa. Giá trị 5 là đủ cho một standby, nếu bạn có nhiều standby hơn thì tăng lên.wal_keep_size = 128: Giữ lại 128 MB dữ liệu WAL trongpg_walđể standby có thể bắt kịp nếu bị ngắt kết nối tạm thời. Bạn có thể tăng lên nếu mạng không ổn định.hot_standby = on: Cho phép standby phục vụ các truy vấn đọc. Nếu bạn chỉ cần dự phòng, vẫn nên bật để có thể kiểm tra dữ liệu trên standby.
Lưu file và mở tiếp file pg_hba.conf:
sudo nano /etc/postgresql/17/main/pg_hba.conf
Thêm dòng sau vào cuối file để cho phép user replication từ standby kết nối:
host replication replicator /32 scram-sha-256
Thay <ip_standby> bằng địa chỉ IP public thực tế của VPS standby. Dòng này nói PostgreSQL chấp nhận kết nối replication từ IP của standby với user replicator và xác thực bằng scram-sha-256 (phương thức mặc định và an toàn trên PostgreSQL 16+).
Bước 3 - Tạo user replication trên primary
Bạn cần một user chuyên dụng cho việc replication, không nên dùng user postgres siêu người dùng cho việc này. Chuyển sang user postgres và tạo user mới:
sudo -i -u postgres
psql -c "CREATE USER replicator REPLICATION LOGIN PASSWORD 'mat_khau_manh';"
exit
Lệnh này tạo user replicator với quyền REPLICATION, cho phép user này kết nối và nhận dữ liệu WAL. Hãy đặt một mật khẩu mạnh và ghi nhớ nó. Bạn cần mật khẩu này ở bước chuẩn bị standby.
Sau khi tạo user, khởi động lại PostgreSQL trên primary để áp dụng các thay đổi cấu hình:
sudo systemctl restart postgresql
Kiểm tra xem PostgreSQL đã lắng nghe trên IP public chưa:
sudo ss -tlnp | grep 5432
Lúc này bạn sẽ thấy LISTEN 0.0.0.0:5432 hoặc LISTEN :5432. Nếu không thấy, kiểm tra lại dòng listen_addresses và chắc chắn bạn đã restart service.
Bước 4 - Chuẩn bị standby bằng pg_basebackup
Bây giờ đến phần thú vị. Trên standby, bạn sẽ dùng pg_basebackup để tạo một bản sao dữ liệu từ primary. Lệnh này sao chép toàn bộ cụm dữ liệu và bắt đầu quá trình replication ngay sau đó.
Trước tiên, dừng dịch vụ PostgreSQL trên standby:
sudo systemctl stop postgresql
Sau đó, xóa dữ liệu mặc định của PostgreSQL cục bộ (chúng ta sẽ thay thế bằng dữ liệu từ primary):
sudo rm -rf /var/lib/postgresql/17/main
Bây giờ, chạy pg_basebackup với user postgres:
sudo -i -u postgres
pg_basebackup -h -D /var/lib/postgresql/17/main -U replicator -v -P --wal-method=stream
exit
Giải thích các tham số:
-h <ip_primary>: Địa chỉ IP của primary.-D /var/lib/postgresql/17/main: Thư mục dữ liệu trên standby.-U replicator: User replication đã tạo ở bước 3.-v -P: Hiển thị tiến trình chi tiết.--wal-method=stream: Gửi dữ liệu WAL qua streaming trong quá trình backup, giúp standby bắt kịp ngay lập tức.
Trong quá trình chạy, bạn sẽ được hỏi mật khẩu của user replicator. Nhập vào và chờ đợi. Nếu thành công, bạn sẽ thấy thông báo pg_basebackup: base backup completed. Lúc này, dữ liệu của primary đã được sao chép sang standby.
Một điểm quan trọng: nếu thư mục /var/lib/postgresql/17/main không tồn tại hoặc trống, bạn cần tạo nó và set quyền sở hữu cho user postgres trước khi chạy pg_basebackup:
sudo mkdir -p /var/lib/postgresql/17/main
sudo chown -R postgres:postgres /var/lib/postgresql/17/main
Bước 5 - Cấu hình standby để chạy replication
Sau khi có bản sao dữ liệu, bạn cần tạo file cấu hình để standby biết cách kết nối tới primary. Trên PostgreSQL 17, file này có tên là standby.signal và được đặt trong thư mục dữ liệu.
Tạo file standby.signal:
sudo touch /var/lib/postgresql/17/main/standby.signal
File này chỉ cần tồn tại là đủ, nội dung có thể để trống. Nó báo cho PostgreSQL biết đây là một standby server.
Tiếp theo, bạn cần cấu hình thông tin kết nối tới primary. Thêm vào cuối file postgresql.conf trên standby:
sudo nano /etc/postgresql/17/main/postgresql.conf
Thêm dòng sau:
primary_conninfo = 'host= port=5432 user=replicator password=mat_khau_manh'
Thay <ip_primary> bằng IP thực tế và mat_khau_manh bằng mật khẩu bạn đã đặt. Dòng này chứa thông tin kết nối để standby stream dữ liệu từ primary.
Sau khi lưu file, set đúng quyền sở hữu và khởi động PostgreSQL trên standby:
sudo chown -R postgres:postgres /var/lib/postgresql/17/main
sudo systemctl start postgresql
Bước 6 - Kiểm tra replication hoạt động
Đây là bước quan trọng để xác nhận mọi thứ hoạt động đúng. Trên primary, chạy lệnh kiểm tra trạng thái replication:
sudo -i -u postgres
psql -c "SELECT * FROM pg_stat_replication;"
Bạn sẽ thấy một dòng dữ liệu với thông tin về kết nối từ standby. Cột state phải có giá trị streaming, cột sync_state có thể là async (mặc định). Điều này có nghĩa là standby đã kết nối thành công và đang nhận dữ liệu.
Kiểm tra trạng thái trên standby:
sudo -i -u postgres
psql -c "SELECT pg_is_in_recovery();"
Nếu output là t (true), nghĩa là standby đang ở chế độ recovery và nhận dữ liệu từ primary. Bạn cũng có thể thử tạo một bảng trên primary và kiểm tra xem nó có xuất hiện trên standby không.
Trên primary:
psql -c "CREATE TABLE test_replication (id int, name text);"
Trên standby:
psql -c "\dt"
Nếu bạn thấy bảng test_replication xuất hiện, replication đang hoạt động chính xác. Nhớ xóa bảng test sau khi kiểm tra xong.
Bước 7 - Xử lý lỗi thường gặp
Trong quá trình thiết lập, bạn có thể gặp một vài lỗi phổ biến dưới đây. Dưới đây là cách chẩn đoán và xử lý.
Lỗi 1: Không kết nối được tới primary khi chạy pg_basebackup
Lỗi thường gặp nhất là could not connect to server: Connection refused. Nguyên nhân thường do primary chưa mở port 5432 trên firewall hoặc listen_addresses chưa được cấu hình đúng. Kiểm tra firewall trên primary:
sudo ufw status
Nếu không thấy port 5432 được phép, thêm rule:
sudo ufw allow from to any port 5432
Đồng thời kiểm tra lại listen_addresses trong postgresql.conf và chắc chắn bạn đã restart service.
Lỗi 2: Authentication failed cho user replicator
Lỗi password authentication failed for user "replicator" nghĩa là mật khẩu sai hoặc dòng trong pg_hba.conf chưa đúng. Kiểm tra lại mật khẩu và dòng cấu hình. Lưu ý, thứ tự các dòng trong pg_hba.conf quan trọng, dòng replication phải được đặt trước các dòng mặc định khác (thường là sau dòng # replication privileges.).
Lỗi 3: Standby không vào chế độ recovery
Nếu standby vẫn chạy ở chế độ bình thường (không recovery), kiểm tra file standby.signal có tồn tại đúng vị trí không. Ngoài ra, xem log PostgreSQL để tìm nguyên nhân:
sudo journalctl -u postgresql -n 50
Thông báo recovery ended trong log nghĩa là standby đã hoàn tất quá trình khởi tạo và sẵn sàng nhận dữ liệu.
Câu hỏi thường gặp
Streaming replication và logical replication khác nhau thế nào?
Streaming replication sao chép toàn bộ dữ liệu ở mức physical (WAL records), phù hợp để dự phòng và failover. Logical replication sao chép ở mức dữ liệu thay đổi (changesets) và cho phép bạn chọn bảng, schema cần sao chép, thích hợp cho việc đồng bộ dữ liệu giữa các hệ thống khác nhau hoặc nâng cấp phiên bản PostgreSQL.
Làm sao để chuyển standby thành primary khi cần failover?
Trên standby, chạy lệnh sudo -i -u postgres rồi psql -c "SELECT pg_promote();". Lệnh này sẽ kết thúc chế độ recovery và biến standby thành primary mới. Bạn cần cập nhật các ứng dụng trỏ về IP mới này.
Có nên dùng synchronous replication để không mất dữ liệu?
Synchronous replication đảm bảo giao dịch chỉ được xác nhận khi đã ghi trên cả primary và standby, RPO bằng 0. Tuy nhiên, nó làm tăng độ trễ ghi, đặc biệt khi mạng giữa 2 VPS có latency cao. Với hầu hết ứng dụng, async replication là đủ tốt và có hiệu năng tốt hơn.
Tôi có thể thêm standby thứ ba không?
Có, bạn có thể cascade replication hoặc cấu hình nhiều standby trực tiếp từ primary. Cần tăng max_wal_senders tương ứng và thêm các dòng trong pg_hba.conf cho từng standby.
Băng thông giữa 2 VPS có ảnh hưởng đến replication không?
Có. Nếu bạn ghi dữ liệu lớn và liên tục, replication sẽ tiêu tốn băng thông mạng. Khi chọn thuê VPS Linux, nên chọn gói có băng thông trong nước tốt nếu cả 2 máy đặt cùng Việt Nam. Bạn có thể kiểm tra throughput giữa 2 VPS bằng iperf3 để ước lượng khả năng đáp ứng.
Bài viết liên quan
- Hướng dẫn cài PostgreSQL trên VPS Ubuntu 24.04
- Tối ưu MySQL/MariaDB: Buffer pool, index, slow query log
- Hướng dẫn backup tự động VPS lên S3 với Restic
- Chuyển n8n từ SQLite sang PostgreSQL không mất workflow


