Cấu hình Streaming Replication cho PostgreSQL
Thiết lập Primary Node (Master)
Bước đầu tiên là cấu hình máy chủ chính (Primary) để cho phép các máy chủ khác (Replica) kết nối và đồng bộ dữ liệu theo thời gian thực.
Tại sao: Streaming Replication giúp Replica nhận các log thay đổi (WAL) từ Primary ngay lập tức, đảm bảo dữ liệu Object Store luôn đồng bộ và có khả năng failover nhanh.
Kết quả mong đợi: Primary node chấp nhận kết nối từ replica và ghi log vào thư mục lưu trữ.
Chỉnh sửa file cấu hình chính postgresql.conf tại đường dẫn đầy đủ /etc/postgresql/16/main/postgresql.conf (giả định phiên bản 16 của Postgres trên Ubuntu 24.04). Thêm hoặc sửa các tham số sau:
wal_level = replica
max_wal_senders = 10
wal_keep_size = 64MB
listen_addresses = '*'
Tham số wal_level = replica yêu cầu server ghi đầy đủ log cần thiết cho replication. max_wal_senders giới hạn số lượng kết nối replication đồng thời.
Chỉnh sửa file cấu hình quyền truy cập pg_hba.conf tại đường dẫn đầy đủ /etc/postgresql/16/main/pg_hba.conf. Thêm dòng sau vào cuối file:
host replication replicator 192.168.1.0/24 md5
Thay 192.168.1.0/24 bằng subnet thực tế của Replica node. replicator là tên user sẽ dùng để connect. md5 yêu cầu xác thực bằng mật khẩu.
Tạo user chuyên dụng cho replication và cấp quyền:
sudo -u postgres psql -c "CREATE USER replicator WITH REPLICATION ENCRYPTED PASSWORD 'YourSecurePassword';"
Thay YourSecurePassword bằng mật khẩu mạnh thực tế.
Khởi động lại dịch vụ PostgreSQL để áp dụng cấu hình:
sudo systemctl restart postgresql@16-main
Dịch vụ sẽ khởi động lại và bắt đầu lắng nghe các kết nối replication trên port 5432.
Thiết lập Replica Node (Standby)
Tiếp theo, ta sẽ thiết lập máy chủ dự phòng bằng cách sao chép toàn bộ dữ liệu từ Primary và cấu hình để nó chạy ở chế độ Standby.
Tại sao: Sử dụng pg_basebackup đảm bảo sao chép nguyên vẹn cluster database ở trạng thái nhất quán, nhanh hơn việc restore từ file dump thông thường.
Kết quả mong đợi: Replica node có dữ liệu giống hệt Primary và tự động đồng bộ liên tục.
Trên máy Replica, thực hiện lệnh backup trực tiếp từ Primary. Thay 192.168.1.10 bằng IP của Primary Node và replicator bằng user đã tạo:
sudo -u postgres pg_basebackup -h 192.168.1.10 -U replicator -D /var/lib/postgresql/16/main -Fp -Xs -P -R
Tham số -R tự động tạo file standby.signal và file recovery.conf (hoặc postgresql.auto.conf) cần thiết để chạy chế độ replica.
Chỉnh sửa file postgresql.conf trên Replica tại /etc/postgresql/16/main/postgresql.conf. Đảm bảo các dòng sau được thiết lập:
listen_addresses = '*'
port = 5432
wal_level = replica
max_wal_senders = 0
Trên Replica, ta thường đặt max_wal_senders = 0 nếu không muốn nó đóng vai trò là Primary cho máy khác nữa, trừ khi muốn cascade replication.
Khởi động dịch vụ PostgreSQL trên Replica:
sudo systemctl start postgresql@16-main
Dịch vụ sẽ khởi động ở chế độ read-only và bắt đầu streaming dữ liệu từ Primary.
Verify Replication
Để kiểm tra xem replication đã hoạt động hay chưa, hãy chạy lệnh sau trên Primary Node:
sudo -u postgres psql -c "SELECT client_addr, state, sent_lsn, write_lsn, flush_lsn, replay_lsn FROM pg_stat_replication;"
Kết quả mong đợi: Xuất hiện một dòng với state là streaming và replay_lsn gần bằng sent_lsn, cho thấy Replica đang đồng bộ dữ liệu gần như tức thời.
Tạo script Backup toàn bộ Database Object Store
Viết script Backup an toàn
Cần tạo một script bash để tự động hóa quá trình backup, đảm bảo khóa ghi (lock) hoặc sử dụng snapshot để dữ liệu không bị hỏng trong quá trình sao lưu.
Tại sao: Object Store chứa nhiều metadata và file lớn, việc backup thủ công dễ bị sai sót hoặc làm gián đoạn dịch vụ. Script giúp chuẩn hóa quy trình và lưu trữ file backup có timestamp.
Kết quả mong đợi: File .sql.gz được tạo ra chứa toàn bộ cấu trúc và dữ liệu của database Object Store.
Tạo file script tại đường dẫn /usr/local/bin/backup-object-store.sh với nội dung hoàn chỉnh sau:
#!/bin/bash
# Cấu hình
DB_NAME="object_store_db"
DB_USER="postgres"
BACKUP_DIR="/var/backup/object-store"
DATE=$(date +%F_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/${DB_NAME}_${DATE}.sql.gz"
# Tạo thư mục backup nếu chưa tồn tại
mkdir -p ${BACKUP_DIR}
# Thực hiện backup
# -d: Database name
# -U: Username
# -F c: Custom format (nhanh, có thể restore từng phần)
# -Z 9: Nén tối đa
# -j 4: Sử dụng 4 luồng nén song song
echo "Starting backup for ${DB_NAME} at ${DATE}..."
/usr/lib/postgresql/16/bin/pg_dump -d ${DB_NAME} -U ${DB_USER} -F c -Z 9 -j 4 | gzip > ${BACKUP_FILE}
# Kiểm tra kết quả
if [ $? -eq 0 ]; then
echo "Backup successful: ${BACKUP_FILE}"
# Xóa các file backup cũ hơn 7 ngày (giữ lại 7 ngày)
find ${BACKUP_DIR} -type f -name "${DB_NAME}_*.sql.gz" -mtime +7 -delete
else
echo "Backup failed!"
exit 1
fi
Thay object_store_db và postgres bằng tên database và user thực tế. Tham số -F c của pg_dump tạo file binary custom, nhanh hơn và nhẹ hơn file SQL text thông thường.
Cấp quyền thực thi cho script:
sudo chmod +x /usr/local/bin/backup-object-store.sh
Script đã sẵn sàng để chạy thủ công hoặc qua cron.
Verify Backup Script
Chạy thử script thủ công để đảm bảo không có lỗi quyền truy cập hoặc đường dẫn:
sudo /usr/local/bin/backup-object-store.sh
Kiểm tra thư mục /var/backup/object-store để xác nhận file .sql.gz đã được tạo và có kích thước hợp lý (không bằng 0 byte).
Cấu hình Cron Job để Backup định kỳ
Thiết lập lịch trình tự động
Sử dụng hệ thống cron để chạy script backup mỗi ngày vào lúc 2 giờ sáng.
Tại sao: Backup tự động đảm bảo dữ liệu được bảo vệ liên tục mà không cần can thiệp của con người, giảm thiểu rủi ro mất dữ liệu do quên backup.
Kết quả mong đợi: Script chạy tự động vào thời gian định trước và ghi log vào file log.
Mở file crontab của user root để thêm job:
sudo crontab -e
Thêm dòng sau vào cuối file, lưu ý dùng dấu / để phân cách các trường thời gian:
0 2 * * * /usr/local/bin/backup-object-store.sh >> /var/log/backup-object-store.log 2>&1
Định dạng 0 2 * * * nghĩa là chạy lúc 00 phút, 2 giờ sáng, mỗi ngày trong tháng, mỗi tháng. 2>&1 chuyển cả lỗi (stderr) vào file log.
Lưu file và thoát trình soạn thảo. Hệ thống cron sẽ tự động tải cấu hình mới.
Verify Cron Job
Để kiểm tra xem cron đã được đăng ký chưa, chạy lệnh:
sudo crontab -l | grep backup-object-store
Kết quả mong đợi: Xuất hiện dòng cron job đã thêm ở trên. Bạn cũng có thể xem file log /var/log/backup-object-store.log sau khi thời gian chạy đến để xác nhận.
Hướng dẫn khôi phục dữ liệu từ file Backup
Quy trình Restore Database
Khi xảy ra sự cố mất dữ liệu, bạn cần thực hiện khôi phục từ file backup đã tạo trước đó.
Tại sao: Việc khôi phục cần thực hiện chính xác để tránh xung đột dữ liệu hoặc hỏng cấu trúc table trong Object Store.
Kết quả mong đợi: Database Object Store được phục hồi hoàn toàn về trạng thái tại thời điểm backup.
Trước tiên, xác định file backup mới nhất trong thư mục backup:
ls -lt /var/backup/object-store/*.sql.gz | head -n 1
Ghi nhớ tên file backup, ví dụ: /var/backup/object-store/object_store_db_2024-05-20_020000.sql.gz.
Xóa dữ liệu hiện tại của database (nếu cần reset hoàn toàn) hoặc tạo database mới để restore vào:
sudo -u postgres psql -c "DROP DATABASE IF EXISTS object_store_db;"
sudo -u postgres psql -c "CREATE DATABASE object_store_db OWNER postgres;"
Lệnh này đảm bảo môi trường sạch để restore dữ liệu mới vào.
Thực hiện lệnh restore sử dụng pg_restore (bắt buộc dùng pg_restore cho file format custom -F c):
sudo -u postgres pg_restore -d object_store_db -j 4 /var/backup/object-store/object_store_db_2024-05-20_020000.sql.gz
Thay đường dẫn file bằng file thực tế bạn đã chọn. Tham số -j 4 giúp tăng tốc độ restore bằng cách sử dụng song song 4 luồng.
Verify Restore
Sau khi restore xong, kiểm tra xem dữ liệu đã về chưa bằng cách đếm số lượng bucket hoặc object:
sudo -u postgres psql -d object_store_db -c "SELECT COUNT(*) FROM buckets;"
sudo -u postgres psql -d object_store_db -c "SELECT COUNT(*) FROM objects;"
Kết quả mong đợi: Số lượng trả về phải khớp với số lượng dữ liệu bạn có trước khi xảy ra sự cố hoặc số lượng trong file backup. Nếu số lượng là 0, quá trình restore có thể thất bại.
Điều hướng series:
Mục lục: Series: Triển khai Database Object Store với PostgreSQL và Ubuntu 24.04
« Phần 5: Tạo bucket, upload và quản lý object cơ bản
Phần 7: Tối ưu hiệu năng và xử lý sự cố phổ biến »