Message Queues: RabbitMQ, Kafka
Message Queues: RabbitMQ, Kafka
1) Wann was zu wählen
RabbitMQ (AMQP 0-9-1 / 1. 0, klassische Warteschlangen, Quorum Queues, Streams)
Geeignet für: RPC/Befehle, Workflow, kurze Aufgaben, Fanout/Topic-Routing, flexible Bestätigungen, Prioritätsmanagement.
Vorteile: reichhaltige Routing-Semantik (Exchanges), 'basic. qos'(prefetch), per-message TTL/delay, komfortable RPC (reply-to) Muster, einfacher Start.
Nachteile: Geschichte wird in der Warteschlange gespeichert, horizontale Skalierung in Warteschlangen/Shards; hohe Durchlaufkosten bei sehr großen Strömen.
Apache Kafka (Ereignisprotokoll, Parteien, Verbrauchergruppen)
Geeignet für: Event-Streams, Auditing, Event-Sourcing, ETL/Integrationen (Connect), hohe RPS/MBps, Replikate/Re-Processing, Stream-Processing (Streams/ksqlDB).
Vorteile: Langzeitprotokoll, Skalierung nach Partitur, stabile Replikation, Schlüsselkomprimierung.
Nachteile: Modell „Pull + Party“ - nicht für kleine RPC; Ordnung nur innerhalb der Partei; Das Management von Schaltungen/Kompatibilität liegt in der Verantwortung des Teams.
2) Liefersemantik und Invarianten
At-most-once: keine Rückblenden; schnell, Verlustrisiko.
At-least-once: mit Retrays; erfordert die Idempotenz des Verbrauchers.
Exactly-once: erreichbar unter eingeschränkten Bedingungen (Kafka TX + idempotent producer + consistent sink; RabbitMQ - über Deduplizierungstabelle/idempotente Schlüssel).
Reihenfolge: RabbitMQ - Reihenfolge in der Warteschlange (kann bei Retrays/Multi-Consumern gestört werden); Kafka ist die Ordnung in der Partei, der Schlüssel ist die Partizipation.
Domain-Invarianten: Geld/Guthaben - durch Zeitschriften/Sagen und idempotente Befehle; Verlassen Sie sich nicht auf LWW.
3) Integrationsmuster
Outbox/InBox: atomare Aufzeichnung des Ereignisses in der DB → Veröffentlichung in der Warteschlange (Outbox) und idempotenter Verbrauch mit Protokoll der Behandlungen (Inbox).
DLQ (tote E-Mails): nach N Versuchen/Fehlern - in DLQ + alert.
Retry/Delay: RabbitMQ — TTL + dead-letter exchange; Kafka - Retry-Tops mit Backoff.
Request/Reply: RabbitMQ — `reply_to` + `correlation_id`; Kafka - selten, nur spezielle Muster.
Entschädigung: Saga über Ereignisse; Jede Operation hat eine umgekehrte.
4) Entwurf von Schlüsseln und Topologien
RabbitMQ
Exchanges: `direct`, `topic`, `fanout`, `headers`.
Routing-Schlüssel: Definiert den Treffer in der Warteschlange (n). Zur Priorisierung gibt es separate Warteschlangen.
QoS: 'prefetch' (z.B. 50-300) gleicht Geschwindigkeit/Latenz aus.
Quorum Queues: replizierbare Warteschlangen auf Floß; Ersatz für mirrored classic.
Streams: Stream mit Offsets (Kafka-like) für High-Throughput/Replay.
Kafka
Topic → partitions: Planen Sie'# partitions' nach dem Ziel throughput und Parallelität (abwärtskompatibel ist das Vergrößern einfacher als das Verkleinern).
Schlüssel: Alle Einträge eines Schlüssels sind in einer Partei (Garantie der Reihenfolge nach Schlüssel).
Replikationsfaktor: 3 für produktive Themen, 'min. insync. replicas = 2'+ 'acks = all' für Zuverlässigkeit.
Retention: nach Zeit/Größe; compaction - Speichert die letzten Werte mit dem Schlüssel + tombstones zum Löschen.
5) Retrai, DLQ, Idempotenz
RabbitMQ
Wiederholungen: per-message TTL + DLX (dead-letter exchange) mit backoff (z.B. 1m → 5m → 15m).
Idempotenz: 'correlation _ id '/' message-id' + Tabelle der verarbeiteten Nachrichten (TTL) oder deterministische Befehle.
Bestätigungen: manual 'basic. ack 'nach erfolgreicher Transaktion;' basic. nack(requeue=false)` в DLQ.
Kafka
Wiederholungen: einzelne Retry-Topics; consumer offset nach erfolgreichem side-effect.
Exactly-once processing (EOS): Producer `enable. idempotence = true', transaktionaler Erzeuger/Verbraucher, „read _ committed“ auf den Verbraucher; sink (z. B. Kafka→Kafka oder Kafka→DB durch eine Transaktion) - sorgfältig synchronisieren.
Dedup: durch Schlüssel/idempotent Schlüssel auf der Seite der Basis, oder durch compacted Thema.
6) Leistung und Dimension
Little's Law: „L = λ × W“
Für workerow: der geforderte Parallelismus ' N ≈ arrival_rate × avg_processing_time × der Vorrat (1. 2–1. 5)`.
RabbitMQ prefetch: Beginnen Sie mit 'prefetch = 100' und messen Sie p99/Zeit 'in-flying'.
Kafka-Partitionen: Berechnung aus gewünschter Consumer-Parallelität und Throughput-Ziel (z.B. 1 Partitur stabil 5-20 MB/s auf SSD/10GbE).
7) Beobachtbarkeit und Warnungen
Allgemein:- Lag/Backlog (messages/bytes), age messages (p95/p99), error-rate processings, DLQ-rate.
- Zeit der publikatsiya→obrabotka (End-to-End)
- Abhängigkeitskarte: Producer → Broker → Consumer.
- Verbindungen, Kanäle, nicht gescannte Nachrichten, 'memory _ alarm', 'disk _ free _ limit', 'queue length' p95.
- Berichte über Quorum (Leader, Floß-Log, Fehler 'quorum not enough').
- Under-replicated partitions, ISR shrink/expand, controller changes.
- Producer errors (timeouts, `request latency`), consumer lag per group/partition.
- Broker I/O, page cache hit, GC, ZooKeeper/KRaft health.
8) Sicherheit und Multi-Tenant
TLS-Verschlüsselung im Transit, Authentifizierung (SASL/PLAIN/SCRAM/OAuth, mTLS).
Autorisierung: vhost/permissions (RabbitMQ), ACL auf Tops/Gruppen (Kafka).
Kontingente: für Verbindungen, Kanäle, Warteschlangen-/Topic-Größe, Veröffentlichungs-/Lesegeschwindigkeit.
Isolierung nach Mittwoch (dev/stage/prod) und nach namespace/vhost.
9) Betrieb und Tuning
RabbitMQ
Verteilen Sie die Exchanges/Queues auf die Knoten (CPU/IO Capacity).
Lazy queues (Nachrichten auf der Festplatte) für große Puffer; Vermeiden Sie „heiße“ Warteschlangen ohne Sharding.
Quorum Queues für HA; Planen Sie die Größe des Raft-Journals und der Disc.
TTL/Length-Limit-Richtlinien, Warteschlangenpriorität nur bei tatsächlichem Bedarf (teuer).
bash rabbitmqctl set_policy DLX "^task\." \
'{"dead-letter-exchange":"dlx","message-ttl":60000,"max-length":100000}' --apply-to queues
Kafka
SSD/NVMe, schnelle Netzwerke; OS-Tuning (Swappiness niedrig, Dateilimits).
`acks=all`, `linger. ms'(Batching), 'compression. type = zstd '/lz4 für den Durchsatz.
Verbraucherparameter: 'max. poll. interval. ms`, `max. poll. records`, `fetch. min. bytes`.
Retention und Compaction - Lager-/Replay-Balance.
java props. put("acks","all");
props. put("enable. idempotence", "true");
props. put("max. in. flight. requests. per. connection","1");
props. put("retries","10");
10) Integrationen und Ökosystem
Kafka Connect (Sinks/Sources), Schema Registry (Avro/JSON/Protobuf) und Kompatibilität („BACKWARD/FORWARD/FULL“).
Kafka Streams/ksqlDB: stateful-Operationen, Fenster, Aggregate.
RabbitMQ Shovel/Federation: Transfer zwischen Clustern/Zentren.
Betreiber K8s: Strimzi (Kafka), RabbitMQ Cluster Operator; GitOps-Manifeste.
11) Implementierung Checkliste (0-45 Tage)
0-10 Tage
Use-case's definieren: Befehle/Taski (RabbitMQ), Ereignisse/Audit (Kafka).
Wählen Sie die Schlüssel ('routing key '/' partition key'), setzen Sie die SLO „publikatsiya→obrabotka“.
Grundlegende Sicherheitsrichtlinien (TLS, ACL), Kontingente, DLQ/TTL.
11-25 Tage
Implementieren outbox/inbox, idempotency und dedup.
Rückblenden mit Backoff einrichten (Rabbit: TTL + DLX; Kafka: retry topics).
Dashboards: Verzögerung, Alter, DLQ-Rate, Ende-zu-Ende-Latenz; Alertas.
26-45 Tage
Tuning des Durchsatzes: prefetch/acks (Rabbit); partitions/acks/batch (Kafka).
DR-Verfahren (Spiegelung/Replikation), Knotenausfalltests.
Dokumentieren Sie Ereignisverträge (Diagramme) und Kompatibilitätsrichtlinien.
12) Anti-Muster
Ein „universelles“ Werkzeug für alle Aufgaben.
Keine DLQ/TTL: ewige Vergifter (poison messages).
Unbegrenzte „prefetch“ → Hunger der Verbraucher, Wachstum p99.
Kafka ohne Schlüssel → Verlust der Ordnung/heiße Parteien standardmäßig.
„Exactly-once“ ohne echtes Bedürfnis/Disziplin ist ein falsches Sicherheitsgefühl.
Geheimnisse/Logins im Code, ohne TLS/ACL.
Hardcode von Schemas/Versionen von Nachrichten ohne Registry und Migrationen.
13) Reifegradkennzahlen
Lag/age SLO wird ≥ 99% der Zeit ausgeführt; DLQ-Rate unter Kontrolle.
Idempotenz deckt 100% der kritischen Pfade ab; outbox/inbox implementiert.
Retention/Compaction sind dokumentiert, Replikate brechen Verbraucher nicht.
Alerts für ISR/URP (Kafka) und Raft/Disk Limits (Rabbit) sind konfiguriert.
Die Ereignisverträge werden versioniert (Schema Registry), die Kompatibilität in CI getestet.
Regelmäßige Spieltage: Ausfall Knoten/Broker/AZ, Überprüfung der Wiederherstellung.
14) Beispiele für Config (Zusammenfassung)
RabbitMQ: Präfetch und Bestätigungen (Pseudocode):python channel. basic_qos(prefetch_count=200)
for msg in consume("tasks"):
try:
handle(msg)
channel. basic_ack(msg. delivery_tag)
except Transient:
channel. basic_nack(msg. delivery_tag, request = False) # will go to DLQ
Kafka Consumer (Ideen):
java props. put("enable. auto. commit","false");
props. put("isolation. level","read_committed"); // при EOS
//...
poll -> process(idempotent) -> commitSync()
15) Fazit
RabbitMQ und Kafka lösen verschiedene Klassen von Aufgaben: Teams/Tasks und Rich Routing gegen ein langfristiges Ereignisprotokoll und skalierbares Streaming. Erfolg liegt in der richtigen Liefersemantik, der Disziplin der Idempotenz, der durchdachten Keynote, den Retrays/DLQs, der Beobachtbarkeit und der strengen Sicherheit. Bauen Sie Engineering-Praktiken - Outbox/Inbox, Schemata und GitOps-Richtlinien - um die Warteschlangen auf und Ihre Integration wird vorhersehbar, skalierbar und nachhaltig.