PostgreSQL Bài 35: Logical Replication: Cơ chế Publish/Subscribe và ứng dụng nâng cấp Zero-Downtime
Khác với Physical Replication (sao chép vật lý bit-by-bit toàn bộ cluster) ở Bài 34, Logical Replication (Sao chép logic) cho phép bạn kiểm soát chính xác từng luồng dữ liệu ở cấp độ bảng (Table-level) hoặc thậm chí cấp độ dòng (Row-level).
Cơ chế này bóc tách nội dung của WAL (Write-Ahead Log), giải mã các khối nhị phân thành các câu lệnh SQL logic nguyên thủy (INSERT, UPDATE, DELETE) trước khi gửi đi.
1. Kiến trúc Publish / Subscribe
Logical Replication hoạt động dựa trên mô hình Pub/Sub:
-
Publisher (Máy phát): Cấu hình trên máy chủ nguồn. Chỉ định danh sách các bảng sẽ phát dữ liệu thông qua đối tượng
PUBLICATION. -
Subscriber (Máy thu): Cấu hình trên máy chủ đích. Khai báo một
SUBSCRIPTIONkết nối đến Publisher để nhận dữ liệu của các bảng tương ứng.
[ DATABASE A - Publisher ] [ DATABASE B - Subscriber ]
(PostgreSQL 14) (PostgreSQL 16)
Table: users, orders (PUBLICATION) ──►─── Table: users, orders (SUBSCRIPTION)
Table: logs (Bỏ qua) Table: analytics_data (Bảng riêng cục bộ)
2. Thiết lập Logical Replication thực chiến
2.1. Cấu hình phía Publisher (Máy nguồn)
Bắt buộc phải đổi tham số wal_level trong postgresql.conf thành logical (cấp độ lưu log chi tiết nhất, tốn dung lượng hơn replica).
Ini, TOML
wal_level = logical
(Khởi động lại database để áp dụng).
Tạo Publication cho các bảng nghiệp vụ cốt lõi:
SQL
-- Tạo Publication cho toàn bộ các bảng trong DB (Cẩn thận tài nguyên)
CREATE PUBLICATION all_tables_pub FOR ALL TABLES;
-- Hoặc tạo Publication chỉ định một vài bảng cụ thể
CREATE PUBLICATION core_pub FOR TABLE users, orders;
-- Lọc dữ liệu (Row Filter) từ PostgreSQL 15+: Chỉ phát đi đơn hàng lớn
CREATE PUBLICATION vip_orders_pub FOR TABLE orders WHERE (total_amount > 10000);
2.2. Cấu hình phía Subscriber (Máy đích)
Trên máy đích, các bảng users, orders phải được tạo sẵn cấu trúc DDL (CREATE TABLE...) y hệt hoặc tương thích với máy nguồn. Logical Replication không tự động đồng bộ cấu trúc bảng.
SQL
-- Tạo Subscription kết nối đến Publisher
CREATE SUBSCRIPTION core_sub
CONNECTION 'host=192.168.1.100 port=5432 dbname=mydb user=repl_user password=secret'
PUBLICATION core_pub;
Ngay khi lệnh này chạy thành công, máy Subscriber sẽ tự động thực hiện Initial Sync (copy toàn bộ dữ liệu hiện có từ Publisher), sau đó chuyển sang chế độ theo dõi thời gian thực (Streaming) để nhận các cập nhật mới.
3. Logical Decoding và Kiến trúc Event-Driven Microservices (CDC)
Logical Replication không chỉ dùng để đồng bộ giữa hai máy chủ PostgreSQL. Lõi của nó là plugin Logical Decoding (đặc biệt là pgoutput hoặc wal2json), cho phép các ứng dụng bên thứ ba đóng vai trò làm Subscriber để "hứng" luồng dữ liệu thay đổi (Change Data Capture - CDC).
Trong kiến trúc hệ thống hiện đại, thay vì các service gọi API trực tiếp với nhau (gây độ trễ và thắt cổ chai), bạn có thể dùng Debezium kết nối vào PostgreSQL như một Logical Subscriber.
-
Debezium đọc luồng Logical Replication.
-
Chuyển đổi các sự kiện
INSERT/UPDATE/DELETEthành các message chuẩn. -
Bắn thẳng vào các topic trên Apache Kafka.
-
Các microservices backend (viết bằng Go, PHP...) chỉ việc consume các event message này từ Kafka để cập nhật Redis cache, đồng bộ Elasticsearch, hoặc kích hoạt pipeline nghiệp vụ tiếp theo một cách hoàn toàn bất đồng bộ.
4. Các kịch bản ứng dụng tối thượng của Logical Replication
-
Nâng cấp phiên bản PostgreSQL không gián đoạn (Zero-Downtime Upgrade):
-
Physical replication không cho phép máy Master và Slave khác phiên bản (ví dụ Master PG 12, Slave PG 16).
-
Logical Replication thì có! Bạn dựng một máy PG 16 trống, làm Subscriber kéo dữ liệu từ máy PG 12. Khi dữ liệu đuổi kịp, bạn đổi chuỗi kết nối của ứng dụng sang máy PG 16. Downtime chỉ là vài giây reload của ứng dụng.
-
-
Đồng bộ hóa dữ liệu tập trung (Data Consolidation):
- Có 5 database ở 5 chi nhánh (Shards). Muốn tổng hợp toàn bộ bảng
salesvề một Data Warehouse trung tâm để phân tích. Bạn tạo 5 Subscription trên máy trung tâm trỏ về 5 Publisher chi nhánh.
- Có 5 database ở 5 chi nhánh (Shards). Muốn tổng hợp toàn bộ bảng
-
Chia sẻ một phần dữ liệu cho đối tác:
- Bạn có bảng
userschứa thông tin nhạy cảm. Bạn tạo Column/Row Filter trongPUBLICATIONđể chỉ gửi các cộtid,name,emailsang một database khác phục vụ cho team Marketing, cách ly hoàn toàn vùng dữ liệu lõi.
- Bạn có bảng
5. Những giới hạn chết người cần lưu ý
Dù linh hoạt, Logical Replication mang theo những "cạm bẫy" lớn nếu không hiểu rõ ranh giới của nó:
-
Không đồng bộ cấu trúc (DDL): Nếu bạn chạy
ALTER TABLE users ADD COLUMN age INT;trên Publisher, máy Subscriber sẽ không tự động có cộtage. Dữ liệu mới gửi sang sẽ báo lỗi lệch schema và làm sập tiến trình đồng bộ. Bạn phải tự chạy lệnh DDL trên cả 2 máy. -
Không đồng bộ Sequence: Lệnh sinh ID tự tăng (như
nextval()) không được ghi vào WAL. Sau khi bạn chuyển traffic sang máy Subscriber, bạn bắt buộc phải cập nhật lại Sequence theo giá trị MAX hiện tại (setval), nếu không sẽ bị kẹt lỗiduplicate key. -
Bắt buộc phải có Replica Identity: Để máy Subscriber biết phải
UPDATE/DELETEdòng nào, bảng bắt buộc phải có Khóa chính (PRIMARY KEY) hoặc Khóa phụ duy nhất (UNIQUE INDEX). Nếu bảng không có, bạn phải cấu hìnhREPLICA IDENTITY FULL(ép PostgreSQL ghi lại toàn bộ giá trị các cột của dòng đó vào WAL), điều này làm phình to file WAL và làm chậm hệ thống đáng kể. -
Nguy cơ phình to Replication Slot: Khi máy Subscriber bị tắt hoặc đứt mạng, máy Publisher sẽ giữ lại toàn bộ file WAL chưa được gửi đi (thông qua cơ chế Replication Slot). Nếu đứt mạng quá lâu, ổ cứng máy Publisher sẽ bị lấp đầy 100% bởi các file WAL cũ, dẫn đến sập toàn bộ database chính.
All rights reserved