CQRS: separa comandi e query per prestazioni migliori

CQRS: separa comandi e query per prestazioni migliori
Che cos'è la Command Query Responsibility Segregation (CQRS)?
La Command Query Responsibility Segregation (CQRS) è un pattern di progettazione che separa le azioni che modificano i dati (comandi) da quelle che recuperano i dati (query). Invece di usare lo stesso modello per entrambi, CQRS li divide in due percorsi distinti. Separando comandi e query, i sistemi possono gestire ogni attività in modo più efficiente, portando a prestazioni migliori, codice più chiaro e scalabilità più semplice man mano che l'applicazione cresce.
Concetti chiave di CQRS
Comando
Un comando è un'azione che modifica i dati nel sistema, come un'operazione di scrittura nel database. Rappresenta una richiesta di eseguire un'attività specifica, come creare, aggiornare o eliminare qualcosa. I comandi non restituiscono dati; dicono al sistema di "fare qualcosa."
Esempio: quando gli utenti aggiornano le informazioni del proprio profilo, viene inviato un comando come “UpdateUserProfile” per modificare il loro nome, email o altri dettagli del sistema.
Query
Una query è una richiesta di recuperare dati senza modificarli, cioè l'operazione di lettura nel database. Le query vengono usate per ottenere informazioni, come cercare o visualizzare dati. A differenza dei comandi, le query restituiscono solo dati e non modificano nulla.
Esempio: quando un utente vuole visualizzare i dettagli del proprio profilo, una query come “GetUserProfile” recupera le informazioni rilevanti dal sistema.
Come funziona CQRS?
Un'analogia del mondo reale per comprendere il funzionamento di CQRS è pensarla come corsie separate per auto e camion su un'autostrada. I camion gestiscono carichi pesanti (comandi), mentre le auto si muovono rapidamente e senza intoppi (query). Tenendoli nelle proprie corsie, il traffico scorre meglio ed entrambe le attività vengono svolte in modo più efficiente.
CQRS opera separando chiaramente la gestione dei comandi (modifiche dei dati) e delle query (recupero dei dati). Quando viene emesso un comando, come l'inserimento o l'aggiornamento di dati, questo passa attraverso un percorso dedicato progettato per elaborare le modifiche. Il sistema elabora questi comandi in modo accurato, spesso attivando logiche di business o eventi correlati. Le query, invece, vengono indirizzate attraverso un percorso diverso, ottimizzato per letture dei dati rapide ed efficienti.
È importante notare che in CQRS separare comandi e query non significa necessariamente dover usare database diversi per ciascuno. L'attenzione è posta sulla separazione dei comportamenti e delle responsabilità, che può essere realizzata all'interno dello stesso database o su più database, se necessario.
Figure- CQRS High-Level Architecture.png
Figura: architettura di alto livello di CQRS
Esempio: un sistema di registrazione utenti
Quando un utente si registra, viene attivato un comando chiamato RegisterUserCommand. Questo comando crea il nuovo utente, convalida i suoi dettagli e lo aggiunge al database. Dietro le quinte, viene archiviato un evento come `UserRegisteredEvent` che registra questa modifica.
Più tardi, quando un'altra parte del sistema (o l'utente) deve visualizzare i dettagli dell'utente, viene usata una query chiamata GetUserProfileQuery. La query recupera i dati del profilo dell'utente dal database senza apportare alcuna modifica.
CQRS ed Event Sourcing
Event Sourcing è una tecnica spesso usata con CQRS. Nei sistemi tradizionali, quando i dati cambiano (come un utente che aggiorna il proprio profilo), salviamo solo lo stato finale dei dati. Ad esempio, se un utente cambia il proprio indirizzo email, memorizziamo solo la nuova email nel database e la vecchia email viene persa.
Con l'Event Sourcing, invece di salvare solo lo stato finale, memorizziamo ogni modifica come un evento separato. Quindi, nel caso dell'aggiornamento di un profilo utente, memorizziamo eventi come "Utente creato," "Email aggiornata," o "Immagine del profilo modificata." Ogni evento registra cosa è successo e quando. Questi eventi vengono salvati in sequenza, quasi come un registro storico di tutto ciò che avviene nel sistema.
Questi eventi diventano la fonte di verità del sistema. Quando viene eseguito un comando (ad esempio, l'aggiornamento del profilo dell'utente), viene creato un nuovo evento e aggiunto a questo elenco di eventi. Nel tempo, tutti questi eventi si accumulano fino a rappresentare l'intera cronologia delle modifiche.
Quando devi interrogare o visualizzare lo stato corrente del sistema (come il recupero del profilo utente), il sistema può riprodurre questi eventi nell'ordine corretto per ricostruire lo stato corrente. Ad esempio, potrebbe riprodurre gli eventi "Utente creato" e "Email aggiornata" per mostrare l'email corrente e i dettagli del profilo.
Differenza tra CQRS e CQS
Sebbene CQRS (Command Query Responsibility Segregation) e CQS (Command Query Separation) siano entrambi principi di progettazione che enfatizzano la distinzione tra comandi e query, sono leggermente diversi in alcuni aspetti.
| Aspetto | CQS (Command Query Separation) | CQRS (Command Query Responsibility Segregation) |
|---|---|---|
| Definizione | I metodi sono o comandi (modificano i dati) o query (recuperano i dati). | Il sistema separa comandi e query in modelli o percorsi distinti. |
| Complessità | Principio semplice applicato all'interno dei metodi. | Più complesso e comporta modelli o livelli separati per comandi e query. |
| Caso d'uso | Adatto a sistemi più semplici in cui comandi e query sono gestiti all'interno della stessa struttura. | Ideale per sistemi grandi e complessi in cui letture e scritture possono essere ottimizzate separatamente. |
| Gestione dati | Lo stesso modello di dati viene utilizzato sia per comandi sia per query. | Comandi e query possono usare modelli di dati diversi o persino database diversi. |
| Focus | Principalmente focalizzato sul fatto che i metodi abbiano una singola responsabilità. | Si concentra su scalabilità, prestazioni e separazione delle responsabilità in tutto il sistema. |
| Scalabilità | Minore impatto sulla scalabilità del sistema, poiché entrambi sono gestiti in un unico modello. | Elevata scalabilità, poiché comandi e query sono gestiti indipendentemente. |
| Flessibilità | Flessibilità limitata, poiché entrambe le operazioni sono legate insieme in un'unica struttura. | Maggiore flessibilità; puoi usare database o meccanismi di archiviazione diversi per comandi e query. |
| Event Sourcing | Non tipicamente utilizzato. | Spesso utilizzato con l'event sourcing per tracciare tutte le modifiche nel tempo. |
Tabella: Differenza tra CQS e CQRS
Casi d'uso per CQRS
Ecco alcuni scenari comuni in cui CQRS è utile:
Carichi di lavoro elevati in lettura/scrittura
Negli scenari in cui esiste uno squilibrio significativo tra il numero di operazioni di lettura e scrittura, CQRS è ideale. Ad esempio, una piattaforma di e-commerce può avere un gran numero di utenti che interrogano le informazioni sui prodotti (letture), ma meno utenti che aggiornano i propri carrelli o effettuano acquisti (scritture). CQRS consente al sistema di scalare il lato delle query in modo indipendente per gestire l'elevato volume di richieste di lettura senza influire sulle operazioni di scrittura.
Logica di business complessa
Quando si gestiscono regole aziendali complesse che si applicano solo alle modifiche dei dati (comandi), CQRS aiuta isolando questa complessità. Ad esempio, il lato dei comandi può applicare rigorose regole di validazione ed elaborazione in un sistema finanziario in cui le transazioni sono fortemente regolamentate. Al contrario, il lato delle query rimane semplice e focalizzato sul recupero dei saldi dei conti o degli storici delle transazioni.
Event Sourcing e audit trail
Nei sistemi in cui è necessario mantenere un audit trail completo di ogni modifica, CQRS si abbina bene all'event sourcing. Ad esempio, in un'applicazione sanitaria, ogni modifica alla cartella clinica di un paziente può essere memorizzata come evento, consentendo al sistema di tracciare facilmente chi ha apportato modifiche e quando, mentre le query possono accedere rapidamente allo stato attuale della cartella.
Analisi in tempo reale
Per le applicazioni che richiedono analisi in tempo reale, come le piattaforme di social media, CQRS può gestire aggiornamenti costanti ai dati degli utenti (ad esempio, like, condivisioni) mentre elabora query per insight in tempo reale (ad esempio, argomenti di tendenza). Il lato delle query può essere ottimizzato per la velocità senza essere influenzato dagli aggiornamenti continui sul lato dei comandi.
Architetture a microservizi
Nei sistemi basati su microservizi, CQRS fornisce servizi diversi per gestire comandi e query in modo indipendente. Ad esempio, in un'azienda di logistica, un servizio può gestire l'elaborazione degli ordini (comandi), mentre un altro gestisce tracciamento e reportistica (query), migliorando la flessibilità e la manutenibilità del sistema.
Strumenti e framework che supportano CQRS
Diversi strumenti e framework rendono più semplice implementare CQRS. Ecco una breve panoramica di alcune opzioni popolari:
Axon Framework (Java) è un framework completo che supporta CQRS ed event sourcing. Fornisce componenti integrati per gestire comandi, query ed eventi, il che lo rende una scelta popolare per applicazioni Java complesse.
MediatR è un'altra libreria leggera per applicazioni .NET che semplifica la separazione di comandi e query. Aiuta a instradare le richieste in modo pulito e organizzato, ideale per CQRS in sistemi di piccole e medie dimensioni.
Laravel Command Bus fa parte del framework Laravel. Gli sviluppatori usano questo strumento per definire comandi e query separatamente. È un'ottima opzione per applicazioni basate su PHP che vogliono implementare CQRS.
EventStore è un database specializzato progettato per l'event sourcing, spesso abbinato a CQRS. Memorizza eventi anziché solo dati, consentendo una facile riproduzione degli eventi passati per ricostruire lo stato del sistema.
NServiceBus è un framework di messaggistica che funziona bene con CQRS gestendo comandi, eventi e messaggi attraverso sistemi distribuiti. È ideale per architetture a microservizi che usano CQRS.
Vantaggi di CQRS
Scalabilità e prestazioni migliorate
Separando comandi e query, CQRS può scalare ogni parte in modo indipendente. Ad esempio, se la tua applicazione gestisce molte più operazioni di lettura (query) che operazioni di scrittura (comandi), puoi scalare il lato delle query senza influenzare il lato dei comandi, migliorando le prestazioni complessive.
Organizzazione del codice più chiara
CQRS promuove una netta separazione delle responsabilità. I comandi si occupano di apportare modifiche, mentre le query gestiscono il recupero dei dati. Questo rende il codice più facile da comprendere e mantenere, poiché ogni parte del sistema ha una responsabilità chiara.
Migliore gestione delle regole aziendali complesse
Con CQRS, le regole aziendali complesse relative all'aggiornamento dei dati possono essere gestite sul lato dei comandi, mentre query più semplici ed efficienti possono essere usate per leggere i dati. Questa divisione aiuta a gestire una logica intricata senza sovraccaricare il sistema o rendere il codice troppo complicato.
Flessibilità nelle scelte del database per la lettura rispetto alla scrittura dei dati
CQRS ti offre la possibilità di usare database diversi per comandi e query. Per esempio, potresti usare un database NoSQL altamente ottimizzato per letture rapide (query) e un database relazionale durante le scritture (comandi). Questa flessibilità ti consente di scegliere gli strumenti migliori per ogni attività.
Sfide e considerazioni su CQRS
Maggiore complessità
Con CQRS, devi gestire due modelli separati: uno per gestire i comandi (scritture) e un altro per gestire le query (letture). Questo aggiunge complessità alla codebase, poiché devi mantenere e aggiornare entrambi i modelli, aumentando lo sforzo necessario per sviluppare e mantenere il sistema.
Sfide di sincronizzazione
Mantenere sincronizzati il lato dei comandi e quello delle query può essere complicato. Quando i dati vengono scritti tramite un comando, potrebbe essere necessario del tempo prima che le modifiche si riflettano sul lato delle query, causando potenziali ritardi. Gestire questa sincronizzazione è importante per garantire dati accurati in tutto il sistema.
Decidere quando CQRS è eccessivo
CQRS non è necessario per applicazioni CRUD (Create, Read, Update, Delete) semplici. Nei sistemi con requisiti di dati lineari, la complessità aggiuntiva di CQRS potrebbe non valerne la pena. CQRS è più adatto a sistemi complessi con un elevato volume di letture e scritture o con logica di business articolata.
Costo
Implementare CQRS spesso richiede infrastruttura aggiuntiva, come il mantenimento di database separati per comandi e query. Questo può aumentare i costi hardware e dei servizi cloud, specialmente quando si scalano entrambi i lati. La necessità di più tecnologie per gestire queste attività può far crescere le spese.
Come CQRS svolge un ruolo nei database vettoriali e nei Big Data
Nei database vettoriali come Milvus, CQRS offre un modo strutturato per gestire diversi tipi di operazioni:
Comandi: Questi includono attività come l’inserimento o l’aggiornamento di grandi volumi di vettori (ad es., embedding vettoriali generati da modelli di machine learning). In Milvus, i comandi aggiornerebbero lo stato del database.
Query: Queste operazioni recuperano vettori, ad esempio trovando elementi simili in un grande dataset usando la ricerca per similarità. Le query di Milvus possono restituire vettori ad alta dimensionalità che corrispondono a criteri specifici, e sono spesso usate in analisi in tempo reale o applicazioni di IA come sistemi di raccomandazione e retrieval augmented generation (RAG).
Esempio: Gestire query di analisi in tempo reale rispetto all’inserimento/aggiornamento di vettori
Supponiamo che tu stia eseguendo un sistema di raccomandazione basato sull’IA su Zilliz Cloud (la versione gestita di Milvus). Quando vengono generati nuovi dati utente o vettori di prodotto, il sistema emette comandi per aggiornare il database vettoriale con embedding aggiornati. Questi comandi garantiscono che i vettori più recenti vengano inseriti o aggiornati in Milvus.
Allo stesso tempo, le analisi in tempo reale vengono eseguite usando query per recuperare i vettori più simili per le raccomandazioni. Il lato delle query è ottimizzato per trovare rapidamente dati pertinenti senza essere influenzato dai continui inserimenti di vettori sul lato dei comandi.
Conclusione
CQRS offre un modo potente per gestire sistemi complessi separando comandi (modifiche ai dati) e query (recupero dei dati). Questa separazione migliora scalabilità, prestazioni e chiarezza del codice, specialmente in applicazioni su larga scala con logica di business complessa. Sebbene CQRS aggiunga una certa complessità, offre vantaggi significativi quando viene usato negli scenari giusti, come sistemi che gestiscono analisi in tempo reale, carichi elevati di lettura/scrittura o event sourcing. Tuttavia, per applicazioni più semplici, la complessità aggiuntiva potrebbe non essere necessaria. In conclusione, CQRS è uno strumento prezioso per migliorare l’efficienza e la flessibilità del sistema quando applicato in modo appropriato.
FAQ di CQRS
- Qual è il principale vantaggio dell’utilizzo di CQRS?
CQRS separa le responsabilità di aggiornamento dei dati (comandi) e di recupero dei dati (query), migliorando la scalabilità, le prestazioni e la chiarezza del codice del sistema. Ogni lato può essere ottimizzato in modo indipendente, il che lo rende utile per sistemi ad alto volume o complessi.
- Quando dovrei evitare di usare CQRS?
CQRS può aggiungere complessità non necessaria per semplici applicazioni CRUD in cui non è necessario gestire in modo distinto letture e scritture. Se la tua applicazione non ha requisiti di prestazioni significativi o logica di business complessa, CQRS potrebbe essere eccessivo.
- Devo usare database separati per comandi e query in CQRS?
No, l’uso di database separati per comandi e query non è obbligatorio. Sebbene sia possibile usare database diversi per CQRS, l’aspetto fondamentale è separare il comportamento e la responsabilità nel codice. Puoi comunque usare un singolo database se soddisfa le esigenze della tua applicazione.
- Come funziona CQRS con l’event sourcing?
Nell’event sourcing, ogni modifica al sistema viene memorizzata come evento. CQRS completa questo approccio gestendo i comandi che generano eventi e usando le query per ricostruire lo stato del sistema riproducendo tali eventi. In questo modo viene mantenuta una cronologia completa delle modifiche, rendendo più facile l’audit o il debug.
- CQRS può migliorare le prestazioni delle applicazioni di analisi in tempo reale?
Sì, CQRS è utile per l’analisi in tempo reale. Consente al sistema di gestire gli aggiornamenti continui (comandi) separatamente dalle query sui dati in tempo reale, ottimizzando ciascuno per il proprio scopo ed evitando che uno rallenti l’altro.
- Quali sono le sfide dell’implementazione di CQRS?
Le principali sfide includono una maggiore complessità, la gestione della sincronizzazione tra i modelli di comando e di query, la gestione dei problemi di coerenza eventuale e costi infrastrutturali potenzialmente più elevati dovuti al mantenimento di percorsi o database separati.
Risorse correlate
- Che cos'è la Command Query Responsibility Segregation (CQRS)?
- Concetti chiave di CQRS
- Come funziona CQRS?
- CQRS ed Event Sourcing
- Differenza tra CQRS e CQS
- Casi d'uso per CQRS
- Strumenti e framework che supportano CQRS
- Vantaggi di CQRS
- Sfide e considerazioni su CQRS
- Come CQRS svolge un ruolo nei database vettoriali e nei Big Data
- Conclusione
- FAQ di CQRS
- Risorse correlate
Contenuto
Inizia gratis, scala facilmente
Prova il database vettoriale completamente gestito progettato per le tue applicazioni GenAI.
Prova Zilliz Cloud gratuitamente

