Designing Clear Street's First Transactional Outbox Pattern

Bài tóm tắt Clear Street 2020 1. Khởi đầu Độ khó: Trung bình

Clear Street · 2020 · 1. Khởi đầu · Độ khó: Trung bình — bài gốc

Bài ngoài sheet. Clear Street là công ty hạ tầng môi giới chứng khoán (thành lập 2018). Bài hứa có phần sau kể các vấn đề gặp phải, nhưng wiki chưa tìm thấy (kiểm 2026-10-19).

Bối cảnh

  • Từ khi bắt đầu năm 2018, mỗi microservice có hai API: gRPC cho CRUD, và một API streaming qua Kafka phát lại chính các thay đổi đó để service phía sau khỏi phải poll.
  • Bài toán: thao tác CRUD nằm trong một giao dịch PostgreSQL, còn publish lên Kafka là tác dụng phụ; làm sao để Kafka không lệch với DB khi có lỗi. Theo Clear Street, 2PC giải được về nguyên tắc nhưng chậm và phức tạp.

Thay đổi chính

  • CDC bằng Debezium: đọc WAL của Postgres và đẩy thay đổi lên Kafka; giao dịch commit thì thay đổi chắc chắn được phát, không phải tự xử lý các ca lỗi.
  • Nhưng không phát thẳng bảng nội bộ: CDC thô đưa nguyên mô hình lưu trữ của service lên Kafka, phá đóng gói và trói API streaming vào schema DB. Họ thêm một lớp outbox:
    • Debezium chỉ nghe các bảng có hậu tố events.
    • Mọi event là message Avro; người viết service tự dựng message và ghi nó vào bảng …-events trong cùng giao dịch với thay đổi dữ liệu, kèm schema_id của Schema Registry và số partition Kafka đích.
    • Hai transformer tự viết cho Kafka Connect (EventConverter, EventRouter) bóc message Avro khỏi dòng được chèn và đẩy vào đúng partition.
  • Đã chạy ở production khoảng hai năm (2018–2020). Phần lớn công sức tuỳ biến là để API streaming không dính vào DB, nên phải mã hoá/giải mã Avro trong đường đi của Debezium.

Vì sao

  • Outbox giữ được hai thứ cùng lúc: tính nguyên tử (event được ghi trong cùng giao dịch với dữ liệu) và đóng gói (người viết service chọn rõ khi nào phát, phát trường nào).

Bài học cho SWE

  • CDC thô là cách nhanh nhất để có event, nhưng biến schema DB thành hợp đồng công khai; outbox là lớp đệm rẻ.
  • Đặt quy ước (hậu tố bảng, schema chuẩn) để công cụ chung xử lý mọi service giống nhau.
  • Bài chưa kể sự cố hay chi phí vận hành (bảng outbox phình, connector lỗi, đổi schema); đó vẫn là phần thiếu.

Liên quan