Skip to content

📬 ASYNCHRONOUS MESSAGING

Kafka vs RabbitMQ: Cuộc chiến Kinh điển của Message Brokers


Mục tiêu Học tập

Sau khi hoàn thành module này, bạn sẽ có khả năng:

  • Phân biệt Synchronous vs Asynchronous communication patterns
  • Hiểu kiến trúc Message Queue (Producer → Broker → Consumer)
  • So sánh Kafka vs RabbitMQ và chọn đúng tool
  • Implement Pub/SubDead Letter Queue patterns

1. Why Asynchronous? Tại sao không gọi trực tiếp?

NOTE

🎓 Giáo sư Tom: Synchronous: "Tôi gọi, bạn trả lời, tôi đợi". Asynchronous: "Tôi gửi tin nhắn, đi làm việc khác, bạn xử lý khi nào xong thì xong". Đây là sự khác biệt cơ bản giữa tight coupling và loose coupling.

┌─────────────────────────────────────────────────────────────────────────┐
│               SYNCHRONOUS vs ASYNCHRONOUS                                │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│   SYNCHRONOUS (Blocking):                                                │
│   ═══════════════════════                                                │
│                                                                          │
│   User ────► Order Service ────► Payment Service ────► Inventory        │
│        wait       wait                 wait               wait           │
│   User ◄──── Order Service ◄──── Payment Service ◄──── Inventory        │
│                                                                          │
│   Total latency = Sum of ALL service latencies                          │
│   If Payment is slow (2s) → User waits 2+ seconds                       │
│   If Inventory down → ENTIRE request fails                              │
│                                                                          │
│   ────────────────────────────────────────────────────────────────────  │
│                                                                          │
│   ASYNCHRONOUS (Non-blocking):                                           │
│   ═════════════════════════════                                          │
│                                                                          │
│   User ────► Order Service ────► Message Queue                          │
│        ◄──── "Order received"    (async process)                        │
│   User done!                          │                                  │
│                                       ├────► Payment Service            │
│   (User doing other things)           │            │                     │
│                                       │            ▼                     │
│                                       │      ┌──────────┐               │
│                                       │      │ Success! │               │
│                                       │      └──────────┘               │
│                                       │                                  │
│                                       └────► Inventory Service          │
│                                       └────► Notification Service       │
│                                                                          │
│   ✅ User gets instant response                                         │
│   ✅ Services process independently                                     │
│   ✅ One service down ≠ entire flow fails                               │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

1.1 When to Use Async?

ScenarioSync or Async?
User login (need immediate result)Sync
Send email after registrationAsync
Process payment (need result)Sync → Then Async for receipt
Generate PDF reportAsync (job queue)
Update search indexAsync
Real-time notificationsAsync
Analytics/LoggingAsync

2. Message Queue Architecture

2.1 Core Components

┌─────────────────────────────────────────────────────────────────────────┐
│                  MESSAGE QUEUE ARCHITECTURE                              │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│   ┌─────────────┐         ┌─────────────────────┐         ┌───────────┐ │
│   │  PRODUCER   │         │       BROKER        │         │ CONSUMER  │ │
│   │             │ ──────► │                     │ ──────► │           │ │
│   │ (Publisher) │         │  ┌───────────────┐  │         │(Subscriber│ │
│   │             │         │  │    QUEUE      │  │         │           │ │
│   └─────────────┘         │  │  ┌─┬─┬─┬─┬─┐  │  │         └───────────┘ │
│                           │  │  │M│M│M│M│M│  │  │                       │
│                           │  │  │1│2│3│4│5│  │  │                       │
│                           │  │  └─┴─┴─┴─┴─┘  │  │                       │
│                           │  └───────────────┘  │                       │
│                           │                     │                       │
│                           └─────────────────────┘                       │
│                                                                          │
│   PRODUCER:                                                              │
│   • Tạo message, gửi đến broker                                         │
│   • Không cần biết ai sẽ xử lý (decoupling)                            │
│                                                                          │
│   BROKER (Message Queue):                                                │
│   • Nhận message từ producers                                           │
│   • Lưu trữ message (persistence)                                       │
│   • Deliver message đến consumers                                       │
│   • Handle failures, retries, ordering                                  │
│                                                                          │
│   CONSUMER:                                                              │
│   • Subscribe vào queue                                                 │
│   • Process message                                                     │
│   • ACK sau khi xử lý xong                                              │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘
)

2.2 Delivery Guarantees

┌─────────────────────────────────────────────────────────────────────────┐
│                   DELIVERY SEMANTICS                                     │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│   1. AT-MOST-ONCE (Fire and Forget)                                     │
│   ══════════════════════════════════                                     │
│   Producer ────► Broker ────► Consumer                                  │
│            (no ACK)     (no ACK)                                        │
│                                                                          │
│   • Message có thể mất                                                  │
│   • Fastest, simplest                                                   │
│   • Use case: Metrics, logs (loss acceptable)                           │
│                                                                          │
│   ─────────────────────────────────────────────────────────────────     │
│                                                                          │
│   2. AT-LEAST-ONCE (Guaranteed but may duplicate)                       │
│   ═════════════════════════════════════════════════                      │
│   Producer ────► Broker ────► Consumer                                  │
│            ◄──── ACK                                                    │
│                         Consumer crashes before ACK?                    │
│                         → Broker re-delivers                            │
│                         → Consumer sees DUPLICATE                       │
│                                                                          │
│   • Message delivered at least once                                     │
│   • Consumer MUST be idempotent                                         │
│   • Most common choice                                                  │
│                                                                          │
│   ─────────────────────────────────────────────────────────────────     │
│                                                                          │
│   3. EXACTLY-ONCE (Holy Grail)                                          │
│   ══════════════════════════════                                         │
│   • Extremely hard to achieve                                           │
│   • Requires transactions across producer/broker/consumer               │
│   • Kafka supports (with limitations)                                   │
│   • High performance cost                                               │
│                                                                          │
│   ⚠️ Real-world tip: Design for AT-LEAST-ONCE with IDEMPOTENT consumers │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

3. Kafka: The Distributed Log

3.1 Kafka Architecture

TIP

🔧 Kỹ sư Raizo: Kafka không phải "message queue" theo nghĩa truyền thống. Nó là "distributed commit log". Sự khác biệt? Queue xóa message sau khi consume. Kafka GIỮ LẠI message theo retention policy. Bạn có thể replay từ bất kỳ điểm nào trong quá khứ.

┌─────────────────────────────────────────────────────────────────────────┐
│                    KAFKA ARCHITECTURE                                    │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│   TOPIC: "orders"                                                        │
│   ═══════════════                                                        │
│                                                                          │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │                        PARTITION 0                               │   │
│   │  ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐           │   │
│   │  │ 0  │ 1  │ 2  │ 3  │ 4  │ 5  │ 6  │ 7  │ 8  │ 9  │  → →      │   │
│   │  └────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘           │   │
│   │                                        ▲                         │   │
│   │                                   Consumer A                     │   │
│   │                                   offset: 8                      │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│                                                                          │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │                        PARTITION 1                               │   │
│   │  ┌────┬────┬────┬────┬────┬────┬────┐                           │   │
│   │  │ 0  │ 1  │ 2  │ 3  │ 4  │ 5  │ 6  │  → →                      │   │
│   │  └────┴────┴────┴────┴────┴────┴────┘                           │   │
│   │                              ▲                                   │   │
│   │                         Consumer B                               │   │
│   │                         offset: 5                                │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│                                                                          │
│   ┌─────────────────────────────────────────────────────────────────┐   │
│   │                        PARTITION 2                               │   │
│   │  ┌────┬────┬────┬────┬────┬────┬────┬────┐                      │   │
│   │  │ 0  │ 1  │ 2  │ 3  │ 4  │ 5  │ 6  │ 7  │  → →                 │   │
│   │  └────┴────┴────┴────┴────┴────┴────┴────┘                      │   │
│   │                                  ▲                               │   │
│   │                             Consumer C                           │   │
│   │                             offset: 6                            │   │
│   └─────────────────────────────────────────────────────────────────┘   │
│                                                                          │
│   KEY CONCEPTS:                                                          │
│   • Partition = ordered, immutable sequence of messages                 │
│   • Offset = position of message in partition (like array index)        │
│   • Consumer Group = set of consumers sharing partitions                │
│   • Each partition → ONE consumer in group (parallelism)                │
│                                                                          │
│   RETENTION:                                                             │
│   • Time-based: Keep 7 days (default)                                   │
│   • Size-based: Keep last 1TB                                           │
│   • Compaction: Keep only latest value per key                          │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

3.2 Kafka Strengths

FeatureBenefit
High ThroughputMillions of messages/second
DurabilityReplicated across brokers
ScalabilityAdd partitions, add consumers
ReplayRe-process from any offset
OrderingGuaranteed within partition
RetentionKeep messages for days/weeks

3.3 Kafka Consumer Groups

┌─────────────────────────────────────────────────────────────────────────┐
│                   CONSUMER GROUPS                                        │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│   Topic "orders" (3 partitions)                                         │
│                                                                          │
│   ┌──────────────────────────────────────────────────────────────────┐  │
│   │                      CONSUMER GROUP A                             │  │
│   │                   (Order Processing)                              │  │
│   │                                                                   │  │
│   │   P0 ──────► Consumer A1                                         │  │
│   │   P1 ──────► Consumer A2                                         │  │
│   │   P2 ──────► Consumer A3                                         │  │
│   │                                                                   │  │
│   │   Each partition → Exactly ONE consumer                          │  │
│   │   Parallel processing: 3 consumers = 3x throughput               │  │
│   │                                                                   │  │
│   └──────────────────────────────────────────────────────────────────┘  │
│                                                                          │
│   ┌──────────────────────────────────────────────────────────────────┐  │
│   │                      CONSUMER GROUP B                             │  │
│   │                    (Analytics Pipeline)                           │  │
│   │                                                                   │  │
│   │   P0 ──────► Consumer B1                                         │  │
│   │   P1 ──────►                                                     │  │
│   │   P2 ──────►                                                     │  │
│   │                                                                   │  │
│   │   Single consumer handles ALL partitions                         │  │
│   │   Lower throughput but simpler                                   │  │
│   │                                                                   │  │
│   └──────────────────────────────────────────────────────────────────┘  │
│                                                                          │
│   ⚠️ SAME MESSAGE → delivered to BOTH groups                           │
│      (Pub/Sub semantics between groups)                                 │
│                                                                          │
│   ⚠️ Within a group, each partition assigned to ONE consumer            │
│      (Competing consumers within group)                                 │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

4. RabbitMQ: The Smart Broker

4.1 RabbitMQ Architecture

┌─────────────────────────────────────────────────────────────────────────┐
│                  RABBITMQ ARCHITECTURE                                   │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│   ┌─────────────┐                              ┌─────────────────────┐  │
│   │  PRODUCER   │───────────┐                  │       QUEUES        │  │
│   └─────────────┘           │                  │                     │  │
│                             ▼                  │  ┌───────────────┐  │  │
│   ┌─────────────┐    ┌─────────────┐           │  │  email_queue  │──┼─►│
│   │  PRODUCER   │───►│  EXCHANGE   │───────────┤  └───────────────┘  │  │
│   └─────────────┘    │             │           │                     │  │
│                      │  (Router)   │           │  ┌───────────────┐  │  │
│   ┌─────────────┐    │             │───────────┤  │  sms_queue    │──┼─►│
│   │  PRODUCER   │───►│             │           │  └───────────────┘  │  │
│   └─────────────┘    └─────────────┘           │                     │  │
│                             │                  │  ┌───────────────┐  │  │
│                             └──────────────────┤  │  push_queue   │──┼─►│
│                                                │  └───────────────┘  │  │
│                                                └─────────────────────┘  │
│                                                                          │
│   EXCHANGE TYPES:                                                        │
│   ═══════════════                                                        │
│                                                                          │
│   1. DIRECT                                                              │
│      Route by exact routing key match                                   │
│      Key = "email" → email_queue                                        │
│                                                                          │
│   2. FANOUT                                                              │
│      Broadcast to ALL bound queues                                      │
│      (Ignores routing key)                                              │
│                                                                          │
│   3. TOPIC                                                               │
│      Pattern matching with wildcards                                    │
│      "orders.*" matches "orders.created", "orders.shipped"              │
│      "orders.#" matches "orders.asia.vietnam.created"                   │
│                                                                          │
│   4. HEADERS                                                             │
│      Route by message headers (rarely used)                             │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

4.2 RabbitMQ vs Kafka: Philosophy

┌─────────────────────────────────────────────────────────────────────────┐
│              SMART BROKER vs SMART CONSUMER                              │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│   RABBITMQ: SMART BROKER                                                 │
│   ══════════════════════                                                 │
│                                                                          │
│   Broker:                                                                │
│   • Routes messages (Exchanges)                                         │
│   • Tracks what's delivered                                             │
│   • Handles ACK/NACK                                                    │
│   • Deletes after consumption                                           │
│   • Manages retries, DLQ                                                │
│                                                                          │
│   Consumer:                                                              │
│   • Just process and ACK                                                │
│   • Minimal logic                                                       │
│                                                                          │
│   Analogy: Post office sorts mail, delivers to your door                │
│                                                                          │
│   ─────────────────────────────────────────────────────────────────     │
│                                                                          │
│   KAFKA: DUMB BROKER, SMART CONSUMER                                    │
│   ══════════════════════════════════                                     │
│                                                                          │
│   Broker:                                                                │
│   • Append to log                                                       │
│   • Serve reads                                                         │
│   • That's it!                                                          │
│                                                                          │
│   Consumer:                                                              │
│   • Track own offset                                                    │
│   • Decide what to re-read                                              │
│   • Handle failures                                                     │
│   • Coordinate with consumer group                                      │
│                                                                          │
│   Analogy: Library - books stay, you track what you've read             │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

5. Kafka vs RabbitMQ: Comparison Matrix

5.1 Feature Comparison

CriteriaKafkaRabbitMQ
ModelDistributed LogMessage Queue
Message DeletionRetention-basedAfter ACK
Replay✅ Any offset❌ Once consumed, gone
OrderingPer partitionPer queue
RoutingTopic-basedExchange (flexible)
ThroughputMillions/secThousands/sec
LatencyHigher (batching)Lower
ComplexityHigherLower

5.2 Use Case Matrix

Use CaseBest ChoiceWhy
Event SourcingKafkaReplay capability
Log AggregationKafkaHigh throughput, retention
Stream ProcessingKafkaKafka Streams, ksqlDB
Task QueueRabbitMQFlexible routing, ACK
RPC-styleRabbitMQRequest-reply pattern
Priority QueueRabbitMQNative priority support
Multi-tenant routingRabbitMQExchange patterns
CDC (Change Data Capture)KafkaDebezium integration

5.3 Decision Flowchart


6. Messaging Patterns

6.1 Pub/Sub Pattern

┌─────────────────────────────────────────────────────────────────────────┐
│                     PUB/SUB PATTERN                                      │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│   Publisher KHÔNG BIẾT ai là Subscriber                                 │
│   Subscriber KHÔNG BIẾT ai là Publisher                                 │
│                                                                          │
│   ┌─────────────┐         ┌─────────────────────┐                       │
│   │  Order      │         │    TOPIC/EXCHANGE   │                       │
│   │  Service    │────────►│   "order.created"   │                       │
│   │             │         │                     │                       │
│   └─────────────┘         └──────────┬──────────┘                       │
│                                      │                                   │
│               ┌──────────────────────┼──────────────────────┐           │
│               │                      │                      │           │
│               ▼                      ▼                      ▼           │
│   ┌─────────────────┐   ┌─────────────────┐   ┌─────────────────┐       │
│   │ Email Service   │   │ Analytics       │   │ Inventory       │       │
│   │                 │   │ Service         │   │ Service         │       │
│   │ "Send confirm"  │   │ "Update stats"  │   │ "Reserve stock" │       │
│   └─────────────────┘   └─────────────────┘   └─────────────────┘       │
│                                                                          │
│   Benefits:                                                              │
│   • Order Service chỉ publish, không quan tâm ai consume               │
│   • Add new subscriber? NO CHANGES to publisher                        │
│   • Remove subscriber? NO IMPACT                                        │
│                                                                          │
│   Challenges:                                                            │
│   • No response (fire-and-forget)                                       │
│   • Hard to debug (distributed tracing needed)                          │
│   • Message ordering across subscribers                                 │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

6.2 Dead Letter Queue (DLQ)

WARNING

The Poison Pill Problem: What happens when a message CANNOT be processed no matter how many times you retry? Without DLQ, it blocks the queue forever.

┌─────────────────────────────────────────────────────────────────────────┐
│                    DEAD LETTER QUEUE                                     │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│   SCENARIO: Malformed order message                                      │
│                                                                          │
│   ┌──────────────────────────────────────────────────────────────────┐  │
│   │                    MAIN QUEUE                                     │  │
│   │                                                                   │  │
│   │  ┌───┐ ┌───┐ ┌───┐ ┌───────────────┐ ┌───┐                       │  │
│   │  │ M │ │ M │ │ M │ │ POISON PILL   │ │ M │  ──────►              │  │
│   │  │ 5 │ │ 4 │ │ 3 │ │ (Invalid JSON)│ │ 1 │                       │  │
│   │  └───┘ └───┘ └───┘ └───────┬───────┘ └───┘                       │  │
│   │                            │                                      │  │
│   └────────────────────────────┼─────────────────────────────────────┘  │
│                                │                                         │
│                                ▼                                         │
│                    ┌───────────────────────┐                            │
│                    │      CONSUMER         │                            │
│                    │                       │                            │
│                    │  Try 1: FAIL          │                            │
│                    │  Try 2: FAIL          │                            │
│                    │  Try 3: FAIL          │                            │
│                    │                       │                            │
│                    │  Max retries = 3      │                            │
│                    │  → Move to DLQ        │                            │
│                    └───────────┬───────────┘                            │
│                                │                                         │
│                                ▼                                         │
│   ┌──────────────────────────────────────────────────────────────────┐  │
│   │                  DEAD LETTER QUEUE                                │  │
│   │                                                                   │  │
│   │  ┌───────────────────────────────────────────────────────────┐   │  │
│   │  │ Original Message + Error Details + Retry Count + Timestamp│   │  │
│   │  └───────────────────────────────────────────────────────────┘   │  │
│   │                                                                   │  │
│   │  Options:                                                         │  │
│   │  1. Human review & manual fix                                     │  │
│   │  2. Alert & monitoring                                            │  │
│   │  3. Automatic reprocessing with different logic                   │  │
│   │  4. Archive for audit                                             │  │
│   │                                                                   │  │
│   └──────────────────────────────────────────────────────────────────┘  │
│                                                                          │
│   ✅ Main queue unblocked, continues processing M1, M3, M4, M5          │
│   ✅ Poison pill isolated for investigation                            │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

6.3 DLQ Best Practices

┌─────────────────────────────────────────────────────────────────────────┐
│                    DLQ IMPLEMENTATION                                    │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│   1. ENRICH THE DEAD LETTER                                             │
│   ══════════════════════════                                             │
│   {                                                                      │
│     "original_message": { ... },                                        │
│     "error": {                                                          │
│       "type": "ValidationError",                                        │
│       "message": "Invalid order_id format",                             │
│       "stack_trace": "..."                                              │
│     },                                                                  │
│     "metadata": {                                                       │
│       "retry_count": 3,                                                 │
│       "first_attempt": "2024-01-15T10:00:00Z",                         │
│       "last_attempt": "2024-01-15T10:00:30Z",                          │
│       "original_queue": "orders.process",                               │
│       "consumer_id": "worker-pod-abc123"                                │
│     }                                                                   │
│   }                                                                      │
│                                                                          │
│   2. MONITORING & ALERTING                                              │
│   ═══════════════════════                                                │
│   • Alert if DLQ > X messages                                           │
│   • Dashboard: DLQ depth, age of oldest message                        │
│   • Runbook: How to investigate, replay                                 │
│                                                                          │
│   3. RETRY STRATEGY                                                      │
│   ══════════════════                                                     │
│   Immediate → Wait 1s → Wait 5s → Wait 30s → DLQ                       │
│   (Exponential backoff with max retries)                                │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

7. Raizo's Production Advice

TIP

🔧 Kỹ sư Raizo - HPN Stack:

Penrift Cloud sử dụng BOTH Kafka và RabbitMQ:

  • Kafka: User activity stream, CDC pipeline, event sourcing
  • RabbitMQ: Background jobs, email queue, webhooks

Rule: Nếu cần replay hoặc high throughput → Kafka. Nếu cần flexible routing hoặc task queue → RabbitMQ.

7.1 Common Pitfalls

┌─────────────────────────────────────────────────────────────────────────┐
│                    COMMON MESSAGING PITFALLS                             │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│   ❌ PITFALL 1: Not handling duplicates                                 │
│   ══════════════════════════════════════                                 │
│   At-least-once = duplicates WILL happen                                │
│   Fix: Idempotent consumers (check if already processed)                │
│                                                                          │
│   ❌ PITFALL 2: Unbounded queues                                        │
│   ══════════════════════════════                                         │
│   Producer faster than consumer = queue grows forever = OOM             │
│   Fix: Backpressure, rate limiting, alerting on queue depth            │
│                                                                          │
│   ❌ PITFALL 3: No DLQ                                                  │
│   ═══════════════════                                                    │
│   Bad message blocks entire queue                                       │
│   Fix: Always have DLQ + monitoring                                     │
│                                                                          │
│   ❌ PITFALL 4: Large messages                                          │
│   ══════════════════════════════                                         │
│   Sending 10MB files through message queue                              │
│   Fix: Store in S3, send reference in message                           │
│                                                                          │
│   ❌ PITFALL 5: Ignoring ordering requirements                          │
│   ══════════════════════════════════════════                             │
│   Multiple partitions/consumers = out of order processing               │
│   Fix: Partition by order_id if sequence matters                        │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

8. Scenario Quiz

Câu hỏi 1: E-commerce Events

HPN Store cần xử lý events: Order Created → Payment Processed → Inventory Updated → Email Sent. Mỗi event có thể có hàng ngàn xử lý đồng thời. Cần replay khả năng đối với Payment team để debug.

Bạn chọn Kafka hay RabbitMQ? Tại sao?

👁️ Xem đáp án

Đáp án: Kafka

Lý do:

  • Replay capability: Payment team cần xem lại events để debug → Kafka giữ messages
  • High throughput: Hàng ngàn events/second → Kafka optimized cho scale
  • Event sourcing: Chuỗi events tự nhiên phù hợp với Kafka's log model
  • Multiple consumers: Analytics, Fraud detection, etc. có thể consume cùng event

Implementation:

yaml
Topic: order-events
Partitions: 10 (partition by order_id for ordering)
Retention: 7 days
Consumer Groups:
  - order-processing
  - analytics-pipeline
  - fraud-detection

Câu hỏi 2: Background Jobs

HPN Blog cần gửi email newsletter cho 100K subscribers. Email gửi không cần nhanh (có thể chờ vài giờ). Nếu gửi thất bại, cần retry với exponential backoff. Priority queue cho VIP users.

Bạn chọn Kafka hay RabbitMQ? Tại sao?

👁️ Xem đáp án

Đáp án: RabbitMQ

Lý do:

  • Priority queue: RabbitMQ native support, Kafka không có
  • Flexible retry: RabbitMQ + DLQ + TTL = easy exponential backoff
  • Task queue model: "Process once and delete" phù hợp với email
  • No replay needed: Email đã gửi thì không cần gửi lại

Implementation:

python
# RabbitMQ với priority queue
channel.queue_declare(
    queue='email_queue',
    arguments={
        'x-max-priority': 10,
        'x-dead-letter-exchange': 'email_dlx',
        'x-message-ttl': 86400000  # 24h
    }
)

# VIP users get priority 10
channel.basic_publish(
    exchange='',
    routing_key='email_queue',
    body=message,
    properties=pika.BasicProperties(priority=10)
)

9. Tiếp theo

Xin chúc mừng! Bạn đã hoàn thành Phase 2: Distributed Systems Theory! 🎉

Quay lại System Design Universe để explore các modules khác:

👉 System Design Home →

Hoặc tiếp tục với Case Studies để áp dụng kiến thức:

👉 Design Twitter →