CQRS: Befehle und Abfragen für bessere Performance trennen

CQRS: Befehle und Abfragen für bessere Performance trennen
Was ist Command Query Responsibility Segregation (CQRS)?
Command Query Responsibility Segregation (CQRS) ist ein Entwurfsmuster, das die Aktionen, die Daten ändern (Befehle), von denen trennt, die Daten abrufen (Abfragen). Anstatt dasselbe Modell für beides zu verwenden, teilt CQRS sie in zwei unterschiedliche Pfade auf. Durch die Trennung von Befehlen und Abfragen können Systeme jede Aufgabe effizienter verarbeiten, was zu besserer Performance, klarerem Code und einfacherer Skalierung führt, wenn deine Anwendung wächst.
Schlüsselkonzepte von CQRS
Befehl
Ein Befehl ist eine Aktion, die Daten im System ändert, beispielsweise eine Schreiboperation in der Datenbank. Er stellt eine Anfrage dar, eine bestimmte Aufgabe auszuführen, etwa etwas zu erstellen, zu aktualisieren oder zu löschen. Befehle geben keine Daten zurück; sie weisen das System an, „etwas zu tun“.
Beispiel: Wenn Benutzer ihre Profilinformationen aktualisieren, wird ein Befehl wie „UpdateUserProfile“ gesendet, um ihren Namen, ihre E-Mail-Adresse oder andere Systemdetails zu ändern.
Abfrage
Eine Abfrage ist eine Anfrage zum Abrufen von Daten, ohne sie zu ändern, d. h. die Leseoperation in der Datenbank. Abfragen werden verwendet, um Informationen zu erhalten, z. B. um Daten zu suchen oder anzuzeigen. Im Gegensatz zu Befehlen geben Abfragen nur Daten zurück und ändern nichts.
Beispiel: Wenn ein Benutzer seine Profildetails anzeigen möchte, ruft eine Abfrage wie „GetUserProfile“ die relevanten Informationen aus dem System ab.
Wie funktioniert CQRS?
Eine Analogie aus der Praxis, um die Funktionsweise von CQRS zu verstehen, ist, es sich wie getrennte Fahrspuren für Autos und Lastwagen auf einer Autobahn vorzustellen. Lastwagen transportieren schwere Lasten (Befehle), während Autos sich schnell und reibungslos bewegen (Abfragen). Indem sie auf ihren eigenen Spuren bleiben, fließt der Verkehr besser, und beide Aufgaben werden effizienter erledigt.
CQRS funktioniert, indem die Verarbeitung von Befehlen (Datenänderungen) und Abfragen (Datenabruf) klar getrennt wird. Wenn ein Befehl ausgegeben wird, beispielsweise zum Einfügen oder Aktualisieren von Daten, läuft er durch einen dedizierten Pfad, der dafür ausgelegt ist, Änderungen zu verarbeiten. Das System verarbeitet diese Befehle präzise und löst dabei häufig zugehörige Geschäftslogik oder Ereignisse aus. Abfragen hingegen werden durch einen anderen Pfad geleitet, der für schnelle und effiziente Datenlesevorgänge optimiert ist.
Es ist wichtig zu beachten, dass die Trennung von Befehlen und Abfragen in CQRS nicht zwangsläufig bedeutet, dass du für beides unterschiedliche Datenbanken verwenden musst. Der Fokus liegt auf der Trennung von Verhaltensweisen und Verantwortlichkeiten, was bei Bedarf innerhalb derselben Datenbank oder über mehrere Datenbanken hinweg erfolgen kann.
Abbildung- CQRS High-Level Architecture.png
Abbildung: CQRS High-Level Architecture
Beispiel: Ein Benutzerregistrierungssystem
Wenn sich ein Benutzer registriert, wird ein Befehl namens RegisterUserCommand ausgelöst. Dieser Befehl erstellt den neuen Benutzer, validiert seine Angaben und fügt ihn der Datenbank hinzu. Im Hintergrund wird ein Ereignis wie `UserRegisteredEvent` gespeichert, das diese Änderung aufzeichnet.
Wenn später ein anderer Teil des Systems (oder der Benutzer) die Details des Benutzers anzeigen muss, wird eine Abfrage namens GetUserProfileQuery verwendet. Die Abfrage ruft die Profildaten des Benutzers aus der Datenbank ab, ohne Änderungen vorzunehmen.
CQRS und Event Sourcing
Event Sourcing ist eine Technik, die häufig mit CQRS verwendet wird. In traditionellen Systemen speichern wir bei Datenänderungen (etwa wenn ein Benutzer sein Profil aktualisiert) nur den endgültigen Zustand der Daten. Wenn ein Benutzer beispielsweise seine E-Mail-Adresse ändert, speichern wir nur die neue E-Mail in der Datenbank, und die alte E-Mail geht verloren.
Mit Event Sourcing speichern wir statt nur des endgültigen Zustands jede Änderung als separates Ereignis. Im Fall einer Benutzerprofilaktualisierung speichern wir also Ereignisse wie „User created“, „Email updated“ oder „Profile picture changed“. Jedes Ereignis zeichnet auf, was passiert ist und wann. Diese Ereignisse werden in einer Reihenfolge gespeichert, fast wie ein Verlaufsprotokoll von allem im System.
Diese Ereignisse werden zur maßgeblichen Quelle des Systems. Wenn ein Befehl ausgeführt wird (z. B. das Aktualisieren des Benutzerprofils), wird ein neues Ereignis erstellt und dieser Ereignisliste hinzugefügt. Im Laufe der Zeit bilden all diese Ereignisse die gesamte Änderungshistorie ab.
Wenn du den aktuellen Zustand des Systems abfragen oder anzeigen musst (wie das Abrufen des Benutzerprofils), kann das System diese Ereignisse in der richtigen Reihenfolge erneut abspielen, um den aktuellen Zustand zu rekonstruieren. Beispielsweise könnte es die Ereignisse „User created“ und „Email updated“ erneut abspielen, um die aktuelle E-Mail-Adresse und die Profildetails anzuzeigen.
Unterschied zwischen CQRS und CQS
Während CQRS (Command Query Responsibility Segregation) und CQS (Command Query Separation) beides Entwurfsprinzipien sind, die die Unterscheidung zwischen Befehlen und Abfragen betonen, unterscheiden sie sich in einigen Aspekten leicht.
| Aspekt | CQS (Command Query Separation) | CQRS (Command Query Responsibility Segregation) |
|---|---|---|
| Definition | Methoden sind entweder Befehle (ändern Daten) oder Abfragen (rufen Daten ab). | Das System trennt Befehle und Abfragen in unterschiedliche Modelle oder Pfade. |
| Komplexität | Einfaches Prinzip, das innerhalb von Methoden angewendet wird. | Komplexer und beinhaltet separate Modelle oder Schichten für Befehle und Abfragen. |
| Anwendungsfall | Geeignet für einfachere Systeme, in denen Befehle und Abfragen innerhalb derselben Struktur behandelt werden. | Ideal für große, komplexe Systeme, in denen Lese- und Schreibvorgänge separat optimiert werden können. |
| Datenverarbeitung | Dasselbe Datenmodell wird sowohl für Befehle als auch für Abfragen verwendet. | Befehle und Abfragen können unterschiedliche Datenmodelle oder sogar Datenbanken verwenden. |
| Fokus | Hauptsächlich darauf ausgerichtet, dass Methoden eine einzige Verantwortung haben. | Konzentriert sich auf Skalierbarkeit, Leistung und Trennung von Verantwortlichkeiten im gesamten System. |
| Skalierbarkeit | Geringerer Einfluss auf die Skalierbarkeit des Systems, da beide in einem Modell behandelt werden. | Hohe Skalierbarkeit, da Befehle und Abfragen unabhängig behandelt werden. |
| Flexibilität | Begrenzte Flexibilität, da beide Operationen in einer Struktur miteinander verbunden sind. | Größere Flexibilität; du kannst unterschiedliche Datenbanken oder Speichermechanismen für Befehle und Abfragen verwenden. |
| Event Sourcing | Wird normalerweise nicht verwendet. | Wird häufig mit Event Sourcing verwendet, um alle Änderungen im Laufe der Zeit nachzuverfolgen. |
Tabelle: Unterschied zwischen CQS und CQRS
Anwendungsfälle für CQRS
Hier sind einige gängige Szenarien, in denen CQRS nützlich ist:
Hohe Lese-/Schreiblasten
In Szenarien, in denen ein erhebliches Ungleichgewicht zwischen der Anzahl der Lese- und Schreiboperationen besteht, ist CQRS ideal. Beispielsweise kann eine E-Commerce-Plattform eine große Anzahl von Benutzern haben, die Produktinformationen abfragen (Lesevorgänge), aber weniger Benutzer, die ihre Warenkörbe aktualisieren oder Käufe tätigen (Schreibvorgänge). CQRS ermöglicht es dem System, die Abfrageseite unabhängig zu skalieren, um das hohe Volumen an Leseanfragen zu bewältigen, ohne die Schreiboperationen zu beeinträchtigen.
Komplexe Geschäftslogik
Beim Umgang mit komplexen Geschäftsregeln, die nur für Datenänderungen (Commands) gelten, hilft CQRS, indem es diese Komplexität isoliert. Beispielsweise kann die Command-Seite in einem Finanzsystem, in dem Transaktionen stark reguliert sind, strenge Validierungs- und Verarbeitungsregeln durchsetzen. Im Gegensatz dazu bleibt die Query-Seite einfach und darauf fokussiert, Kontostände oder Transaktionshistorien abzurufen.
Event Sourcing und Audit Trails
In Systemen, in denen die Pflege eines vollständigen Audit Trails jeder Änderung erforderlich ist, lässt sich CQRS gut mit Event Sourcing kombinieren. Beispielsweise kann in einer Gesundheitsanwendung jede Änderung an der Krankenakte eines Patienten als Event gespeichert werden, sodass das System leicht nachverfolgen kann, wer Änderungen vorgenommen hat und wann, während Queries schnell auf den aktuellen Zustand der Akte zugreifen können.
Echtzeit-Analysen
Für Anwendungen, die Echtzeit-Analysen erfordern, wie etwa Social-Media-Plattformen, kann CQRS ständige Aktualisierungen von Benutzerdaten (z. B. Likes, Shares) verarbeiten und gleichzeitig Queries für Echtzeit-Einblicke (z. B. Trending Topics) bearbeiten. Die Query-Seite kann für Geschwindigkeit optimiert werden, ohne von den laufenden Aktualisierungen auf der Command-Seite beeinträchtigt zu werden.
Microservices-Architekturen
In Microservices-basierten Systemen stellt CQRS verschiedene Services bereit, um Commands und Queries unabhängig voneinander zu verarbeiten. Beispielsweise kann in einem Logistikunternehmen ein Service die Auftragsverarbeitung (Commands) verwalten, während ein anderer Tracking und Reporting (Queries) übernimmt, wodurch die Flexibilität und Wartbarkeit des Systems verbessert wird.
Tools und Frameworks, die CQRS unterstützen
Mehrere Tools und Frameworks erleichtern die Implementierung von CQRS. Hier ist ein kurzer Überblick über einige beliebte Optionen:
Axon Framework (Java) ist ein umfassendes Framework, das CQRS und Event Sourcing unterstützt. Es bietet integrierte Komponenten für die Verarbeitung von Commands, Queries und Events, was es zu einer beliebten Wahl für komplexe Java-Anwendungen macht.
MediatR ist eine weitere leichtgewichtige Bibliothek für .NET-Anwendungen, die die Trennung von Commands und Queries vereinfacht. Sie hilft dabei, Requests auf saubere und organisierte Weise weiterzuleiten, was perfekt für CQRS in kleinen bis mittelgroßen Systemen ist.
Laravel Command Bus ist Teil des Laravel-Frameworks. Entwickler verwenden dieses Tool, um Commands und Queries getrennt zu definieren. Es ist eine großartige Option für PHP-basierte Anwendungen, die CQRS implementieren möchten.
EventStore ist eine spezialisierte Datenbank, die für Event Sourcing entwickelt wurde und häufig mit CQRS kombiniert wird. Sie speichert Events statt nur Daten und ermöglicht so die einfache Wiedergabe vergangener Events, um den Zustand des Systems zu rekonstruieren.
NServiceBus ist ein Messaging-Framework, das gut mit CQRS funktioniert, indem es Commands, Events und Messages über verteilte Systeme hinweg verarbeitet. Es ist ideal für Microservices-Architekturen, die CQRS verwenden.
Vorteile von CQRS
Verbesserte Skalierbarkeit und Performance
Durch die Trennung von Commands und Queries kann CQRS jeden Teil unabhängig skalieren. Wenn Ihre Anwendung beispielsweise deutlich mehr Leseoperationen (Queries) als Schreiboperationen (Commands) verarbeitet, können Sie die Query-Seite skalieren, ohne die Command-Seite zu beeinflussen, wodurch die Gesamtperformance verbessert wird.
Klarere Code-Organisation
CQRS fördert eine saubere Trennung der Verantwortlichkeiten. Commands befassen sich mit Änderungen, und Queries übernehmen den Datenabruf. Dadurch wird der Code leichter verständlich und wartbar, da jeder Systemteil eine klare Verantwortung hat.
Bessere Handhabung komplexer Geschäftsregeln
Mit CQRS können komplexe Geschäftsregeln im Zusammenhang mit der Aktualisierung von Daten auf der Command-Seite verarbeitet werden, während einfachere, effiziente Queries zum Lesen von Daten verwendet werden können. Diese Aufteilung hilft, komplexe Logik zu verwalten, ohne das System zu überlasten oder den Code zu kompliziert zu machen.
Flexibilität bei der Datenbankauswahl für das Lesen vs. Schreiben von Daten
CQRS gibt Ihnen die freie Wahl, unterschiedliche Datenbanken für Commands und Queries zu verwenden. Beispielsweise könnten Sie eine hochoptimierte NoSQL-Datenbank für schnelle Lesevorgänge (Queries) und eine relationale Datenbank für Schreibvorgänge (Commands) verwenden. Diese Flexibilität ermöglicht es Ihnen, die besten Tools für jede Aufgabe auszuwählen.
Herausforderungen und Überlegungen zu CQRS
Erhöhte Komplexität
Mit CQRS müssen Sie zwei separate Modelle verwalten: eines zur Verarbeitung von Commands (Schreibvorgängen) und ein weiteres zur Verarbeitung von Queries (Lesevorgängen). Dies erhöht die Komplexität der Codebasis, da Sie beide Modelle pflegen und aktualisieren müssen, wodurch der Aufwand für die Entwicklung und Wartung des Systems steigt.
Herausforderungen bei der Synchronisierung
Die Command- und Query-Seiten synchron zu halten, kann schwierig sein. Wenn Daten über einen Command geschrieben werden, kann es einige Zeit dauern, bis die Änderungen auf der Query-Seite sichtbar werden, was zu potenziellen Verzögerungen führt. Die Verwaltung dieser Synchronisierung ist wichtig, um korrekte Daten im gesamten System sicherzustellen.
Entscheiden, wann CQRS überdimensioniert ist
CQRS ist für einfache CRUD-Anwendungen (Create, Read, Update, Delete) nicht notwendig. In Systemen mit unkomplizierten Datenanforderungen ist die zusätzliche Komplexität von CQRS möglicherweise nicht lohnenswert. CQRS eignet sich am besten für komplexe Systeme mit einem hohen Volumen an Lese- und Schreibvorgängen oder komplexer Geschäftslogik.
Kosten
Die Implementierung von CQRS erfordert häufig zusätzliche Infrastruktur, beispielsweise die Pflege separater Datenbanken für Commands und Queries. Dies kann die Hardware- und Cloud-Service-Kosten erhöhen, insbesondere wenn beide Seiten skaliert werden. Der Bedarf an mehreren Technologien zur Bewältigung dieser Aufgaben kann die Ausgaben in die Höhe treiben.
Wie CQRS in Vektordatenbanken und Big Data eine Rolle spielt
In Vektordatenbanken wie Milvus bietet CQRS eine strukturierte Möglichkeit, unterschiedliche Arten von Operationen zu handhaben:
Commands: Dazu gehören Aufgaben wie das Einfügen oder Aktualisieren großer Mengen von Vektoren (z. B. Vektoreinbettungen, die von Machine-Learning-Modellen erzeugt werden). In Milvus würden Commands den Zustand der Datenbank aktualisieren.
Queries: Diese Operationen rufen Vektoren ab, beispielsweise das Finden ähnlicher Elemente in einem großen Datensatz mithilfe der Ähnlichkeitssuche. Milvus-Queries können hochdimensionale Vektoren zurückgeben, die bestimmten Kriterien entsprechen, und sie werden häufig in Echtzeit-Analysen oder KI-Anwendungen wie Empfehlungssystemen und Retrieval Augmented Generation (RAG) verwendet.
Beispiel: Umgang mit Echtzeit-Analyse-Queries vs. Einfügen/Aktualisieren von Vektoren
Angenommen, Sie betreiben ein KI-gestütztes Empfehlungssystem auf Zilliz Cloud (der verwalteten Version von Milvus). Wenn neue Benutzerdaten oder Produktvektoren generiert werden, gibt das System Commands aus, um die Vektordatenbank mit frischen Einbettungen zu aktualisieren. Diese Commands stellen sicher, dass die neuesten Vektoren in Milvus eingefügt oder aktualisiert werden.
Gleichzeitig werden Echtzeit-Analysen mithilfe von Queries durchgeführt, um die ähnlichsten Vektoren für Empfehlungen abzurufen. Die Query-Seite ist darauf optimiert, relevante Daten schnell zu finden, ohne durch die ständigen Vektoreinfügungen auf der Command-Seite beeinträchtigt zu werden.
Fazit
CQRS bietet eine leistungsstarke Möglichkeit, komplexe Systeme zu verwalten, indem Commands (Datenänderungen) und Queries (Datenabruf) getrennt werden. Diese Trennung verbessert Skalierbarkeit, Performance und Code-Klarheit, insbesondere in groß angelegten Anwendungen mit komplexer Geschäftslogik. Obwohl CQRS eine gewisse Komplexität hinzufügt, bietet es erhebliche Vorteile, wenn es in den richtigen Szenarien eingesetzt wird, beispielsweise in Systemen, die Echtzeit-Analysen, hohe Lese-/Schreiblasten oder Event Sourcing bewältigen. Für einfachere Anwendungen ist die zusätzliche Komplexität jedoch möglicherweise nicht notwendig. Zusammenfassend ist CQRS ein wertvolles Werkzeug zur Steigerung der Systemeffizienz und Flexibilität, wenn es angemessen angewendet wird.
FAQ’s zu CQRS
- Was ist der Hauptvorteil der Verwendung von CQRS?
CQRS trennt die Verantwortlichkeiten für das Aktualisieren von Daten (Commands) und das Abrufen von Daten (Queries), was die Skalierbarkeit, Leistung und Klarheit des Codes des Systems verbessert. Jede Seite kann unabhängig optimiert werden, wodurch es für Systeme mit hohem Volumen oder hoher Komplexität nützlich ist.
- Wann sollte ich die Verwendung von CQRS vermeiden?
CQRS kann bei einfachen CRUD-Anwendungen unnötige Komplexität hinzufügen, wenn keine separate Behandlung von Lese- und Schreibvorgängen erforderlich ist. Wenn Ihre Anwendung keine erheblichen Leistungsanforderungen oder keine komplexe Geschäftslogik hat, kann CQRS überdimensioniert sein.
- Muss ich in CQRS separate Datenbanken für Commands und Queries verwenden?
Nein, die Verwendung separater Datenbanken für Commands und Queries ist nicht erforderlich. Obwohl Sie für CQRS unterschiedliche Datenbanken verwenden können, besteht der Kern darin, das Verhalten und die Verantwortung im Code zu trennen. Sie können weiterhin eine einzelne Datenbank verwenden, wenn dies den Anforderungen Ihrer Anwendung entspricht.
- Wie funktioniert CQRS mit Event Sourcing?
Beim Event Sourcing wird jede Änderung am System als Ereignis gespeichert. CQRS ergänzt dies, indem es Commands verarbeitet, die Ereignisse erzeugen, und Queries verwendet, um den Zustand des Systems durch erneutes Abspielen dieser Ereignisse zu rekonstruieren. So wird eine vollständige Änderungshistorie beibehalten, was Audits oder Debugging erleichtert.
- Kann CQRS die Leistung von Echtzeit-Analyseanwendungen verbessern?
Ja, CQRS ist für Echtzeit-Analysen nützlich. Es ermöglicht dem System, kontinuierliche Aktualisierungen (Commands) getrennt von Echtzeit-Datenabfragen zu verarbeiten, wobei jede Seite für ihren Zweck optimiert wird und verhindert wird, dass die eine die andere verlangsamt.
- Welche Herausforderungen gibt es bei der Implementierung von CQRS?
Zu den wichtigsten Herausforderungen gehören erhöhte Komplexität, die Verwaltung der Synchronisierung zwischen Command- und Query-Modellen, der Umgang mit Problemen der eventual consistency und potenziell höhere Infrastrukturkosten durch die Pflege separater Pfade oder Datenbanken.
Verwandte Ressourcen
- Was ist Command Query Responsibility Segregation (CQRS)?
- Schlüsselkonzepte von CQRS
- Wie funktioniert CQRS?
- CQRS und Event Sourcing
- Unterschied zwischen CQRS und CQS
- Anwendungsfälle für CQRS
- Tools und Frameworks, die CQRS unterstützen
- Vorteile von CQRS
- Herausforderungen und Überlegungen zu CQRS
- Wie CQRS in Vektordatenbanken und Big Data eine Rolle spielt
- Fazit
- FAQ’s zu CQRS
- Verwandte Ressourcen
Inhalte
Kostenlos starten, einfach skalieren
Testen Sie die vollständig verwaltete Vektordatenbank, die für Ihre GenAI-Anwendungen entwickelt wurde.
Zilliz Cloud kostenlos ausprobieren

