Cơn ác mộng mang tên ‘Sập Database lúc 3 giờ sáng’
Hãy tưởng tượng: 3 giờ sáng, điện thoại rung bần bật. Database chính (Primary) ‘ngỏm’, sếp gọi cháy máy, khách hàng than phiền trên mọi mặt trận. Hồi mới vào nghề, mình từng mất cả tiếng đồng hồ SSH vào server để kiểm tra node nào còn sống. Sau đó là chuỗi thao tác thủ công đầy rủi ro: gõ SELECT pg_promote(); rồi vội vã sửa cấu hình ứng dụng để trỏ vào IP mới. Chỉ một phút sơ sẩy cũng đủ khiến dữ liệu bay màu.
Nếu bạn đã nắm vững PostgreSQL Streaming Replication, bạn đã có bản sao dữ liệu. Nhưng replication thôi là chưa đủ. Nó không thể tự phát hiện lỗi hay chuyển đổi (failover) khi có sự cố. Đó là lý do Patroni ra đời để gánh vác toàn bộ phần việc nặng nhọc và căng thẳng đó.
Ba cách tiếp cận High Availability (HA) phổ biến
Trước khi chọn Patroni, hãy nhìn lại những phương án mà dân kỹ thuật thường dùng khi Primary ‘tử trận’:
1. Chuyển đổi thủ công (Manual Failover)
- Cách làm: Admin trực tiếp can thiệp và nâng cấp node phụ.
- Ưu điểm: Kiểm soát tuyệt đối, tránh tình trạng nhảy node nhầm.
- Nhược điểm: Quá chậm. Downtime kéo dài tùy thuộc vào tốc độ thức dậy của bạn.
2. Script tự chế
- Cách làm: Dùng Bash hoặc Python ping Primary liên tục để tự động promote Standby.
- Ưu điểm: Phản ứng nhanh hơn con người.
- Nhược điểm: Cực kỳ nguy hiểm với lỗi Split-brain. Khi hai node cùng tưởng mình là Primary và cùng ghi dữ liệu, database của bạn sẽ nát vụn.
3. Patroni – Tiêu chuẩn vàng hiện nay
- Cách làm: Quản lý tập trung qua một ‘cuốn sổ cái chung’ (DCS như ETCD hoặc Consul).
- Ưu điểm: Tự động hoàn toàn, chống Split-brain bằng thuật toán đồng thuận, hỗ trợ REST API xịn sò.
- Nhược điểm: Tốn thêm thời gian nghiên cứu cấu hình ban đầu.
Tại sao Patroni là lựa chọn số một cho dự án lớn?
Mình từng triển khai hệ thống cho một sàn thương mại điện tử với hơn 15.000 người truy cập đồng thời. Yêu cầu cực gắt: downtime không được quá 30 giây. Sau khi test thử Repmgr và Patroni, mình chọn Patroni nhờ cơ chế Distributed Configuration Store (DCS).
Hãy coi ETCD như một trọng tài quyền lực. Patroni trên mỗi node sẽ liên tục gửi tín hiệu ‘Tôi vẫn sống’ (heartbeat) đến trọng tài. Nếu Primary im lặng quá 10 giây, trọng tài sẽ ra lệnh cho các node còn lại bầu Leader mới ngay lập tức. Quy trình này diễn ra minh bạch, chính xác và không cần con người nhúng tay.
Kiến trúc chuẩn của một cụm Patroni
Một mô hình thực chiến mình thường setup bao gồm:
- PostgreSQL: Nhân vật chính lưu trữ dữ liệu.
- Patroni: ‘Vệ sĩ’ chạy kèm mỗi instance PostgreSQL.
- ETCD: Nơi lưu giữ trạng thái sống còn của cả cụm (Cluster state).
- HAProxy & Keepalived: Cung cấp một Virtual IP duy nhất. Ứng dụng chỉ cần kết nối vào IP này, HAProxy sẽ tự biết node nào đang là Primary để trỏ tới.
Hướng dẫn triển khai chi tiết
Giả sử bạn có 3 server Ubuntu. Chúng ta sẽ tập trung vào cài đặt Patroni và ETCD để tạo khung xương cho hệ thống.
Bước 1: Thiết lập ETCD (Cửa hàng trạng thái)
Cài đặt etcd trên cả 3 node:
sudo apt-get update
sudo apt-get install etcd -y
Hãy chỉnh sửa /etc/default/etcd để các node nhìn thấy nhau. Đây là bước sống còn để tạo ra sự đồng thuận (consensus) trong cụm.
Bước 2: Cài đặt PostgreSQL và Patroni
Lưu ý quan trọng: Đừng khởi tạo database bằng initdb. Hãy để Patroni tự tay làm việc đó để đảm bảo tính đồng nhất.
sudo apt-get install postgresql-15 python3-pip -y
sudo pip3 install patroni[etcd]
Bước 3: Cấu hình ‘trái tim’ patroni.yml
Dưới đây là các thông số then chốt bạn cần lưu ý:
scope: postgres-cluster
name: pg-node-1 # Đặt tên riêng cho mỗi node
dcs:
ttl: 30 # Thời gian giữ key Leader
loop_wait: 10
retry_timeout: 10
etcd:
hosts: 10.0.0.1:2379,10.0.0.2:2379,10.0.0.3:2379
postgresql:
listen: 0.0.0.0:5432
data_dir: /var/lib/postgresql/15/main
bin_dir: /usr/lib/postgresql/15/bin
authentication:
replication:
username: replicator
password: your_password
Bước 4: Kích hoạt hệ thống
Khởi chạy Patroni bằng lệnh:
patroni patroni.yml
Node đầu tiên sẽ tự khởi tạo database và lên làm Leader. Các node sau khi bật lên sẽ tự động chạy pg_basebackup từ Leader. Bạn không cần gõ lệnh backup hay restore thủ công nào cả. Tiện lợi vô cùng!
Thử nghiệm Failover: Giây phút sự thật
Đây là lúc kiểm tra thành quả. Hãy dùng lệnh patronictl để xem trạng thái:
patronictl -c patroni.yml list
Bạn sẽ thấy một bảng hiện ra với một node Leader và các node Replica. Bây giờ, hãy thử ‘rút phích cắm’ bằng cách stop service trên node Leader:
sudo systemctl stop patroni
Chỉ sau khoảng 5-10 giây, hãy nhìn log của các node còn lại. Một Replica sẽ tự động được nâng cấp lên Leader. Khi bạn bật lại node cũ, nó sẽ tự hiểu mình đã bị ‘phế truất’ và lặng lẽ quay về làm Standby.
Kinh nghiệm thực tế từ những lần ‘vấp ngã’
Vận hành Patroni trong thực tế có vài điểm ‘xương xẩu’ bạn cần nhớ:
- HAProxy là bắt buộc: Patroni không tự đổi IP cho ứng dụng. Bạn cần HAProxy gọi vào REST API (port 8008) của Patroni để check xem node nào là master thực sự.
- Cấu hình Watchdog: Hãy dùng Linux Watchdog để tự reboot server nếu Patroni treo. Nó giúp loại bỏ hoàn toàn các node ‘dở sống dở chết’ gây nhiễu cho cụm.
- Băng thông đồng bộ: Nếu DB của bạn lớn hơn 500GB, hãy dùng mạng 10Gbps. Khi node mới join cụm, nó sẽ kéo dữ liệu cực nặng, dễ làm nghẽn mạng của Leader hiện tại.
Làm chủ Patroni không chỉ nâng tầm hệ thống mà còn giúp bạn có những giấc ngủ ngon hơn. Thay vì trực chiến 24/7, hãy để tự động hóa gánh vác thay bạn.
