Bỏ qua để đến nội dung
Knowledge Hub

Thiết kế: tách checkout đồng bộ sang bất đồng bộ Trung cấp

Thời gian đọc ước tính: 1 phút

Checkout đang làm mọi thứ trong một request: p99 3,5 s, email provider sập là không ai mua được hàng. Kéo thành phần vào bốn tầng để đưa side effect ra khỏi request mà không mất event, không gửi trùng.

  • Mục tiêu: đạt mọi yêu cầu trong ngân sách độ phức tạp.
  • Thử thêm: tìm một thiết kế dùng RabbitMQ và một thiết kế dùng Kafka + CDC. Rồi thử “publish sau COMMIT” thay cho outbox xem số event mất đổi thế nào.
Thiết kế

Tách checkout đồng bộ thành luồng bất đồng bộ không mất event

POST /checkout hiện làm tuần tự trong một request: tạo order, charge PSP, gửi email, cộng điểm loyalty, push analytics. Kết quả: p99 ~3,5 s, email provider sập là checkout sập, deploy cắt ngang thì có đơn không có email hay điểm.

Payment phải giữ đồng bộ: khách cần biết đã trả tiền chưa. Mọi thứ khác có thể chạy sau. Checkout API và PostgreSQL đã có sẵn; bạn thêm thành phần quanh chúng.

Giả định để chơi: DB ~40 ms, PSP p99 ~700 ms khi có timeout (~2,2 s khi không), email ~900 ms, loyalty ~120 ms, analytics ~300 ms. Số mất/trùng tính trên 10k đơn trong một ngày có 2 lần deploy và email provider sập 30 phút. Số liệu minh hoạ, không phải benchmark.

Yêu cầu

  • p99 POST /checkout ≤ 1.000 ms; payment vẫn đồng bộ, có timeout và idempotency key
  • Email provider sập: 0 checkout lỗi
  • 0 side effect mất và 0 side effect trùng / 10k đơn
  • Email xác nhận tới trong ≤ 60 s khi mọi thứ bình thường
  • Độ phức tạp ≤ 14 đơn vị

Bấm + Thêm ở từng tầng để chọn thành phần. Trên máy tính có thể kéo thành phần thả vào tầng. Chỉ số cập nhật ngay.

Chạm một thành phần để xem nó làm gì.

Người dùng Client
Checkout API POST /checkout🔒
PostgreSQL orders, payments🔒
MessagingBroker, CDC, retry/DLQ
Worker nềnProcess chạy ngoài request
p99 checkout3.560 ms
Checkout lỗi khi email sập100 %
Side effect mất / 10k đơn3
Side effect trùng / 10k đơn5
Độ trễ email1 s
Độ phức tạp0 đv
  • Gọi PSP không timeout: mỗi lần PSP chậm, request treo theo nó, p99 lên ~2.200 ms và worker pool cạn.
  • Không có idempotency key: app mobile retry khi mạng chập chờn tạo đơn và charge trùng (~5/10k đơn).
  • email xác nhận vẫn chạy đồng bộ trong request: +900 ms p99, và email provider sập là checkout sập theo; process chết giữa chừng thì việc này mất.
  • cộng điểm loyalty vẫn chạy đồng bộ trong request: +120 ms p99; process chết giữa chừng thì việc này mất.
  • push analytics vẫn chạy đồng bộ trong request: +300 ms p99; process chết giữa chừng thì việc này mất.

Vì sao outbox chống mất nhưng không chống trùng, và relay polling khác CDC ra sao: Transactional outbox.