┌─────────────────────────────────────────────────────────────────┐│ STANDARD vs FIFO QUEUE │├─────────────────────────────────────────────────────────────────┤│ ││ STANDARD QUEUE: ││ ┌─────────────────────────────────────────────────────────┐ ││ │ Send: A → B → C → D │ ││ │ Receive: A → C → B → A → D (Best-effort ordering) │ ││ │ ↑ │ ││ │ Có thể trùng! │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ FIFO QUEUE: ││ ┌─────────────────────────────────────────────────────────┐ ││ │ Send: A → B → C → D │ ││ │ Receive: A → B → C → D (Exact ordering) │ ││ │ │ ││ │ Exactly-once processing │ ││ └─────────────────────────────────────────────────────────┘ ││ │└─────────────────────────────────────────────────────────────────┘
300 API calls/s per action (batch 10: ~3000 msg/s)
Ordering
Best-effort
Guaranteed (FIFO)
Delivery
At-least-once
Exactly-once
Deduplication
No
Yes (5 min window)
Queue Name
Any
Must end with .fifo
Use Case
High throughput
Ordering important
[!TIP]
Per action trong FIFO nghĩa là gì?
300 API calls/s per action nghĩa là mỗi nhóm API có quota riêng:
SendMessage / SendMessageBatch
ReceiveMessage
DeleteMessage / DeleteMessageBatch
Trong AWS docs, quota mặc định này áp trên từng partition của FIFO queue (non-high throughput mode)
Throughput messages phụ thuộc batch size:
Batch 1 (không batch): ~300 msg/s
Batch 2: ~600 msg/s
Batch 4: ~1200 msg/s
Batch 10: ~3000 msg/s
Công thức nhanh: messages/s ≈ requests/s × batch_size
[!NOTE]
Các con số trên là baseline FIFO thường dùng trong exam (non-high throughput FIFO).
SQS FIFO High Throughput mode có quota cao hơn và phụ thuộc Region.
[!WARNING]
Best-effort Ordering nghĩa là gì?
SQS Standard Queue là distributed system (nhiều servers). Messages phân tán trên nhiều servers nên thứ tự KHÔNG ĐẢM BẢO:
Gửi: [1] → [2] → [3] → [4] → [5]Nhận: [2] → [1] → [4] → [3] → [5] (có thể sai thứ tự!)
"Best-effort" = SQS cố gắng giữ thứ tự, nhưng không hứa.
[!CAUTION]
Duplicate Processing - Khi Visibility Timeout hết trong lúc đang xử lý
T=0s: Consumer A nhận message, bắt đầu xử lýT=30s: Visibility Timeout HẾT HẠN (A vẫn đang xử lý)T=31s: Message VISIBLE lại → Consumer B nhận đượcKẾT QUẢ: CẢ A VÀ B ĐANG XỬ LÝ CÙNG 1 MESSAGE!
Giải pháp:
Set Visibility Timeout > thời gian xử lý
Gọi ChangeMessageVisibility API để extend timeout
Code consumer phải IDEMPOTENT (chạy 2 lần = kết quả giống nhau)
┌─────────────────────────────────────────────────────────────────┐│ FIFO QUEUE CONCEPTS │├─────────────────────────────────────────────────────────────────┤│ ││ MESSAGE GROUP ID: ││ ┌─────────────────────────────────────────────────────────┐ ││ │ Group "OrderA": [1] → [2] → [3] (Processed in order) │ ││ │ Group "OrderB": [1] → [2] → [3] (Parallel processing) │ ││ │ Group "OrderC": [1] → [2] → [3] (Different consumer) │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ → Messages cùng Group ID được xử lý theo thứ tự ││ → Khác Group ID có thể xử lý parallel ││ ││ DEDUPLICATION ID: ││ ┌─────────────────────────────────────────────────────────┐ ││ │ Message với cùng Deduplication ID trong 5 phút │ ││ │ sẽ bị reject (prevent duplicates) │ ││ └─────────────────────────────────────────────────────────┘ ││ │└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐│ HOT PARTITION PROBLEM │├─────────────────────────────────────────────────────────────────┤│ ││ Group "VIP-Customer": [1][2][3]...[1000] ← HOT! 🔥 ││ Group "Normal-1": [1][2] ← bình thường ││ Group "Normal-2": [1] ← bình thường ││ ││ Vấn đề: VIP-Customer có 1000 msgs nhưng chỉ xử lý 1 lúc 1! ││ → BOTTLENECK! ││ ││ Giải pháp: Chia nhỏ Group ID ││ ─────────────────────────── ││ ❌ Trước: Group ID = "customer-123" ││ ✅ Sau: Group ID = "customer-123-order-456" ││ ││ → Mỗi order là 1 group riêng → scale tốt hơn ││ │└─────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐│ KHI CONSUMER XỬ LÝ MESSAGE FAIL │├──────────────────────────────────────────────────────────────────┤│ ││ Timeline: ││ ┌─────────┬──────────────────────────┬────────────────────────┐││ │ Receive │ Visibility Timeout │ Message visible lại │││ │ Message │ (message invisible) │ trong queue │││ └─────────┴──────────────────────────┴────────────────────────┘││ ↓ ↓ ││ Consumer nhận Consumer khác ││ message & FAIL có thể nhận lại ││ ││ Retry Flow: ││ ┌─────────────────────────────────────────────────────────┐ ││ │ Receive 1 → Fail → Visible lại │ ││ │ Receive 2 → Fail → Visible lại │ ││ │ Receive 3 → Fail → Visible lại │ ││ │ ... │ ││ │ Receive N (= maxReceiveCount) → Fail → CHUYỂN ĐẾN DLQ │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ ⚠️ Lưu ý: ││ • Message KHÔNG tự động bị xóa khi fail ││ • Visibility Timeout hết → message quay lại queue ││ • Consumer khác (hoặc chính nó) có thể nhận lại ││ • Sau maxReceiveCount lần fail → chuyển sang DLQ ││ │└──────────────────────────────────────────────────────────────────┘
[!IMPORTANT]
Tự động scale consumer là key pattern để SQS hoạt động hiệu quả với workload biến động. AWS cung cấp các SQS metrics trong CloudWatch để bạn có thể setup Auto Scaling.
[!TIP]
AWS Recommended Metric: Thay vì dùng ApproximateNumberOfMessagesVisible đơn thuần, AWS khuyến nghị tính Backlog per Instance để scale chính xác hơn.
┌─────────────────────────────────────────────────────────────────┐│ BACKLOG PER INSTANCE │├─────────────────────────────────────────────────────────────────┤│ ││ Công thức: ││ ┌─────────────────────────────────────────────────────────┐ ││ │ ApproximateNumberOfMessagesVisible │ ││ │ Backlog = ───────────────────────────────────────── │ ││ │ Current Number of Consumers │ ││ └─────────────────────────────────────────────────────────┘ ││ ││ Ví dụ: ││ • Queue có 1000 messages ││ • Có 5 consumers ││ • Backlog per instance = 1000 / 5 = 200 msgs/consumer ││ ││ Target: ││ • Nếu mỗi consumer xử lý 50 msgs/phút ││ • Target backlog = 100 (≈ 2 phút xử lý) ││ • Khi backlog > 100 → Scale OUT ││ • Khi backlog < 100 → Scale IN ││ │└─────────────────────────────────────────────────────────────────┘
@Componentpublic class OrderConsumer { @SqsListener("order-queue") public void processOrder(String message) { log.info("Received order: {}", message); // Xử lý order orderService.process(message); // Message tự động được delete sau khi method return success } // Hoặc với object mapping: @SqsListener("order-queue") public void processOrder(Order order) { orderService.process(order); }}
Khác biệt KHÔNG PHẢI là Spring Boot có thể làm consumer hay không (đều được!), mà là:
Kafka
SQS
Consumer library
@KafkaListener
@SqsListener
Sau khi đọc
Message VẪN CÒN
Message BỊ XÓA
Consumer Groups
✅ Native
❌ Không có
Replay
✅ Có
❌ Không
Nhiều apps đọc cùng data
✅ Dễ dàng
❌ Phải dùng SNS fan-out
KAFKA: Topic ─┬→ App A (đọc tất cả) ← CÙNG DATA └→ App B (đọc tất cả) ← CÙNG DATASQS: Queue ─→ App A hoặc App B (MỖI msg chỉ 1 app nhận)SNS+SQS: SNS ─┬→ Queue A → App A (nhận copy) └→ Queue B → App B (nhận copy)
┌─────────────────────────────────────────────────────────────────┐│ SQS vs SNS vs KINESIS │├─────────────────────────────────────────────────────────────────┤│ ││ SQS: ││ • Consumer "pulls" messages ││ • Messages deleted after consumed ││ • No need to provision throughput ││ • Ordering only with FIFO ││ ││ SNS: ││ • "Push" to subscribers ││ • No persistence (instant delivery) ││ • Many subscribers (fan-out) ││ • Up to 12,500,000 subscribers ││ ││ Kinesis Data Streams: ││ • Consumer "pulls" data ││ • Data persists (replay capability) ││ • Provisioned throughput (shards) ││ • Ordering at shard level ││ • Real-time big data streaming ││ │└─────────────────────────────────────────────────────────────────┘