Sei sulla pagina 1di 10
Modello CQRS CQRS @ 'acronimo di Command and Query Responsibility Segregation, un modello che separa le operazioni di lettura e aggiornamento per un archivio dati. L'implementazione del modello CQRS nell'applicazione pud massimizzare prestazioni, scalabilita e sicurezza La flessibilita creata dalla migrazione al modello CQRS consente a un sistema di evolversi meglio nel tempo e impedisce ai comandi di aggiornamento di causare conflitti di merge a livello di dominio. Contesto e problema Nelle architetture tradizionali viene usato lo stesso modello di dati per eseguire query su un database e per aggiornarlo, Questo é un comportamento semplice che funziona bene per operazioni CRUD di base. In applicazioni pit: complesse, tuttavia, questo approccio pus risultare poco pratico. Ad esempio, sul lato lettura l'applicazione pud eseguire molte query diverse, restituendo oggetti DTO (Data Transfer Object) in diverse forme. In questi casi, il mapping degli oggetti pud diventare difficoltoso. Sul lato scrittura il modello pud implementare convalida e logica di business complesse. Di conseguenza, pud risultare un modello eccessivamente complesso che esegue troppe attivita, I carichi di lavoro di lettura e scrittura sono spesso asimmetrici, con requisiti di prestazioni e scalabilita molto diversi. * Spesso si verifica una mancata corrispondenza tra le rappresentazioni di lettura e scrittura dei dati, ad esempio colonne o proprieta aggiuntive che devono essere aggiornate correttamente anche se non sono necessarie come parte di un'operazione. * La contesa dei dati pud verificarsi quando le operazioni vengono eseguite in parallelo sullo stesso set di dati * L’approccio tradizionale pud avere un effetto negativo sulle prestazioni a causa del carico sull'archivio dati e sul livello di accesso ai dati e la complessita delle query necessarie per recuperare le informazioni * Lagestione della sicurezza e delle autorizzazioni pud diventare complessa, perché ogni entita é soggetta a operazioni di lettura e scrittura, che potrebbero esporre i dati nel contesto errato. Soluzione QRS separa le letture e le scritture in modelli diversi, usando i comandi per aggiornare i dati e le query per leggere i dati. * | comandi devono essere basati su attivita, anziché incentrati sui dati. ("Prenota camera hotel”, non "imposta ReservationStatus su Riservato"). * I comandi possono essere inseriti in una coda per l'elaborazione asincrona, anziché essere elaborati in modo sincrono. * Le query non modificano mai il database. Una query restituisce un oggetto DTO che non incapsula informazioni sul dominio. | modelli possono quindi essere isolati, come illustrato nel diagramma seguente, anche se non é un requisito assoluto. Read model e Cl Cred Pier) Write model Data store La presenza di modelli di query e aggiornamento separati semplifica la progettazione e implementazione. Tuttavia, uno svantaggio é che il codice CQRS non pus essere generato automaticamente da uno schema di database usando meccanismi di scaffolding come gli strumenti O/RM. Per un isolamento maggiore, é possibile separare fisicamente i dati di lettura da quelli di scrittura. In questo caso, il database di lettura pud usare il proprio schema dei dati ottimizzato per le query. Ad esempio, pud archiviare una vista materializzata dei dati per evitare join complessi o mapping relazionali di oggetti. Pud addirittura usare un tipo di archivio dati diverso. Ad esempio, il database di scrittura pud essere relazionale, mentre quello di lettura pud essere un database di document Se vengono usati database di lettura e scrittura separati, devono essere mantenuti sincronizzati. Questa operazione viene in genere eseguita mediante la pubblicazione di un evento da parte de! modello di scrittura ogni volta che aggiorna il database. Per altre informazioni sull'uso degli eventi, vedere Stile dell'architettura basata su eventi. Poiché i broker di messaggi e i database in genere non possono essere inseriti in una singola transazione distribuita, possono verificarsi problemi di coerenza durante 'aggiornamento del database e degli eventi di pubblicazione. Per altre informazioni, vedere le indicazioni sull'elaborazione dei messaggi idempotent. Clears eens) DTOs) Larchivio di lettura pud essere una replica di sola lettura di quello di scrittura oppure gli archivi di lettura e scrittura possono avere una struttura completamente diversa. L'uso di pid repliche di sola lettura pud migliorare le prestazioni delle query, in particolare negli scenari distribuiti in cui le repliche di sola lettura si trovano vicino alle istanze dell'applicazione. La separazione degli archivi di lettura e scrittura consente anche di dimensionare ogni archivio a seconda del carico. Il carico degli archivi di lettura, ad esempio, é in genere molto pitielevato rispetto a quello degli archivi di scrittura. Alcune implementazioni di CQRS usano il modello di determinazione dell'origine degli eventi. Con questo modello lo stato dell'applicazione viene archiviato come sequenza di eventi. Ogni evento rappresenta un set di modifiche apportate ai dati. Lo stato corrente viene costruito riproducendo gli eventi. In un contesto CQRS, un vantaggio dell’origine event é che gli stessi eventi possono essere usati per notificare ad altri component, in particolare per notificare al modello di lettura. Il modello di lettura usa gli eventi per creare uno snapshot dello stato corrente, pid efficiente per le query. Tuttavia, la determinazione dell‘origine degli eventi aggiunge complessita alla progettazione. | vantaggi di CQRS includono: * Scalabilita indipendente. CQRS consente il ridimensionamento indipendente dei carichi di lavoro di lettura e scrittura e pud ridurre i conflitti di blocco. ‘* Schemi di dati ottimizzati. II lato lettura pud usare uno schema ottimizzato per le query, mentre il lato scrittura usera uno schema ottimizzato per gli aggiornamenti. * Sicurezza. E pili facile fare in modo che solo le entita di dominio corrette eseguano scritture sui dati. * Separazione delle preoccupazioni. 'isolamento del lato lettura dal lato scrittura e viceversa pud comportare modelli pit gestibili e flessibili. La maggior parte della logica di business € correlata al modello di scrittura. II modello di lettura pud essere relativamente semplice. * Query pid semplici. Grazie all'archiviazione di una vista materializzata nel database di lettura, 'applicazione pud evitare join complessi durante l'esecuzione di query. Problemi di implementazione e considerazioni Alcune sfide dell'implementazione di questo modello includono: ‘© Complessita. L'idea alla base di CQRS @ semplice. Tuttavia, pud aggiungere complessita alla progettazione di applicazioni, in particolare quando si usa il modello di determinazione dell’origine degli event ‘* Messaggistica. Benché CQRS non richieda la messaggistica, questa viene comunemente usata per elaborare i comandi e pubblicare gli eventi di aggiornamento. In questo caso, l'applicazione deve gestire gli errori dei messaggi 0 i messaggi duplicati. Vedere le indicazioni sulle code di priorita per gestire i comandi con priorita diverse ‘* Coerenza finale. Separando i database di lettura e scrittura, i dati di lettura possono non essere aggiornati. L'archivio modelli di lettura deve essere aggiornato per riflettere le modifiche apportate all'archivio modelli di scrittura e pud essere difficile rilevare quando un utente ha inviato una richiesta in base ai dati di lettura non aggiornati, Quando usare il modello CQRS Prendere in considerazione CQRS per gli scenari seguenti: © Domini collaborativi in cui molti utenti accedono agli stessi dati in parallelo. CQRS consente di definire comandi con una granularita suffi imo i conflitti di merge a livello di dominio e i conflitti che si verificano possono essere nte per ridurre al uniti dal comando. * Interfacce utente basate su attivita in cui gli utenti vengono guidati in un proceso complesso, ad esempio con una serie di passaggi o con modelli di dominio complessi. !! modello di scrittura ha uno stack di elaborazione dei comandi completo con logica di business, convalida dellinput e convalida aziendale. II modello di scrittura pud considerare un set di oggetti associati come una singola unita per le modifiche ai dati (un'aggregazione, nella terminologia DDD) e assicurarsi che questi oggetti siano sempre in uno stato coerente. || modello di lettura non ha una logica di business 0 uno stack di convalida e restituisce solo un DTO da usare in un modello di visualizzazione. Il modello di lettura é coerente con il modello di scrittura. Gli scenari in cui le prestazioni delle letture dei dati devono essere ottimizzate separatamente dalle prestazioni delle scritture dei dati, soprattutto quando il numero di letture @ molto maggiore de! numero di scritture. In questo scenario & possibile aumentare il numero di istanze del modello di lettura, ma eseguire il modello di scrittura in poche istanze. Un numero ridotto di istanze di un modello di scrittura consente anche di ridurre 'occorrenza di conflitti di unione. ‘© Scenari in cui un team di sviluppatori possa concentrarsi su un modello di dominio complesso che fa parte del modello di scrittura e in cui un altro team possa concentrarsi sul modello di lettura e sulle interfacce utente ‘© Scenari in cui si prevede che il sistema si evolva nel tempo e che possa contenere pili versioni del modello oppure in cui le regole di business cambiano regolarmente. '* Integrazione con altri sistemi, soprattutto in combinazione con un‘origine eventi, in cui l'errore temporaneo di un sottosistema non deve influire sulla disponibilita degli altri. Questo modello non é consigliato quando: * Il dominio o le regole business sono semplici ‘© Un'interfaccia utente di tipo CRUD semplice e le operazioni di accesso ai dati sono sufficienti. E possibile applicare il modello CQRS a sezioni limitate del sistema in cui é pill rilevante. Modello di origine eventi e CQRS II modello CQRS viene spesso usato con il modello di origine evento. | sistemi basat CQRS usano modelli dati di lettura e scrittura separati, ognuno personalizzato in base ad u attivita rilevanti e spesso situato in archivi separati fisicamente. Se usato con il modello di origine eventi, archivio di eventi @ il modello di scrittura ed @ la fonte ufficiale di Informazioni. II modello di lettura di un sistema basato su CQRS offre viste in genere come viste fortemente denormalizzate. Tali viste sono specifiche per le interfacce e i requisiti di visualizzazione dell'applicazione, in modo da ottimizzare sia le prestazioni delle query che quelle di visualizzazione. L'uso del flusso di eventi come archivio di scrittura, anziché dei dati effettivi in un punto nel tempo, consente di evitare conflitti di aggiornamento su una singola funzione di aggregazione e di ottimizzare prestazioni e scalabilita. Gli eventi possono essere usati per generare in modo asincrono le viste mat larchivio di lettura. izzate dei dati usati per popolare Poiché l'archivio di eventi é 'origine ufficiale delle informazioni, & possibile eliminare le viste materializzate e riprodurre tutti gli eventi precedenti per creare una nuova rappresentazione dello stato corrente quando il sistema si evolve 0 quando il modello di lettura deve cambiare. Le viste materializzate sono in effetti una cache di sola lettura permanente dei dati. Quando si usa il modello CRS in combinazione con i! modelo di origine evento, & necessario considerare quanto segue In modo analogo a qualsiasi sistema in cui gli archivi di lettura e scrittura sono separati, i sistemi basati su questo modelo sono caratterizzati solo da coerenza finale. Si verifica pertanto un ritardo tra 'evento generato e l'archivio dati aggiornato. * Il modello aggiunge complessita perché é necessario creare codice per awiare e gestire gli eventi e assemblare o aggiomare le viste o gli oggetti appropriati richiesti dalle query o da un modello di lettura. La complessita del modello CQRS quando si usa il modello di origine evento rende pit difficile una corretta implementazione e richiede un approccio diverso alla progettazione di sistem. II modelo di origine evento, tuttavia, pud semplificare la modellazione del dominio e la rigenerazione di viste o la creazione di nuove perché lo scopo delle modifiche dei dati viene mantenuto. * Lagenerazione di viste materializzare per 'uso nel modello di lettura o nelle pri specifiche o raccolte di entita pud richiedere tempo di elaborazione e uso di iezioni dei dati per la riproduzione e la gestione degli eventi per entita risorse significativi. Questo aspetto é particolarmente vero se @ richiesta la somma 6 lanalisi dei valori per lunghi periodi, poiché potrebbe essere necessario esaminare tutti gli eventi associati. Risolvere questo problema implementando snapshot dei dati a intervalli pianificati, ad esempio un conteggio totale del numero totale di un'azione specifica che si é verificata o lo stato corrente di unventita Esempio di modello CQRS II codice seguente mostra alcuni estratti da un esempio di un‘implementazione del modello CQRS che usa definizioni diverse per modelli di lettura e di scrittura. Le interface di modello non impongono alcuna funzionalita degli archivi dati sottostanti e possono evolversi ed essere ottimizzate in modo indipendente, perché queste interfacce sono separate. Il codice seguente illustra la definizione di modello di lettura. ce // Query interface namespace ReadModel = public interface ProductsDao { ProductDisplay FindById(int productId); ICollection FindByName(string name); ICollection FindQutOfStockProducts(); ICollection FindRelatedProducts(int productId) ; + public class ProductDisplay { public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } public decimal UnitPrice { get; set; } public bool IsOutOfStock { get; set; } public double UserRating { get; set; } + public class ProductInventory 7 public int Id { get; set; } public string Name { get; set; } public int CurrentStock { get; set; } a } II sistema consente agli utenti di valutare i prodotti. II codice dell'applicazione pud usare il comando RateProduct lustrato nel codice seguente. co public interface ICommand { Guid Id { get; } + public class RateProduct : ICommand af public RateProduct() { this.Id = Guid.NewGuid() ; + public Guid Id { get; set; } public int ProductId { get; set; } public int Rating { get; set; } public int UserId {get; set; } II sistema usa la classe ProductsCommandHandler per gestire i comandi inviati dall'applicazione, | client inviano in genere comandi al dominio usando un sistema di messaggistica, ad esempio una coda. II gestore de! comando accetta tali comandi e richiama i metodi dell'interfaccia di dominio. La granularita di ogni comando & progettata per ridurre il rischio di richieste in conflitto. II codice seguente illustra la classe ProductsCommandHandler . ce public class ProductsCommandHandler : ICommandHandler, CommandHandler, CommandHandler, ICommandHandler, ICommandHandler private readonly IRepository repository; public ProductsCommandHandler (IRepository repository) { this. repository = repository; + void Handle (AddNewProduct command) { + void Handle (RateProduct command) { var product = repository. Find(command.ProductId) ; if (product != null) { product .RateProduct(command.UserId, command. Rating) ; repository. Save(product) ; + + void Handle (AddToInventory command) Passaggi successivi Quando si implementa questo modello, possono essere utili i modelli ¢ le linee guida seguenti ‘© Informazioni di base sulla coerenza dei dati. Descrive i problemi che si verificano in genere a causa della coerenza finale tra gli archivi dati di lettura e scrittura quando si usa il modello CQRS e il modo in cui possono essere risolti * Partizionamento dei dati orizzontali, verticali e funzionali. Descrive le procedure consigliate per suddividere i dati in partizioni che possono essere gestite e accessibili separatamente per migliorare la scalabilita, ridurre la contesa e ottimizzare le prestazioni. * Le procedure dei modelli & guidano il percorso CRS. In particolare, introduzione al modello di separazione responsabilita query comando esplora il modello e quando é utile e Epilogue: Le lezioni apprese consentono di comprendere alcuni dei problemi che si verificano quando si usa questo modelo, Post di blog di Martin Fowler: * Cosa significa "Guidata dagli eventi"? Risorse correlate delle eventi. Desc Jettaglio il modo in cui l'origine e 1 il modello CQF semplificare le attivita in domini cor anche come off dello di visua 0. I modello di lettura di un‘implementazione ¢ ntenere materializzate dei dati del modello di scrittura oppure pud essere usato per generare viste materializzate

Potrebbero piacerti anche