[ OK ]Kernel wird initialisiert...
~/im/blog
Kontakt aufnehmen

Lass uns reden

Interesse an einer Zusammenarbeit oder eine Frage? Ich bin immer offen für neue Projekte.

Kontakt aufnehmen

Vernetzen

Finden Sie mich in sozialen Medien und auf beruflichen Netzwerken.

DatenschutzerklärungNutzungsbedingungen
© 2026 Irfan MiralEntwickelt vonirfanMiral.com
StartÜber mich/LebenslaufBlogKontakt
2026-08-05• 5 Min. Lesezeit

Wenn eine Queue-Tabelle nicht mehr reicht: der Wechsel zu RabbitMQ

Datenbanken RabbitMQ Message Queues Architektur

Überraschend viele Produktionssysteme handhaben Hintergrundarbeit auf dieselbe Art: eine jobs-Tabelle, eine status-Spalte (pending, processing, done, failed), und ein oder mehrere Worker, die sie in einer Schleife abfragen, ausstehende Zeilen aufgreifen und dabei ihren Status aktualisieren. Das ist ein völlig vernünftiger Anfang. Es braucht keine neue Infrastruktur, lässt sich leicht inspizieren (SELECT * FROM jobs WHERE status = 'failed' ist ein Debugging-Werkzeug, das jeder schon kennt), und bei niedrigem Volumen funktioniert es lange Zeit ohne Probleme.

Die Anzeichen, dass eine Tabelle das hinter sich gelassen hat, sind selten "zu viel Volumen" im Abstrakten. Sie sind konkreter als das.

Das Polling selbst wird zur Last

Jeder Worker, der die Tabelle alle paar Sekunden prüft, ist eine Query, egal ob es etwas zu tun gibt oder nicht. Bei niedrigem Volumen ist das vernachlässigbar. Wächst die Tabelle und kommen für mehr Durchsatz weitere Worker hinzu, wird dieses Polling zu einer konstanten Hintergrundlast auf der Datenbank, die mit den eigentlichen Anwendungsqueries konkurriert, die sie unterstützen soll, und SELECT ... FOR UPDATE SKIP LOCKED (die richtige Art, das sicher zu machen) ändert nichts daran, dass jeder Worker bei jedem Zyklus dieselbe Tabelle trifft.

Retries und Fehlerbehandlung werden neu erfunden, schlecht

Die Retry-Logik einer Queue-Tabelle ist meist eine retry_count-Spalte und etwas Anwendungscode, der sie erhöht und den Job neu einreiht, bis es eben nicht mehr funktioniert: Edge Cases rund um Jobs, die teilweise abgeschlossen waren, bevor sie fehlschlugen, Jobs, die doppelt aufgegriffen werden, weil zwei Worker im selben Moment gepollt haben, oder fehlgeschlagene Jobs, die sich anhäufen, ohne dass klar ist, warum, sammeln sich mit der Zeit als Sonderfälle an. Das sind keine schwierigen Probleme, aber es sind Probleme, die eine Message Queue schon vor Jahren gelöst hat, und sie im Anwendungscode neu zu lösen bedeutet, auch ihre Edge Cases neu zu lösen.

Was RabbitMQ tatsächlich ändert

RabbitMQ dreht das Modell von Pull auf Push um: Ein Producer veröffentlicht eine Nachricht an einen Exchange, RabbitMQ routet sie anhand von Bindings an eine Queue, und Consumer empfangen Nachrichten, sobald sie eintreffen, statt wiederholt nachzufragen:

# Producer
channel.basic_publish(
    exchange='',
    routing_key='email_benachrichtigungen',
    body=json.dumps({'user_id': 123, 'template': 'willkommen'}),
    properties=pika.BasicProperties(delivery_mode=2)  # persistent
)

# Consumer
def callback(ch, method, properties, body):
    process_notification(json.loads(body))
    ch.basic_ack(delivery_tag=method.delivery_tag)

channel.basic_consume(queue='email_benachrichtigungen', on_message_callback=callback)

basic_ack wird erst ausgelöst, nachdem die Nachricht erfolgreich verarbeitet wurde, stürzt der Consumer mitten in der Verarbeitung ab, liefert RabbitMQ die Nachricht erneut aus, weil sie nie bestätigt wurde. Fehlgeschlagene Nachrichten können automatisch an einen Dead-Letter-Exchange weitergeleitet werden, was eine separate Queue mit "Dingen, die fehlgeschlagen sind" ergibt, die sich inspizieren lässt, ohne diese Logik selbst zu schreiben.

Was bleibt, und was sich nicht direkt übertragen lässt

Das mentale Modell von "ein Job hat eine Payload und einen Status" verschwindet nicht, RabbitMQ ersetzt nicht das Konzept, sondern den Zustellmechanismus. Was sich nicht direkt übertragen lässt: Die Debugging-Gewohnheit SELECT * FROM jobs WHERE status = 'failed' wird zum Prüfen einer Dead-Letter-Queue, die eine andere (wohl sogar bessere, Nachrichten dort sind tatsächlich unzustellbar und nicht nur langsam) Form hat. Und alles, was sich darauf verlassen hat, dass die Queue-Tabelle zusammen mit anderen Anwendungsdaten in derselben Transaktion abfragbar ist, etwa eine Zeile und einen zugehörigen Queue-Eintrag atomar gemeinsam einzufügen, muss neu gedacht werden, da die Queue jetzt ein separates System ist.

Wenn die Tabelle immer noch die richtige Wahl ist

Ist das Volumen niedrig, sind die Jobs einfach, und registriert eine Handvoll Worker, die alle paar Sekunden pollen, in der Datenbank gar nicht als Last, ist eine Queue-Tabelle kein Fehler, sondern angemessen für das Problem dimensioniert. Der Wechsel zu RabbitMQ lohnt sich, wenn die Polling-Last in den Datenbank-Metriken sichtbar wird, wenn Retry- und Fehlerbehandlung im Anwendungscode ihre eigenen Edge Cases angesammelt haben, oder wenn mehrere unterschiedliche Services dieselben Events produzieren oder konsumieren müssen, an diesem Punkt hört ein Message Broker, der genau dafür gebaut wurde, auf, "zusätzliche Infrastruktur" zu sein, und wird zur einfacheren Option.

VorherigerRedis als Cache vs. Redis als DatenbankNächster Eine langsame WordPress-Seite beschleunigen: meine Reihenfolge