Mở rộng PostgreSQL: Hướng dẫn thực tế về Cân bằng tải và HA với Pgpool-II

Database tutorial - IT technology blog
Database tutorial - IT technology blog

Cuộc gọi lúc 2 giờ sáng: Khi PostgreSQL đơn lẻ chạm ngưỡng giới hạn

Lúc đó là 2 giờ 14 phút sáng. Điện thoại của tôi rung bần bật trên tủ đầu giường. Nagios đang gào thét: "Đã đạt giới hạn kết nối cơ sở dữ liệu." Lại nữa rồi. Ứng dụng của chúng tôi vừa chạm mốc 1.200 phiên đồng thời, nghiền nát giới hạn mặc định 100 kết nối. CPU bị kẹt ở mức 99%, và mọi yêu cầu mới đều bị từ chối thẳng thừng.

Cơn ác mộng này chính là khoảnh khắc mà mọi DBA nhận ra rằng một cơ sở dữ liệu độc lập là một quả bom hẹn giờ. Mặc dù tôi thường chọn PostgreSQL vì khả năng mở rộng của nó, nhưng nó vẫn cần một lớp trung gian mạnh mẽ để thực sự scale. Đó là lúc Pgpool-II xuất hiện. Bạn không chỉ muốn sống sót qua đêm; bạn muốn xây dựng một hệ thống luôn im lặng vì nó thực sự hoạt động ổn định.

Kiến trúc: Không chỉ đơn thuần là một Proxy

Các kỹ sư thường hỏi: "Tại sao phải dùng Pgpool-II khi tôi đã có PgBouncer?" Mặc dù cả hai đều xử lý connection pooling, nhưng Pgpool-II là một "con quái thú" tinh vi hơn nhiều. Nó đóng vai trò như một proxy thông minh hiểu được giao thức PostgreSQL và đưa ra các quyết định định tuyến dựa trên các truy vấn SQL mà nó nhận được.

Connection Pooling và Load Balancing

Connection pooling giúp giảm đáng kể chi phí tài nguyên. Thay vì tốn 30ms để khởi tạo một tiến trình mới cho mỗi truy vấn, Pgpool-II tái sử dụng các tiến trình hiện có. Nhưng sức mạnh thực sự nằm ở Cân bằng tải (Load Balancing). Khi ứng dụng của bạn gửi một truy vấn SELECT, Pgpool-II sẽ định tuyến nó đến một server standby. Điều này giúp server primary rảnh tay để xử lý các hoạt động INSERT, UPDATE, và DELETE. Trên thực tế, điều này có thể tăng gấp ba hiệu suất đọc mà không cần chỉnh sửa một dòng mã ứng dụng nào.

Tính sẵn sàng cao với Watchdog

Một proxy chỉ hữu ích nếu nó luôn trực tuyến. Nếu Pgpool-II bị sập, toàn bộ hệ thống của bạn sẽ ngừng hoạt động. Pgpool-II giải quyết vấn đề này thông qua Watchdog. Bằng cách cụm hóa (clustering) nhiều instance, các node sẽ giám sát "nhịp tim" (heartbeat) của nhau. Nếu node dẫn đầu (leader) gặp sự cố, một node theo sau (follower) sẽ ngay lập tức chiếm quyền sở hữu IP ảo (VIP). Ứng dụng của bạn thậm chí còn không nhận ra sự thay đổi này.

Thực hành: Xây dựng một Cluster linh hoạt

Hãy cùng xem xét một thiết lập thực tế. Chúng ta sẽ sử dụng ba server:

  • Node 1 (192.168.1.10): PostgreSQL chính (Primary)
  • Node 2 (192.168.1.11): PostgreSQL dự phòng (Standby – Streaming Replication)
  • Node 3 (192.168.1.12): Pgpool-II

Bước 1: Cài đặt

Trên Ubuntu, việc lấy các tệp thực thi là phần dễ dàng nhất. Phép màu thực sự nằm ở các tệp cấu hình.

sudo apt-get update
sudo apt-get install pgpool2

Bước 2: Cấu hình pgpool.conf

Mở tệp /etc/pgpool2/pgpool.conf. Chúng ta cần định nghĩa các node backend và bật chế độ cân bằng tải.

# Cấu hình mạng
listen_addresses = '*'
port = 9999

# Bật Cân bằng tải
load_balance_mode = on
master_slave_mode = on
master_slave_sub_mode = 'stream'

# Cấu hình các Node Backend
backend_hostname0 = '192.168.1.10'
backend_port0 = 5432
backend_weight0 = 1
backend_flag0 = 'ALLOW_TO_FAILOVER'

backend_hostname1 = '192.168.1.11'
backend_port1 = 5432
backend_weight1 = 1.5
backend_flag1 = 'ALLOW_TO_FAILOVER'

Việc chỉ định backend_weight cho phép bạn ưu tiên phần cứng mạnh hơn. Nếu Node 2 có 64GB RAM trong khi Node 1 chỉ có 32GB, việc đặt trọng số của Node 2 là 1.5 sẽ đảm bảo server mạnh hơn đảm nhận nhiều công việc nặng nhọc hơn.

Bước 3: Tự động Failover

Can thiệp thủ công là kẻ thù của thời gian hoạt động (uptime). Chúng ta phải cấu hình các kịch bản kiểm tra sức khỏe (health check) để thăm dò các backend vài giây một lần.

health_check_period = 10
health_check_timeout = 5
health_check_user = 'pgpool_check'
health_check_password = 'mat_khau_cua_ban'

# Script xử lý Failover
failover_command = '/etc/pgpool2/failover.sh %d %h %p %D %m %M %H %P'

Lệnh failover_command sẽ kích hoạt một shell script mà bạn tạo ra. Khi Node 1 bị sập, Pgpool-II thực thi script này để chạy lệnh pg_ctl promote trên Node 2. Việc này nâng cấp node standby lên trạng thái primary trong vòng chưa đầy 5 giây.

Kiểm tra thiết lập: “Hạ gục” thủ công

Đừng bao giờ tin vào một cấu hình mà bạn chưa từng cố ý làm hỏng. Tôi luôn mô phỏng một sự cố nghiêm trọng trong môi trường staging. Hãy dừng tiến trình PostgreSQL trên node primary và quan sát sự chuyển đổi.

# Trên Node 1
sudo systemctl stop postgresql

# Trên node Pgpool-II, theo dõi quá trình thăng cấp
tail -f /var/log/pgpool2/pgpool.log

Bạn sẽ thấy Pgpool-II đánh dấu Node 0 là ‘down’ và kích hoạt script failover. Ứng dụng của bạn có thể thấy một sự gián đoạn nhỏ khoảng 2 giây, nhưng nó sẽ tự động hoạt động trở lại ngay khi standby được thăng cấp.

Những bài học từ thực tế chiến trường

Tôi từng dành bốn giờ để debug lỗi "Permission Denied" mà hóa ra chỉ là do sự sai lệch đơn giản trong pool_hba.conf. Giống như pg_hba.conf của PostgreSQL, Pgpool-II có danh sách kiểm soát truy cập riêng. Hãy luôn giữ chúng đồng bộ. Ngoài ra, hãy cấu hình pcp.conf với mật khẩu đã mã hóa md5. Điều này cho phép bạn sử dụng pcp_attach_node để kết nối lại các node đã sửa lỗi mà không cần khởi động lại toàn bộ proxy.

Mở rộng quy mô không phải là ném thêm RAM vào một server duy nhất. Đó là về sự điều phối (orchestration). Pgpool-II cung cấp cho bạn các đòn bẩy để cân bằng tải và sống sót qua các lỗi phần cứng mà không làm bạn mất ngủ — hay mất dữ liệu.

Share: