TopDev AI Robot TopDev
#Backend & Microservices#Cơ sở dữ liệu & Tối ưu#Kiến trúc & System Design

Xử lý Outbox Pattern trong Microservices: Đảm bảo tính nhất quán giữa Database và Message Broker

Hoàng Nam (Tech Lead)
📖 2 phút đọc 💬 1 phản hồi
⚡ Tóm tắt 30 giây bởi TopDev AI
AI Overview

Cơn ác mộng phân tán: DB lưu thành công nhưng Message Broker sập Hãy xem xét đoạn code tưởng chừng rất bình thường sau: Nếu bước 1 thành công nhưng bước 2 bị fail do Kafka cluster rớt mạng hoặc serve…

☰ Mục lục bài viết (4 phần) Mở / Đóng mục lục

Cơn ác mộng phân tán: DB lưu thành công nhưng Message Broker sập#

Hãy xem xét đoạn code tưởng chừng rất bình thường sau:

TYPESCRIPT
await db.transaction(async (trx) => {
  await orderService.createOrder(trx, orderData); // 1. Lưu đơn hàng vào DB
});

// 2. Gửi message thông báo sang Kafka để trừ tiền
await kafkaProducer.send('order_events', { event: 'ORDER_CREATED', orderId });

Nếu bước 1 thành công nhưng bước 2 bị fail do Kafka cluster rớt mạng hoặc server bị crash đột ngột? Đơn hàng đã được lưu nhưng không ai trừ tiền hay gửi hàng, hệ thống rơi vào trạng thái dữ liệu bất nhất (Data Inconsistency).

Nếu đảo ngược lại (gửi Kafka trước rồi lưu DB sau)? Nếu lưu DB fail, bạn lại phát đi một event giả mạo!

Giải pháp chuẩn mực: Transactional Outbox Pattern#

Ý tưởng cốt lõi: Thay vì gửi trực tiếp sang Kafka, hãy ghi sự kiện cần phát vào một bảng tạm có tên là outbox_events nằm TRONG CÙNG TRANSACTION của database chính!

SQL
-- Bảng Outbox nằm chung trong cơ sở dữ liệu
CREATE TABLE outbox_events (
    id UUID PRIMARY KEY,
    aggregate_type VARCHAR(255) NOT NULL,
    aggregate_id VARCHAR(255) NOT NULL,
    event_type VARCHAR(255) NOT NULL,
    payload JSONB NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    processed_at TIMESTAMPTZ
);

Vì cùng nằm trong 1 Transaction của PostgreSQL, hoặc cả đơn hàng và event cùng được lưu, hoặc cả hai cùng bị rollback!

Làm thế nào để đẩy dữ liệu từ Outbox sang Kafka?#

Có 2 cách:

  1. Polling Publisher (Đơn giản): Dùng một worker chạy ngầm định kỳ query SELECT ... FROM outbox_events WHERE processed_at IS NULL LIMIT 100 rồi đẩy sang Kafka.
  2. Change Data Capture (CDC - Đỉnh cao): Sử dụng công cụ Debezium đọc trực tiếp WAL (Write-Ahead Log) của PostgreSQL và tự động stream vào Kafka mà không cần chạm vào bảng.

Góc thảo luận#

Hệ thống microservices của bạn giải quyết bài toán giao dịch phân tán (Distributed Transaction) bằng cách nào? Bạn chuộng dùng Outbox Pattern hay Saga Pattern?


Xem thêm nội dung liên quan:

Chia sẻ thảo luận này:

Thảo luận

1 phản hồi

Ý kiến từ cộng đồng kỹ sư TopDev
💬

Tham gia thảo luận

Cộng đồng mở · Đăng nhập 1-chạm qua Google
  1. Thu Trang (Backend Engineer)
    #1

    Outbox Pattern kết hợp với Debezium đọc WAL Postgres là giải pháp chuẩn không cần chỉnh! Vừa đảm bảo tính nhất quán 100%, vừa không làm tăng tải query SELECT polling vào database chính.

Bài liên quan trong #Backend & Microservices

1
TopDev AI Companion
AI
✓ Đã sao chép link