Retry ngay lập tức và không giới hạn là cách nhanh nhất để biến một sự cố nhỏ thành sự cố lớn: service phía sau đang quá tải lại nhận thêm lưu lượng retry.
Exponential backoff — giãn khoảng chờ theo cấp số nhân (1s, 2s, 4s, 8s...) và chặn bằng trần maxDelay, cho hệ thống phía sau thời gian hồi phục.
Jitter — thêm ngẫu nhiên vào khoảng chờ. Nếu không có jitter, hàng nghìn consumer cùng lỗi tại một thời điểm sẽ cùng retry đúng mốc 1s, 2s, 4s và tạo ra các đợt tải dồn cục. Biến thể hay dùng là full jitter:
long delay = ThreadLocalRandom.current()
.nextLong(Math.min(maxDelay, base * (1L << attempt)));Phân loại lỗi trước khi retry:
- Lỗi tạm thời (timeout, 503, deadlock, mất kết nối) → retry.
- Lỗi vĩnh viễn (payload sai định dạng, validation fail, 400, bản ghi không tồn tại) → không retry, đẩy thẳng vào DLQ. Retry loại này chỉ đốt tài nguyên.
Kèm theo: giới hạn số lần (thường 3-5), gắn retry_count vào header message, retry ở tầng ngoài queue (queue retry riêng) thay vì Thread.sleep giữ luôn consumer, và luôn có đích đến cuối cùng là DLQ.