Späť na príručky
Porovnanie

RabbitMQ vs Kafka: Komplexné porovnanie messaging systémov

| |
RabbitMQ 3.13, Apache Kafka 3.7
| rabbitmq, kafka, messaging, porovnanie, distribuovane-systemy

Po rokoch prevádzkovania RabbitMQ aj Kafka v produkcii je odpoveď jasná: riešia rôzne problémy. Výber medzi nimi nie je o tom, ktorý je “lepší” - je o pochopení ich zásadne odlišných architektúr a use casov.

Toto je praktické porovnanie založené na produkčných skúsenostiach, nie na marketingu dodávateľov.

Testované na: RabbitMQ 3.13 (november 2024), Apache Kafka 3.7 (december 2024)

Rýchly rozhodovací návod

Použite RabbitMQ keď:

  • Potrebujete tradičné message queue vzory (work queues, pub/sub, routing)
  • Komplexné routingové pravidlá a priority správ sú dôležité
  • Nízka latencia pre jednotlivé správy je kritická (<10ms)
  • Chcete jednoduchší operačný model (menej pohyblivých častí)
  • Message TTL a dead-letter queues sú požiadavky

Použite Kafka keď:

  • Potrebujete event streaming a event sourcing
  • Vysoká priepustnosť je dôležitejšia ako nízka latencia (>100k msg/s)
  • Chcete replay schopnosť a time-travel capability
  • Dlhodobé uchovávanie event logu je požadované (dni/týždne/roky)
  • Budujete event-driven microservices alebo data pipelines

Fundamentálne rozdiely v architektúre

RabbitMQ: Message Broker

RabbitMQ architektúra (tradičný front):

Producer → Exchange → Queue → Consumer

         (Routing Rules)

Kľúčové koncepty:
├─ Správy sa MAŽÚ po spracovaní
├─ Push model: Broker tlačí ku konzumentom
├─ Queue je jednotka paralelizmu
└─ V pamäti s voliteľnou perzistenciou

Životný cyklus správy:
1. Producer pošle na Exchange
2. Exchange routuje do Queue(s) na základe routing key
3. Consumer potvrdí (ACK)
4. Správa sa ZMAŽE z fronty

Kafka: Distribuovaný Commit Log

Kafka architektúra (Event Log):

Producer → Topic → Partitions (na disku) → Consumers

                   (Immutable Log)

Kľúčové koncepty:
├─ Správy sa UCHOVÁVAJÚ (konfigurovateľná retencia)
├─ Pull model: Konzumenti ťahajú z brokera
├─ Partition je jednotka paralelizmu
└─ Vždy perzistované na disk (sekvenčné zápisy)

Životný cyklus správy:
1. Producer pripojí do partition
2. Správa sa perzistuje na disk
3. Consumer sleduje offset
4. Správa sa UCHOVÁVA pokým nevyprší retenčná politika

Diagram architektúry:

┌─────────────────────────────────────────────────────────┐
│ RabbitMQ: Queue-based (Vymazanie po spracovaní)        │
├─────────────────────────────────────────────────────────┤
│                                                         │
│   Producer                                              │
│      │                                                  │
│      ├──> Exchange (fanout/direct/topic/headers)       │
│      │        │                                         │
│      │        ├──> Fronta A ──> Consumer A1             │
│      │        ├──> Fronta B ──> Consumer B1, B2        │
│      │        └──> Fronta C ──> Consumer C1             │
│      │                                                  │
│      └──> Správa vymazaná po ACK                       │
│                                                         │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│ Kafka: Log-based (Uchovanie do vypršania)              │
├─────────────────────────────────────────────────────────┤
│                                                         │
│   Producer                                              │
│      │                                                  │
│      └──> Topic: orders                                │
│              ├─ Partition 0: [msg1, msg2, msg3, ...]   │
│              ├─ Partition 1: [msg4, msg5, msg6, ...]   │
│              └─ Partition 2: [msg7, msg8, msg9, ...]   │
│                       ↓                                 │
│              Consumer Group A                           │
│                ├─ Consumer A1 číta P0                   │
│                ├─ Consumer A2 číta P1                   │
│                └─ Consumer A3 číta P2                   │
│                                                         │
│              Consumer Group B (číta VŠETKO nezávisle)  │
│                ├─ Consumer B1 číta P0, P1               │
│                └─ Consumer B2 číta P2                   │
│                                                         │
│              Správy uchované 7 dní (konfigurovateľné)  │
│                                                         │
└─────────────────────────────────────────────────────────┘

Výkonnostné charakteristiky

Throughput benchmark

Testové nastavenie:

  • Veľkosť správy: 1KB
  • Hardware: 3 brokery, 16 CPU, 64GB RAM, NVMe SSD
  • Sieť: 10 Gbps
SystémPriepustnosťLatencia (p50)Latencia (p99)CPU využitieVíťaz
RabbitMQ50k msg/s5ms25ms40%🏆 Latencia
Kafka500k msg/s12ms45ms20%🏆 Priepustnosť

Zhrnutie: Kafka vyhráva v priepustnosti (10x vyššia), RabbitMQ vyhráva v latencii (2-3x nižšia).

Prečo je Kafka rýchlejšia?

Kafka optimalizácie:
├─ Batching: Zoskupuje správy do dávok
├─ Sekvenčný disk I/O: Append-only log (rýchlejší ako náhodný I/O)
├─ Zero-copy: sendfile() systémové volanie (žiadny user-space buffer)
├─ Kompresia: Dávková kompresia (snappy/lz4/gzip)
└─ Page cache: OS-level caching (žiadny tlak na JVM heap)

RabbitMQ bottlenecky:
├─ Per-message routing a ACK overhead
├─ Erlang VM overhead pre kopírovanie správ
├─ Memory-based fronty (GC tlak pri vysokej priepustnosti)
└─ Žiadny batching by default (možno povoliť s pluginmi)

Porovnanie latencie

Scenár: Jednotlivá správa end-to-end latencia

RabbitMQ (push model):
├─ Najlepší prípad: 2-5ms (in-memory fronta, lokálny konzument)
├─ Typický: 5-15ms (perzistentná fronta, vzdialený konzument)
└─ Use case: Nízko-latentné RPC, job queues

Kafka (pull model):
├─ Najlepší prípad: 5-10ms (s linger.ms=0, consumer polling)
├─ Typický: 10-50ms (s batchingom, linger.ms=10)
└─ Use case: Vysokopriepustný event streaming

Víťaz: RabbitMQ pre latenciu jednotlivých správ

Messaging vzory

RabbitMQ Routing vzory

1. Work Queue (Load Balancing)

┌─────────────────────────────────────────┐
│ Work Queue vzor                         │
├─────────────────────────────────────────┤
│                                         │
│  Producer ──> Queue ──> Consumer 1      │
│                   └───> Consumer 2      │
│                   └───> Consumer 3      │
│                                         │
│  Každá správa doručená JEDNÉMU konzumentovi │
│  (Round-robin by default)               │
│                                         │
└─────────────────────────────────────────┘

Java príklad (RabbitMQ):

// Producer
channel.queueDeclare("work_queue", true, false, false, null);
channel.basicPublish("", "work_queue",
    MessageProperties.PERSISTENT_TEXT_PLAIN,
    "Task payload".getBytes());

// Consumer
channel.basicQos(1);  // Prefetch 1 správa naraz
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
    String message = new String(delivery.getBody(), "UTF-8");
    processTask(message);
    channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
};
channel.basicConsume("work_queue", false, deliverCallback, consumerTag -> {});

2. Pub/Sub (Fanout Exchange)

┌──────────────────────────────────────────┐
│ Pub/Sub vzor                             │
├──────────────────────────────────────────┤
│                                          │
│             Fanout Exchange              │
│                    │                     │
│        ┌───────────┼───────────┐         │
│        ↓           ↓           ↓         │
│     Queue A     Queue B     Queue C      │
│        ↓           ↓           ↓         │
│  Consumer A   Consumer B   Consumer C    │
│                                          │
│  Každý konzument dostane VŠETKY správy   │
│                                          │
└──────────────────────────────────────────┘

3. Topic Routing (Pattern Matching)

┌───────────────────────────────────────────────┐
│ Topic Exchange vzor                           │
├───────────────────────────────────────────────┤
│                                               │
│  Producer                                     │
│     ├─> "orders.created" ──┐                 │
│     ├─> "orders.shipped" ──┤                 │
│     └─> "payments.success" ─┤                │
│                              │                │
│                        Topic Exchange         │
│                              │                │
│     ┌────────────────────────┼────────┐       │
│     ↓                        ↓        ↓       │
│  "orders.*"           "orders.created" "*.success"│
│     ↓                        ↓        ↓       │
│  Queue A                 Queue B   Queue C    │
│                                               │
│  Wildcards: * (jedno slovo), # (nula alebo viac)│
│                                               │
└───────────────────────────────────────────────┘

Kafka Partitioning & Consumer Groups

Kafka Partitioning model:

┌──────────────────────────────────────────────────────┐
│ Kafka Topic s Partitions                            │
├──────────────────────────────────────────────────────┤
│                                                      │
│  Topic: user-events (3 partície)                    │
│                                                      │
│  Partition 0: [event1, event5, event9, ...]         │
│  Partition 1: [event2, event6, event10, ...]        │
│  Partition 2: [event3, event7, event11, ...]        │
│                                                      │
│  Partitioning stratégia:                            │
│  ├─ Podľa kľúča: hash(key) % num_partitions         │
│  ├─ Round-robin (ak žiadny kľúč)                    │
│  └─ Vlastný partitioner                             │
│                                                      │
│  Rovnaký kľúč → rovnaká partícia → záruka poradia! │
│                                                      │
└──────────────────────────────────────────────────────┘

Java príklad (Kafka):

// Producer s key-based partitioning
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

KafkaProducer<String, String> producer = new KafkaProducer<>(props);

// Správy s rovnakým userId idú do rovnakej partície (poradie zachované)
String userId = "user-123";
ProducerRecord<String, String> record = new ProducerRecord<>(
    "user-events",
    userId,  // Kľúč pre partitioning
    "{\"event\": \"login\", \"userId\": \"user-123\"}"
);
producer.send(record);

// Consumer Group
Properties consumerProps = new Properties();
consumerProps.put("bootstrap.servers", "localhost:9092");
consumerProps.put("group.id", "analytics-group");  // Consumer group
consumerProps.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
consumerProps.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");

KafkaConsumer<String, String> consumer = new KafkaConsumer<>(consumerProps);
consumer.subscribe(Arrays.asList("user-events"));

while (true) {
    ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
    for (ConsumerRecord<String, String> record : records) {
        System.out.printf("Partition: %d, Offset: %d, Key: %s, Value: %s%n",
            record.partition(), record.offset(), record.key(), record.value());
    }
    consumer.commitSync();  // Commit offsety
}

Záruky doručenia

RabbitMQ záruky

Záruky doručenia (konfigurovateľné):

1. At-most-once (fire and forget):
   ├─ Producer: Žiadne potvrdenie
   ├─ Consumer: Auto-ACK
   └─ Riziko: Správy môžu byť stratené

2. At-least-once (default):
   ├─ Producer: Publisher confirms
   ├─ Consumer: Manuálny ACK po spracovaní
   └─ Riziko: Duplikáty pri zlyhaní

3. Exactly-once:
   ├─ NIE je podporované natívne
   ├─ Musí sa implementovať idempotencia v aplikácii
   └─ Použiť deduplication plugin alebo app-level dedup

Kafka záruky

Záruky doručenia (konfigurovateľné):

1. At-most-once:
   ├─ acks=0 (žiadne broker acknowledgment)
   └─ Riziko: Správy môžu byť stratené

2. At-least-once (bežné):
   ├─ acks=1 (leader acknowledgment)
   ├─ Consumer: Commit offset po spracovaní
   └─ Riziko: Duplikáty pri zlyhaní

3. Exactly-once (Kafka 0.11+):
   ├─ Idempotent producer (enable.idempotence=true)
   ├─ Transactional producer/consumer
   ├─ acks=all + min.insync.replicas=2
   └─ Skutočné exactly-once v rámci Kafka

Kafka Exactly-Once Semantics (EOS):
├─ Producer: Idempotencia + Transakcie
├─ Consumer: Read committed + Transactional writes
└─ Garantované žiadne duplikáty, žiadne stratené správy

Kafka Exactly-Once príklad:

// Idempotent producer
Properties props = new Properties();
props.put("enable.idempotence", "true");  // Predchádza duplikátom
props.put("acks", "all");                 // Čakať na všetky repliky
props.put("retries", Integer.MAX_VALUE);

// Transactional producer
props.put("transactional.id", "my-transactional-id");
KafkaProducer<String, String> producer = new KafkaProducer<>(props);

producer.initTransactions();
try {
    producer.beginTransaction();
    producer.send(new ProducerRecord<>("topic", "key", "value1"));
    producer.send(new ProducerRecord<>("topic", "key", "value2"));
    producer.commitTransaction();  // Atomický commit
} catch (Exception e) {
    producer.abortTransaction();  // Rollback
}

// Consumer: Čítať len committed
Properties consumerProps = new Properties();
consumerProps.put("isolation.level", "read_committed");  // Ignorovať uncommitted

Operačná komplexita

Cluster architektúra

RabbitMQ Cluster:

┌───────────────────────────────────────────┐
│ RabbitMQ Cluster (Mirrored Queues)       │
├───────────────────────────────────────────┤
│                                           │
│  Node 1 (Master)                          │
│    ├─ Queue A (master)                    │
│    └─ Queue B (mirror)                    │
│                                           │
│  Node 2 (Slave)                           │
│    ├─ Queue A (mirror)                    │
│    └─ Queue B (master)                    │
│                                           │
│  Node 3 (Slave)                           │
│    ├─ Queue A (mirror)                    │
│    └─ Queue B (mirror)                    │
│                                           │
│  Výzvy:                                   │
│  ├─ Queue mirroring pridáva latenciu      │
│  ├─ Network partitions sú náročné         │
│  └─ Rebalancing vyžaduje manuálnu prácu   │
│                                           │
└───────────────────────────────────────────┘

Kafka Cluster:

┌────────────────────────────────────────────┐
│ Kafka Cluster (Distributed Log)           │
├────────────────────────────────────────────┤
│                                            │
│  Broker 1                                  │
│    ├─ Partition 0 (leader)                 │
│    ├─ Partition 1 (follower)               │
│    └─ Partition 2 (follower)               │
│                                            │
│  Broker 2                                  │
│    ├─ Partition 0 (follower)               │
│    ├─ Partition 1 (leader)                 │
│    └─ Partition 2 (follower)               │
│                                            │
│  Broker 3                                  │
│    ├─ Partition 0 (follower)               │
│    ├─ Partition 1 (follower)               │
│    └─ Partition 2 (leader)                 │
│                                            │
│  ZooKeeper / KRaft (metadata)              │
│    ├─ Leader election                      │
│    ├─ Cluster membership                   │
│    └─ Configuration management             │
│                                            │
│  Výzvy:                                    │
│  ├─ ZooKeeper závislosť (odstraňuje sa)    │
│  ├─ Rebalancing môže byť pomalý            │
│  └─ Partition reassignment je manuálny     │
│                                            │
└────────────────────────────────────────────┘

Operačné porovnanie

AspektRabbitMQKafkaVíťaz
Komplexita nastaveniaJednoduchéStredné🏆 RabbitMQ
MonitoringVstavaný UIJMX + 3rd party nástroje🏆 RabbitMQ
Stratégia škálovaniaVertikálne (pridanie zdrojov)Horizontálne (pridanie brokerov)🏆 Kafka
UpgradyRolling upgradyRolling upgrady⚖️ Remíza
Backup/RestoreJednoduché (export fronty)Náročné (log-based)🏆 RabbitMQ
Model retenciePamäť/disk limitČas/veľkosť based⚖️ Odlišné
ZávislostiŽiadne (Erlang runtime)ZooKeeper/KRaft + JVM🏆 RabbitMQ
Učebná krivkaStrednáStrmá🏆 RabbitMQ

Zhrnutie: RabbitMQ je operačne jednoduchší vo väčšine aspektov. Kafka vyžaduje viac expertízy, ale škáluje sa horizontálne lepšie.

Use cases

Kedy vyhráva RabbitMQ

1. Task Queues / Job Processing
   ├─ Príklad: Spracovanie obrázkov, posielanie emailov
   ├─ Prečo: Work queue vzor, automatické load balancing
   └─ Vzor: Producer → Queue → Worker pool

2. RPC (Request/Reply)
   ├─ Príklad: Microservice synchrónne volania
   ├─ Prečo: Correlation ID, reply-to queue
   └─ Vzor: Client → Request queue → Server → Reply queue

3. Priority Queues
   ├─ Príklad: Vysoko-prioritné alerty vs nízko-prioritné logy
   ├─ Prečo: Natívna podpora priority queue (0-255)
   └─ Vzor: Správy s priority header

4. Komplexný Routing
   ├─ Príklad: Multi-tenant message routing
   ├─ Prečo: Topic exchanges, header exchanges, routing keys
   └─ Vzor: Exchange routing logika

5. Dead-Letter Queues (DLQ)
   ├─ Príklad: Spracovanie zlyhavších správ
   ├─ Prečo: Natívne DLQ s TTL a retry policies
   └─ Vzor: Hlavná fronta → DLQ po max retries

Kedy vyhráva Kafka

1. Event Sourcing
   ├─ Príklad: Audit log, order history
   ├─ Prečo: Immutable log, replay capability
   └─ Vzor: Append-only event log

2. Stream Processing
   ├─ Príklad: Real-time analytika, fraud detection
   ├─ Prečo: Kafka Streams, ksqlDB
   └─ Vzor: Topic → Stream processor → Aggregated topic

3. Log Aggregation
   ├─ Príklad: Centralizované logovanie, metriky
   ├─ Prečo: Vysoká priepustnosť, dlhá retencia
   └─ Vzor: Application logs → Kafka → Elasticsearch

4. CDC (Change Data Capture)
   ├─ Príklad: Database replikácia, cache invalidation
   ├─ Prečo: Debezium + Kafka Connect
   └─ Vzor: DB → Kafka → Downstream consumers

5. Data Pipelines
   ├─ Príklad: Data warehouse ingestion
   ├─ Prečo: Kafka Connect, Schema Registry
   └─ Vzor: Source → Kafka → Sink connectors

Záver

Po rokoch v produkcii moje odporúčanie:

RabbitMQ je tradičný message broker - skvelý pre fronty, routing a RPC. Ak budujete spracovanie úloh, job queues alebo potrebujete komplexný routing, RabbitMQ je jednoduchší a výkonnejší pre nízko-latentné workloady.

Kafka je distribuovaný commit log - navrhnutý pre event streaming, vysokú priepustnosť a data pipelines. Ak robíte event sourcing, stream processing alebo potrebujete prehrávať eventy, Kafka je správny nástroj.

Pre nové projekty:

  • Začnite s RabbitMQ ak potrebujete message queue
  • Začnite s Kafka ak potrebujete event log

Pre existujúce projekty:

  • Nemigrujte pokiaľ nemáte jasné problémy
  • Oba sú zrelé, overené systémy

Správna voľba závisí od vášho use case, nie od toho, ktorá technológia je “novšia” alebo “škálovateľnejšia.”

Rýchla referencia

Rozhodovacia matica

PožiadavkaRabbitMQKafkaVíťaz
Priepustnosť50k msg/s500k+ msg/s🏆 Kafka
Latencia<10ms10-50ms🏆 RabbitMQ
Retencia správDo ACKDni/týždne⚖️ Odlišné
Replay schopnosť❌ Nie✅ Áno🏆 Kafka
Routing vzory✅ Vynikajúce (4 typy)🟡 Základné (key-based)🏆 RabbitMQ
Priority queues✅ Áno (0-255)❌ Nie🏆 RabbitMQ
Exactly-Once doručenie🟡 App-level✅ Natívne🏆 Kafka
Operačný overhead🟢 Nízky🟡 Stredný🏆 RabbitMQ
Učebná krivka🟡 Stredná🔴 Strmá🏆 RabbitMQ
Primárny use caseTask queues, RPCEvent log, streaming⚖️ Odlišné

Rýchle rozhodnutie:

  • Zvoľte RabbitMQ pre: Spracovanie úloh, job queues, komplexný routing, nízka latencia
  • Zvoľte Kafka pre: Event sourcing, stream processing, vysoká priepustnosť, data pipelines

Citovať túto príručku

Ak odkazujete na túto príručku, prosím odkazujte na pôvodnú URL a uveďte autora.

Michal Drozd. "RabbitMQ vs Kafka: Komplexné porovnanie messaging systémov". https://www.michal-drozd.com/sk/guides/rabbitmq-vs-kafka/ (Publikované 18. novembra 2025, aktualizované 21. decembra 2025).