Warum Datenbank als Warteschlange so schlecht? [geschlossen]

33

Ich habe gerade diesen Artikel gelesen und bin verwirrt.

Stellen wir uns eine Webanwendung und eine separate Anwendung als "Worker" vor, die beide dieselbe Datenbank verwenden .

Oh, ich sagte "Teilen" ... aber wovor warnt der Artikel? :

Viertens ist die gemeinsame Nutzung einer Datenbank zwischen Anwendungen (oder Diensten) eine schlechte Sache. Es ist einfach zu verlockend, einen amorphen geteilten Zustand einzurichten, und bevor Sie es merken, haben Sie ein enorm gekoppeltes Monster.

=> nicht einverstanden. Es gibt einige Fälle, in denen unterschiedliche Anwendungen immer noch Teil derselben Einheit sind, und daher macht der Begriff "Kopplungsproblem" in diesem Fall keinen Sinn.

Fahren wir fort: Die Webanwendung verarbeitet HTTP-Clientanforderungen und kann jederzeit einige Aggregate (DDD-Term) aktualisieren und die entsprechenden Domänenereignisse generieren.
Das Ziel des Workers wäre es, diese Domänenereignisse zu verarbeiten, indem die erforderlichen Jobs verarbeitet werden.

Der Punkt ist:

Wie sollen Ereignisdaten an den Worker übergeben werden?

Die erste Lösung, wie der gelesene Artikel bewirbt, wäre die Verwendung von RabbitMQ, einer großartigen nachrichtenorientierten Middleware.

Der Workflow wäre einfach:

Jedes Mal, wenn der Web-Dyno ein Ereignis generiert, veröffentlicht er es über RabbitMQ, das den Arbeiter füttert.
Der Nachteil wäre, dass nichts die sofortige Konsistenz zwischen dem Festschreiben des aggregierten Updates und dem Veröffentlichen des Ereignisses garantiert , ohne sich mit den möglichen Sendefehlern oder Hardwareproblemen zu befassen. das ist ein weiteres Hauptproblem.

Beispiel: Möglicherweise wurde ein Ereignis veröffentlicht, ohne dass die Gesamtaktualisierung erfolgreich war. Dies führte zu einem Ereignis, das eine falsche Darstellung des Domänenmodells darstellt.
Sie könnten argumentieren, dass globales XA (Zwei-Phasen-Commit) vorhanden ist, aber es ist keine Lösung, die für alle Datenbanken oder Middlewares geeignet ist.

Was könnte also eine gute Lösung sein, um diese sofortige Konsistenz sicherzustellen? :
IMO, Speichern des Ereignisses in der Datenbank in derselben lokalen Transaktion wie die Aggregataktualisierung.
Ein einfacher asynchroner Scheduler würde erstellt und dafür verantwortlich sein, aktuelle unveröffentlichte Ereignisse aus der Datenbank abzufragen und sie an RabbitMQ zu senden, das wiederum den Worker auffüllt.

Aber warum braucht man einen zusätzlichen Scheduler auf der Webapp-Seite und im Übrigen: Warum braucht man in diesem Fall RabbitMQ?

Bei dieser Lösung scheint es logisch, dass RabbitMQ unnötig sein könnte, insbesondere weil die Datenbank gemeinsam genutzt wird.
Tatsächlich, was auch immer der Fall ist , sahen wir , dass die unmittelbare Konsequenz beinhaltet eine Abfrage aus der Datenbank.
Warum sollte der Arbeitnehmer nicht direkt für diese Umfrage verantwortlich sein?

Deshalb frage ich mich, warum so viele Artikel im Web kaum Datenbankwarteschlangen kritisieren und gleichzeitig eine nachrichtenorientierte Middleware fördern.

Auszug aus dem Artikel:

Verwenden Sie einfach das richtige Tool für den Job: Dieses Szenario verlangt nach einem Messaging-System. Es löst alle oben beschriebenen Probleme. Keine Abfrage mehr, effiziente Nachrichtenübermittlung, keine Notwendigkeit, abgeschlossene Nachrichten aus Warteschlangen zu löschen, und kein gemeinsamer Status.

Und sofortige Konsistenz, ignoriert?

Zusammenfassend scheint es wirklich so zu sein, dass wir in jedem Fall, dh wenn eine Datenbank freigegeben ist oder nicht, eine Datenbankabfrage benötigen .

Habe ich einige kritische Begriffe übersehen?

Vielen Dank

Mik378
quelle
2
Polling ist eine Art roter Faden, da fast alle wichtigen Datenbanken über einen Mechanismus verfügen, mit dem ein anderer Prozess asynchron benachrichtigt wird, dass es Zeit ist, etwas Arbeit aus einer Tabelle zu ziehen.
Blrfl

Antworten:

28

Wenn Sie eine einfache Anwendung mit geringem Datenverkehr erstellen, sollten Sie eine andere Komponente aus Ihrem System heraushalten. Es ist sehr wahrscheinlich, dass kein Nachrichtenbus die richtige Antwort für Sie ist. Ich würde jedoch vorschlagen, Ihr System so aufzubauen, dass Sie das datenbankbasierte Warteschlangensystem gegen eine Middleware-Lösung austauschen können. Ich stimme dem Artikel zu. Eine Datenbank ist nicht das richtige Tool für ein warteschlangenbasiertes System, kann aber für Sie gut genug sein.

Warteschlangenbasierte Systeme wie RabbitMq sind massiv auf mäßiger Hardware aufgebaut. Ihre Architektur kann dies erreichen, indem sie Prozesse vermeidet, die das ACID- kompatible Datenbanksystem von Natur aus verlangsamen. Da ein Nachrichtenbus nur sicherstellen muss, dass eine Nachricht gespeichert und erfolgreich verarbeitet wird, muss er sich nicht mit dem Sperren und Schreiben von Transaktionsprotokollen befassen. Beide Konzepte sind für ein ACID-System unbedingt erforderlich, aber häufig umstritten.

In Bezug auf die Leistung kommt es darauf an: Sie haben eine SQL-Tabelle. Viele Lese- und Schreibvorgänge. Beide erfordern eine Art Sperrung, um Zeilen, Seiten und Indizes zu aktualisieren. Ihr Abfragemechanismus sperrt ständig einen Index, um darin nachzuschlagen. Dies verhindert, dass Schreibvorgänge ausgeführt werden. Bestenfalls stehen sie in der Warteschlange. Der Code, der die Verarbeitung ausführt, wird ebenfalls gesperrt, um den Status in der Warteschlange zu aktualisieren, sobald sie abgeschlossen sind oder fehlschlagen. Ja, Sie können die Abfrageoptimierung nach der Optimierung durchführen, um dies zum Laufen zu bringen, oder Sie können ein System verwenden, das speziell für die von Ihnen angeforderte Arbeitslast entwickelt wurde. Ein RabbitMq frisst diese Art von Arbeit, ohne auch nur ins Schwitzen zu geraten. Darüber hinaus können Sie Ihre Datenbank vor dem Arbeitsaufwand schützen, um mehr Platz für die Skalierung anderer Aufgaben zu haben.

Eine andere zu berücksichtigende Sache ist, dass die meisten Warteschlangensysteme normalerweise keine Abfragetechnik verwenden (einige erlauben HTTP, empfehlen jedoch, die Verwendung für die Empfangsseite zu vermeiden). RabbitMq verwendet Netzwerkprotokolle, die speziell für Nachrichtenbusse wie AMPQ entwickelt wurden .

Bearbeiten: Hinzufügen eines Anwendungsfalls.

Die Art, wie ich Rabbit verwendet habe, ist, dass ich einen API-Endpunkt hatte, der eine Änderung akzeptiert, die eine stark verwendete Datenbanktabelle erfordert. Diese Tabelle steht unter ständigem Konflikt und kann zeitweise Änderungen nicht rechtzeitig über die API speichern. Stattdessen schreibe ich die Änderungsanforderung in eine Warteschlange und habe dann einen Dienst, der diese Nachrichten so behandelt, wie sie können. Wenn Datenbankkonflikte auftreten, wächst die Warteschlange einfach und die Nachrichtenverarbeitung wird verzögert. Normalerweise liegt die Verarbeitungszeit im Bereich von 14 ms, aber in Zeiten hoher Konkurrenz können wir bis zu 2-3 Sekunden erreichen.

brianfeucht
quelle
Wie könnten Sie in diesem Fall sofort mit Konsistenz umgehen? Wenn die Veröffentlichung erfolgt, jedoch direkt danach, wird die Transaktion, die für die Aktualisierung des Domain-Modells verantwortlich ist, zurückgesetzt. Die Middleware würde das Ereignis vollständig ignorieren und verarbeiten.
Mik378
Sie haben geschrieben: "Es muss sich nicht um das Sperren kümmern". Aber es gibt sicherlich eine Art Sperrung, um die aufsteigende Reihenfolge (in der Zeit) der weitergeleiteten Ereignisse (in Richtung des Arbeitnehmers) sicherzustellen, nicht wahr?
Mik378
@ Mik378 Sehen Sie sich diesen Artikel über die Idempotenz von Nachrichten an . Ja, technisch gesehen verlieren Sie ein gewisses Konsistenzversprechen, aber ich wette, Sie werden feststellen, dass sich das, was Sie in Bezug auf die Zuverlässigkeit der Anwendungsverfügbarkeit und -leistung gewinnen, lohnt. Es ist auch ziemlich einfach, die Art und Weise zu ändern, in der Sie Nachrichten verarbeiten, um die Verluste ziemlich schmerzlos zu machen.
brianfeucht
2
Ja, Sie benötigen eine Sperre, um die Bestellung zu garantieren. Einige Warteschlangensysteme bieten dies zum Preis der Leistung. Wenn Sie die Tatsache akzeptieren können, dass Vorgänge manchmal nicht in der richtigen Reihenfolge ablaufen, und herausfinden, wie Sie damit auf der Prozessorseite umgehen können, werden Sie vom Standpunkt der Leistung aus exponentiell profitieren.
brianfeucht
1
@ Mik378 - Ich habe meiner Antwort einen Anwendungsfall hinzugefügt. Ich hoffe, es hilft!
brianfeucht