Skip to content

ADR-0002. CDC (Debezium) làm seam tích hợp - Kafka chỉ producer

TrườngGiá trị
StatusAccepted
Ngày2026-03-15
Người quyết địnhPhat Nguyen
Thay thế-

Bối cảnh

  • Commerce là nguồn dữ liệu gốc cho catalog/tenant. Nhiều dịch vụ cần dữ liệu của nó: search (đánh chỉ mục products/merchants/categories), inventory (khởi tạo locations + items), pricing (khởi tạo fares), taxation (cấp phát nhóm thuế), invoice (suy ra TaxInfo).
  • Việc phát Kafka ở tầng ứng dụng sẽ buộc commerce phải biết mọi hợp đồng phía hạ nguồn, phát một topic cho mỗi dạng thay đổi, và giữ cho code phát sự kiện luôn đồng bộ với mọi thay đổi dữ liệu catalog trên nhiều dịch vụ - gắn kết cao và dễ bỏ sót một đường ghi.
  • Postgres vốn đã ghi lại mọi thay đổi trong WAL. Debezium có thể nắm bắt thay đổi đó một cách tổng quát.

Quyết định

Dùng CDC (Debezium) làm seam tích hợp chính. Nghĩa vụ duy nhất của commerce là ghi đúng vào Postgres; Debezium đọc WAL và publish một topic cho mỗi bảng (CDCKafkaTopics / CdcTables trong @nx/core, ví dụ public.Merchant, public.ProductVariant).

  • Các consumer phía hạ nguồn (search/inventory/pricing/taxation/invoice) tự lo phần đấu nối CDC consumer của riêng mình.
  • ApplicationKafkaComponent của commerce chỉ ràng buộc một producer - và trên thực tế không gọi .send() ở bất cứ đâu trong src/. Có khai báo một khóa ràng buộc APPLICATION_KAFKA_CONSUMER nhưng không có consumer nào được đấu nối.
  • CDC consumer duy nhất mà chính commerce chạy là ApplicationCdcComponent (từ @nx/search, vai trò WORKER) để đồng bộ DB của chính nó vào Typesense.
  • Thông tin thuế của merchant là ví dụ điển hình cho mẫu hình này: ghi vào Merchant.metadata.tax, được CDC nắm bắt, rồi được @nx/invoice upsert vào TaxInfo (nguồn đọc chuẩn ở phía hạ nguồn).

Hệ quả

ƯuNhược
Không cần code phát sự kiện riêng cho từng consumer trong commerce; consumer mới gắn vào mà không phải sửa commerceConsumer gắn chặt với schema của bảng - đổi tên cột sẽ gây phá vỡ
Không có rủi ro "quên phát sự kiện trên đường ghi này"CDC thêm Debezium/Kafka Connect thành phụ thuộc vận hành
Thứ tự WAL + replay theo offset cho phép phân phối bền, có thể phát lạiNhất quán sau cùng; consumer phải idempotent theo từng PK
Producer được giữ lại để dùng về sau mà không ép phải dùng ngayMột producer đã ràng buộc nhưng nhàn rỗi có thể gây nhầm lẫn cho người mới (đã ghi chú ở đây)

Phương án đã cân nhắc

Tùy chọnƯuNhượcVì sao bị từ chối
Phát Kafka ở tầng ứng dụng theo từng thay đổiPayload tường minh, được chọn lọcGắn kết cao; phải cài đặt cho mọi đường ghi trong mọi dịch vụDễ vỡ; phá vỡ tính đơn giản của nguồn dữ liệu gốc
Phát tán HTTP đồng bộ trên mỗi thay đổi dữ liệuTức thìGắn kết chặt lúc chạy; lỗi lan tỏa dây chuyền; ghi chậmPhạm vi ảnh hưởng không chấp nhận được
Bảng outbox + relayĐảm bảo tính giao dịchPhát minh lại thứ mà Debezium đã cung cấp miễn phí trên WALDebezium đã bao quát rồi

Tham khảo

  • packages/core/src/common/cdc/tables.ts (CdcTables)
  • packages/core/src/common/kafka/topics.ts (CDCKafkaTopics)
  • src/components/kafka/component.ts (producer được ràng buộc, không gọi .send())
  • src/common/keys.ts (APPLICATION_KAFKA_CONSUMER được khai báo, không dùng)
  • src/services/merchant.service.ts (tax → metadata.tax → CDC → TaxInfo)

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.