Lập trình 22/09/2026 7 phút

Vì sao cần hàng đợi tin nhắn: đo thật việc tách rời producer khỏi consumer theo thời gian

Gọi service trực tiếp thì caller bị chặn tới khi downstream xong — và sập theo nếu nó chết. Hàng đợi đảo ngược điều đó. Bài này đo thật trên Kafka: producer đẩy 100.000 message ở 377.000 msg/s, chỉ chờ broker ack 1.49ms mà KHÔNG cần consumer nào tồn tại; 100.000 message nằm chờ an toàn trong topic; rồi một consumer đến muộn đọc hết và bắt kịp về lag 0. Đó là tách rời theo thời gian.

Lập trình 22/09/2026 7 phút

At-most-once, at-least-once, exactly-once: đo thật message bị mất và bị trùng

Ba ngữ nghĩa giao nhận nghe trừu tượng cho tới khi bạn mất tiền của khách vì xử lý đơn hai lần. Bài này chạy thật trên Kafka với 1000 message đánh số: at-least-once cho đọc lại khi chưa commit — trùng đúng 1000; at-most-once dời offset vượt trước xử lý — mất đúng 1000 (mà LAG vẫn báo 0, 'khoẻ' giả); idempotent producer ghi đúng 1000 không trùng. Khác biệt nằm gọn ở chỗ commit offset trước hay sau khi xử lý.

Lập trình 22/09/2026 7 phút

Consumer group và partition: mở rộng throughput, và vì sao thêm consumer có trần

Consumer xử lý không kịp? Thêm consumer. Nhưng không phải thêm bao nhiêu cũng nhanh hơn. Bài này chạy thật trên Kafka topic 6 partition: 3 consumer trong một group chia đều mỗi cái 2 partition; nhưng khi lên 7 consumer trên 6 partition, consumer thứ 7 nhận đúng 0 partition — ngồi không, lãng phí. Partition là đơn vị song song thật, và nó là trần cứng của việc scale consumer.

Lập trình 22/09/2026 7 phút

Idempotency: xử lý message trùng mà vẫn đúng — demo trừ tiền hai lần và cách chặn

At-least-once chắc chắn sẽ giao message trùng. Nếu consumer cứ thế xử lý, khách bị trừ tiền hai lần. Bài này chạy thật: 1000 thanh toán được Kafka giao 2000 lượt (1000 trùng); consumer ngây thơ cộng ra 200.000 — sai gấp đôi; consumer idempotent dùng redis SETNX khử trùng theo id, chỉ xử lý 1000 lượt duy nhất, ra đúng 100.000. At-least-once + idempotency an toàn như exactly-once mà rẻ hơn.

Lập trình 22/09/2026 7 phút

Outbox pattern: vì sao ghi database rồi publish message là cái bẫy mất dữ liệu

Service ghi đơn hàng vào database rồi publish message sang Kafka — hai bước riêng. Nếu crash giữa hai bước, database có đơn mà message biến mất. Bài này chạy thật: dual-write để lệch 40/100 đơn; outbox pattern ghi business row và outbox row trong cùng một transaction PostgreSQL, relay đọc và publish — khớp 100%, và relay chạy lại vẫn an toàn. Chìa khoá là tính nguyên tử của database.

Lập trình 22/09/2026 8 phút

Dead Letter Queue: một message độc không được phép giữ con tin cả hàng đợi

Một message hỏng không xử lý nổi mà consumer cứ retry mãi sẽ chặn đứng mọi message sau nó. Bài này chạy thật trên Kafka: 10 message với 2 cái độc ở vị trí 3 và 7 — consumer không có DLQ kẹt tại message độc đầu tiên, chỉ xử lý được 2/10; consumer có DLQ tách 2 message độc sang topic riêng sau vài lần retry, xử lý trọn 8 message tốt và hàng đợi không kẹt.