Consumer acknowledgements và publisher confirms
Publisher confirm bảo vệ hop producer → broker; consumer acknowledgement bảo vệ hop broker → consumer. Hai cơ chế độc lập và không chứng minh side effect trong application database đã commit.
1. Hai delivery lifecycles độc lập
producer -- publish + confirm --> exchange / queue
queue -- delivery + ack ----> consumer / business database
Confirm trả lời broker đã xử lý publish đến mức nào theo queue/storage configuration. Ack trả lời consumer đã xử lý delivery và broker có thể quên nó. Không có transaction tự động xuyên cả producer DB, broker và consumer DB; mỗi boundary cần protocol hoặc pattern riêng.
EN interview answer · Confirm vs acknowledgement
Publisher confirms protect the producer-to-broker handoff, while consumer acknowledgements protect broker-to-consumer processing. They solve different failure windows. I still design consumers to be idempotent because redelivery can occur.
2. Consumer acknowledgement và redelivery
Mỗi delivery có delivery tag tăng dần và chỉ có ý nghĩa trong channel nhận nó. basic.ack, basic.nack hoặc basic.reject phải gửi trên cùng channel; ack bằng channel khác gây protocol exception. Multiple ack có thể xác nhận mọi tag đến một mốc, nên correlation sai có thể mất nhiều delivery.
| Thời điểm ack | Crash window | Kết quả |
|---|---|---|
| Trước business commit | Crash sau ack, trước commit | Broker xóa delivery; work có thể mất |
| Sau business commit | Crash sau commit, trước ack | Broker redeliver; side effect có thể lặp |
| Auto ack khi dispatch | Consumer chết khi đang xử lý | Không redelivery; phù hợp work có thể bỏ |
| Nack/reject requeue | Poison message quay lại ngay | Hot loop nếu không có retry policy |
redelivered chỉ là hint broker biết delivery có thể đã gửi trước đó; false không chứng minh business event chưa từng xử lý, và true không thay deduplication.
3. Publisher confirms và unknown outcome
Confirm mode gán sequence cho publishes; broker gửi ack/nack riêng lẻ hoặc theo batch. Producer throughput tốt hơn khi publish pipeline rồi correlate confirmations, thay vì chờ từng message synchronously. Cần giới hạn in-flight set, timeout, nack handling và recovery khi channel/connection đóng.
Publisher confirms không atomic với application DB. AMQP transactions có overhead lớn và vẫn không gộp broker transaction với database transaction; transactional outbox giải quyết dual-write bằng cách commit business change + outbox record cùng DB transaction rồi relay ra broker.
4. Durability scope của confirm
Ý nghĩa durability phụ thuộc queue type, replication, durable declaration và persistent message. Confirm cho transient message hoặc non-durable queue không biến nó thành durable. Với replicated queue, confirm timing tuân theo implementation/queue semantics; application phải chọn cấu hình theo tolerated loss và latency.
- Unroutable publish và publisher confirm là hai tín hiệu khác nhau.
- Nack hiếm nhưng phải được xử lý và quan sát.
- Batch confirm giảm overhead nhưng tăng số message có outcome chưa biết khi channel fail.
- Sequence map phải được cleanup để không leak memory khi timeout/recovery.
5. Prefetch, throughput và fairness
Prefetch giới hạn số unacknowledged deliveries consumer/channel được giữ, tạo backpressure giữa broker và worker. Quá cao làm một consumer chiếm backlog, tăng memory và số work phải redeliver khi crash; quá thấp tăng round-trip và để worker nhàn.
Ước lượng ban đầu dựa processing latency × desired throughput/concurrency, rồi đo. Payload lớn, processing variance cao và strict fairness thường cần prefetch thấp hơn. Per-consumer và global channel limits có semantics/cost khác; kiểm client/broker version đang dùng.
6. Idempotency và bằng chứng vận hành
Lưu message ID hoặc business idempotency key bằng unique constraint trong cùng transaction với side effect. Pattern check-then-insert tách rời có race khi hai deliveries xử lý đồng thời. Với external side effect, truyền idempotency key xuống downstream hoặc thiết kế state transition conditional.
Pseudocode · Idempotent consumer: unique key và business change nằm trong cùng local transaction; ack/offset commit là bước sau đó.
begin transaction
insert processed_message(event_id) -- unique
apply business change
commit
ack/commit offset
Theo dõi publish confirms/nacks/timeouts, unconfirmed count/age, unacked deliveries, redelivery rate, consumer utilization, processing latency và duplicate suppression. Test bằng cách kill process ở từng điểm trước/sau DB commit và trước/sau ack/confirm.