Tóm tắt: Kiến trúc hướng sự kiện chỉ đáng tin khi dữ liệu đã xác nhận không thể âm thầm mất sự kiện đi kèm.
Thuật ngữ chính: Outbox: bảng lưu sự kiện cùng giao dịch nghiệp vụ; relay: tiến trình chuyển sự kiện lên broker; idempotent: nhận lặp sự kiện nhưng chỉ tạo một kết quả.
Bài toán
Ghi cơ sở dữ liệu và gửi sự kiện là hai thao tác riêng. Nếu tiến trình dừng ở giữa, hệ thống có thể lưu dữ liệu nhưng mất sự kiện, hoặc gửi sự kiện cho dữ liệu chưa được xác nhận. Việc thử lại còn có thể tạo sự kiện trùng.
Vì sao cách làm đơn giản chưa đủ
Broker giúp tách thời gian xử lý và nhịp triển khai. Tuy nhiên, không tạo atomicity với cơ sở dữ liệu của ứng dụng. Nếu mặc định phát hành sẽ thành công sau commit, lỗi mất dữ liệu sẽ trở nên vô hình.
sự kiện là một interface sống lâu. Cách đặt tên, phiên bản, retention và người phụ trách cần kỷ luật tương đương API công khai.
Luồng xử lý
kiểm tra command→cơ sở dữ liệu
dữ liệu và outbox→Relay
phát hành có thử lại→bộ phận nhận sự kiện
tác động phụ idempotent
Quyết định kiến trúc
Commit ý định trước khi giao
Lưu sự kiện cạnh thay đổi nghiệp vụ. Relay có thể phát hành lại cho tới khi broker xác nhận.
bộ phận nhận sự kiện phải idempotent
Lưu mã sự kiện đã xử lý hoặc dùng inbox table trong cùng transaction với tác động phụ của bộ phận nhận sự kiện.
Giữ thứ tự theo aggregate
Partition theo aggregate ID và từ chối aggregate phiên bản cũ. Thay vì giả định toàn hệ thống có global ordering.
Phân tích chuyên sâu
sự kiện là sự thật, không phải command trá hình
OrderCreated thuộc order domain và mô tả điều đã xảy ra. SendEmailToCustomer lại buộc bộ phận phát sự kiện biết cách dịch vụ khác triển khai. Bộ phận nhận sự kiện nên tự quyết định phản ứng của mình.
Tương thích cần governance
Ưu tiên thay đổi schema dạng bổ sung, giữ nguyên ý nghĩa và có contract test. Không đưa dữ liệu nhạy cảm vào sự kiện khi retention và mọi đường truy cập chưa được phê duyệt.
Các bước triển khai
- Định nghĩa sự kiện là sự thật đã xảy ra, dùng thì quá khứ, không biến nó thành lời gọi hàm từ xa.
- Ghi thay đổi của aggregate và outbox trong cùng một transaction.
- phát hành bất đồng bộ và để mọi bộ phận nhận sự kiện chống xử lý trùng bằng mã sự kiện.
Ví dụ kỹ thuật: Tạo đơn hàng và phát sự kiện một cách atomic
BEGIN
INSERT INTO orders (...) VALUES (...)
INSERT INTO outbox(id, aggregate_id, type, payload)
VALUES (:eventId, :orderId, 'OrderCreated.v1', :payload)
COMMIT
relay.publish_unpublished(limit = 500)Chỉ đánh dấu outbox đã phát hành sau khi broker acknowledge. Lease giúp relay khác tiếp quản batch bị bỏ dở.
Các tình huống lỗi cần tính trước
- Relay dừng sau phát hành nhưng trước khi đánh dấu. Điều này khiến sự kiện được giao lại.
- Poison sự kiện chặn một partition. Cần quarantine kèm ngữ cảnh và đường replay có kiểm soát.
- bộ phận nhận sự kiện mới không tương thích schema và hiểu sai các sự kiện đang được lưu giữ.
Tín hiệu cần giám sát
| Tín hiệu | Ý nghĩa |
|---|---|
| Tuổi outbox chưa phát hành lớn nhất | Cho biết thay đổi đã commit bị vô hình ở downstream bao lâu. |
| bộ phận nhận sự kiện lag theo sự kiện type | Phân biệt một luồng nghiệp vụ chậm với tình trạng chung của broker. |
| Tỷ lệ duplicate và replay | Lộ ra relay bất ổn hoặc bộ phận nhận sự kiện chưa thực sự idempotent. |
Cách kiểm chứng thiết kế
- Dừng API ngay sau commit và chứng minh relay vẫn phát hành.
- Dừng relay sau broker acknowledge và chứng minh duplicate chỉ tạo một hiệu ứng nghiệp vụ.
- Replay sự kiện đã lưu bằng phiên bản bộ phận nhận sự kiện kế tiếp trước khi triển khai.
Kế hoạch triển khai an toàn
Bắt đầu với một tác động phụ ít rủi ro ở compare-only mode. Đối soát kết quả đồng bộ và hướng sự kiện, sau đó chuyển sang phản hồi ngay sau cơ sở dữ liệu commit. Hoàn thiện công cụ replay và dashboard người phụ trách trước khi thêm nhiều bộ phận nhận sự kiện.
Checklist trước khi đưa vào vận hành
- Hệ thống giao sự kiện ít nhất một lần. Hiệu ứng nghiệp vụ đúng một lần đến từ idempotency.
- Kiểm tra tương thích schema trước khi triển khai bộ phận phát sự kiện.
- Tuổi sự kiện và bộ phận nhận sự kiện lag là tín hiệu ảnh hưởng người dùng, không chỉ là số liệu của broker.
Kết luận
hướng sự kiện đáng tin cậy khi transaction ranh giới, quyền sở hữu và thử lại semantics đều được thể hiện rõ.
