Di recente, ho tenuto una lezione ai miei colleghi sull’approvvigionamento di eventi e mi sono reso conto che queste informazioni introduttive potrebbero essere preziose per un pubblico più ampio.
Questo articolo è utile per coloro che sono interessati al concetto di approvvigionamento di eventi e che vogliono decidere se è adatto ai loro progetti evitando al contempo insidie comuni. Quindi, immergiamoci.
Sourcing per eventi è un approccio in cui, invece di conservare lo stato attuale del sistema, tutte le modifiche vengono salvate come eventi, che diventano la principale fonte di dati. L’approccio ha acquisito popolarità intorno al 2005 dopo l’argomento di Martin Fowler sull’argomento.
L’concept principale è che invece di archiviare e aggiornare lo stato dell’applicazione, salvi gli eventi che descrivono le modifiche. Gli eventi fungono da fonte di informazione principale. Ciò differisce dall’approccio tradizionale, in cui lo stato attuale viene salvato e aggiornato advert ogni cambiamento. Nell’approvvigionamento di eventi, ogni modifica viene registrata come un nuovo evento invece di modificare un file esistente.
Advert esempio, in un’app in cui gli utenti possono modificare i propri profili, l’approccio tradizionale utilizza un comando “aggiornamento” per modificare il file di database esistente. Con l’approvvigionamento di eventi, invece di “aggiornamento”, usiamo “insert”, aggiungendo una nuova voce a un registro eventi che registra la modifica.
Gli eventi includono un identificatore utente (StreamID), il nome dell’evento, la versione e nuovi dati, come un nuovo nome utente. Questo crea un registro “solo appendici”, un file immutabile in cui ogni modifica è un evento separato.
Questo metodo preserva l’intera cronologia delle modifiche, semplificando l’auditing, il recupero e l’analisi dei dati.
Occasion Sourcing Professional e contro
Di seguito sono riportati alcuni vantaggi per l’approvvigionamento di eventi:
- Osservabilità. È possibile tracciare tutte le modifiche, creare un registro di audit e ripristinare gli stati di dati in qualsiasi momento.
- Decomposizione del sistema. Supporta interazioni asincroni tra componenti del sistema e microservizi.
- Miglioramento della tolleranza ai guasti. Riduce il rischio di perdita di dati, soprattutto quando esistono repliche di archivio di eventi.
- Migrazione dei dati facile. I dati possono essere facilmente trasferiti tra i database riproducendo eventi.
Sfide
- Implementazione e manutenzione complesse. L’approvvigionamento di eventi non è sempre la soluzione migliore.
- Potenziale sovratensione. Non è adatto a ogni progetto.
Prima di implementare l’approvvigionamento di eventi, è essenziale rispondere a queste domande:
1. Gli eventi possono essere considerati Parte del dominio della mia app?
Determina se si prevede di utilizzare eventi per attività asincroni, come inviare e -mail o per abbattere il sistema in microservizi che interagiscono attraverso eventi.
2. Gli eventi possono aiutarmi a sviluppare e mantenere la mia app?
Considera se l’archiviazione di eventi supporterà le tue esigenze di sviluppo e manutenzione.
3. Devo sapere su ogni cambiamento nella mia app?
Valuta se è necessario tenere traccia di ogni modifica o se ci sono limiti di archiviazione per il monitoraggio di tutte le operazioni.
Con queste domande in mente, puoi decidere se l’approvvigionamento di eventi è adatto alla tua applicazione.
Advert esempio, nelle app finanziarie in cui i bilanciamenti del conto cambiano spesso, gli eventi possono riflettere in modo efficiente questi aggiustamenti. Ogni saldo cambia collegamenti a eventi come depositi o prelievi. Questo approccio consente di ricreare lo stato dell’account in qualsiasi momento applicando la sequenza di eventi, ciascuno con un tipo e una logica specifici.
Ecco alcuni esempi dell’approccio in diversi settori:
Fintech
- Esempio di stato: Saldo del conto
- Eventi: Deposito, prelievo, inizio del mese finanziario, creazione del conto
- Proiezioni: Registri delle transazioni, cronologia dell’account
Catena di fornitura
- Esempio di stato: Stato di spedizione
- Eventi: Consegna richiesta, accettata dal corriere, aggiornamenti di stato
- Proiezioni: Richieste di consegna, consegne in attesa del vettore
Assistenza sanitaria
- Esempio di stato: Cartella clinica del paziente
- Eventi: Visite mediche, esami medici
- Proiezioni: Storia medica
Occasion Sourcing Constructing Blocks
Per creare un sistema di sourcing da evento, concentrati su questi componenti chiave:
1. Occasion Retailer
Una soluzione di archiviazione per tutti gli eventi nel sistema, raggruppata in flussi con ID univoci e versioni ordinate. Advert esempio, EventStordB è una scelta popolare. Il negozio di eventi organizza eventi in flussi, ognuno con un ID e un elenco cronologico di eventi per una particolare entità.
2. Aggregati
UN Concetto di design guidato dal dominio (DDD) Ciò raggruppa più oggetti in un insieme, ognuno con un ID univoco. Per un’app finanziaria, un aggregato potrebbe essere un resoconto che unisce saldi e carte, mentre le transazioni potrebbero costituire un aggregato separato. La radice di un aggregato è il punto di accesso per la gestione delle modifiche.
3. Eventi
Ogni evento ha un ID, una versione e un tipo univoci ed è immutabile. Advert esempio, un evento di transazione può essere rappresentato in JSON con campi come versione, nome (advert esempio “deposito”), importo, valuta e altri dettagli.
4. Stream di eventi
Una sequenza ordinata di eventi, ognuno con una versione nel flusso. Esistono diversi modi per organizzare i flussi:
- Flusso singolo per aggregato. Ogni flusso è legato a un aggregato specifico, come un flusso di “saldo” per l’ID account 1 con eventi solo per quel saldo.
- Flussi multipli per un aggregato. È possibile creare flussi separati per periodi o categorie various, come flussi di saldo mensili.
- Flusso di eventi globali. Contiene tutti gli eventi per tutti gli aggregati, ordinati dal tempo.
5. Proiezioni
Chiamati anche modelli di lettura, modelli di question o modelli di visualizzazione, le proiezioni organizzano eventi in formati intuitivi, come storie di transazioni o dichiarazioni di account. Possono aggregare o raggruppare eventi per semplificare l’accesso ai dati.
6. Snapshot
Risparmio di stato opzionale per aggregati, utilizzati per ottimizzare il restauro dello stato. Le istantanee non sono necessarie ma possono migliorare le prestazioni durante la riproduzione di storie di eventi.
Costruire stati aggregati
Per costruire uno stato aggregato dagli eventi in un flusso, seguire questi passaggi:
1. Replaying dello stato da eventi
Per ricreare lo stato dell’account, definire una classe come “AccountBoundState” con campi come “importo”, “valuta” e altre proprietà. La classe embrace un metodo “Applica” che prende un evento e regola lo stato in base al tipo di evento:
- Per un evento di deposito, il metodo “Applica” aumenta “Importo” per l’importo del deposito.
- Per un evento di prelievo, il metodo “Applica” diminuisce “importo” dell’importo corrispondente.
Questo approccio ti consente di ripristinare lo stato dell’account in una knowledge versione applicando in sequenza ogni evento fino alla versione desiderata.
2. Utilizzo delle proiezioni
Le proiezioni semplificano l’accesso ai dati creando modelli di sola lettura per question efficienti. Le proiezioni possono essere adattate per singoli eventi o mixture per gruppi di eventi. Esempi includono:
- Proiezione delle transazioni. Memorizza un elenco di tutte le transazioni dell’account.
- Bilanciare la proiezione. Riflette il saldo del conto corrente.
Ottimizzazione con istantanee
Quando il numero di eventi diventa molto grande (milioni o più), la riproduzione di tutti gli eventi diventa inefficiente. Le istantanee aiutano salvando lo stato dell’aggregato in versioni specifiche, in modo da poter iniziare dall’ultima snapshot piuttosto che dall’inizio.
var snapshot = snapshots.LastOrDefault();
state.LoadFromSnapshot(snapshot);
foreach (var domainEvent in orderedDomainEvents.The place(x => x.Model > snapshot.Model))
{
state.Apply(domainEvent);
}
- Le istantanee possono essere archiviate in un flusso separato, come
balance-1-snapshot
. - Per ripristinare lo stato a una determinata versione, recupera l’ultima istantanea e applica tutti gli eventi con versioni superiori alla versione dell’istantanea.
Strategia di creazione di istantanee
Decidi quanto spesso creare istantanee in base all’utilizzo del sistema:
- Ogni evento N (advert esempio, ogni 100 eventi),
- A intervalli di tempo specifici (advert esempio, all’inizio di ogni nuovo mese),
- Una combinazione di entrambi gli approcci.
Le principali sfide nell’approvvigionamento di eventi e le loro soluzioni
1. Aggiornamenti di concorrenza
Nei sistemi distribuiti con più microservizi e accesso parallelo ai dati, si presentano aggiornamenti di concorrenza e problemi di transazione distribuiti. Gli approcci principali per la gestione degli aggiornamenti di concorrenza includono:
Controllo della concorrenza pessimista
Questo approccio blocca la risorsa (advert esempio, un file di database) durante un’operazione, quindi altri processi devono attendere fino al rilascio del blocco. Può essere implementato utilizzando blocchi distribuiti, advert esempio con Redis o PostgreSQL.
Controllo ottimista di concorrenza
Invece di bloccare la risorsa, questo approccio si basa sul controllo della versione. Lo stato dell’oggetto contiene una versione e durante un aggiornamento verifica che la versione nel database corrisponda alla versione prevista. In caso contrario, le operazioni operative: lo stato viene nuovamente letta, convalidata e aggiornata.
Nell’approvvigionamento di eventi, piuttosto che uno stato mutabile, c’è un flusso di eventi (registro solo append). Ciò evita i problemi di aggiornamento della concorrenza poiché i nuovi eventi vengono aggiunti solo alla fantastic dei registri. Se ogni nuovo evento deve dipendere da quello precedente, viene utilizzato il controllo della versione ottimistica, supportato naturalmente da molte implementazioni di sourcing da eventi. Se la dipendenza tra gli eventi non è importante (advert esempio, aggiungendo articoli a un ordine in un negozio on-line), gli eventi possono essere aggiunti senza il controllo della versione.
2. Transazioni distribuite
Nei sistemi distribuiti, è fondamentale garantire che i cambiamenti tra vari negozi di dati o servizi siano coerenti. Le soluzioni includono:
Commit in 2 fasi
Adatto alle transazioni su più sistemi, sebbene non supportati da tutti i negozi di dati. Questo processo prevede due fasi: la preparazione (tutti i partecipanti confermano la prontezza) e il commit, a condizione che tutti siano pronti.
Sample Outbox
L’concept qui è di Scrivi eventi su una “Outbox” (una tabella di messaggi speciali) in parallelo con la scrittura del database. Quindi, un servizio dedicato invia asincrono questi messaggi a una coda, garantendo una consegna affidabile.
Modello di saga transazionale
Gestisce transazioni distribuite attraverso l’orchestrazione (sequenza centralizzata di passaggi) e la coreografia (ogni passaggio determine il successivo in base allo stato di transazione corrente).
3. Sincronizzazione della proiezione
Quando un sistema utilizza le proiezioni per le letture dei dati, è essenziale garantire la loro coerenza e la loro sincronizzazione con il principale negozio di eventi. Questo può essere ottenuto con:
Aggiornamenti asincroni
Le proiezioni vengono aggiornate in modo asincrono man mano che vengono aggiunti nuovi eventi. È possibile utilizzare una coda di messaggi in modo che ogni proiezione riceva aggiornamenti automaticamente.
Eventuale coerenza
Il sistema consente un piccolo ritardo tra la registrazione degli eventi e gli aggiornamenti di proiezione. Garantire che tutti gli eventi richiesti vengano elaborati è la chiave.
Questi approcci consentono flessibilità nel soddisfare requisiti di sistema specifici, mantenimento della coerenza e alte prestazioni in ambienti distribuiti.
4. Ottimizzazione del processo di lettura e calcolo dello stato
L’approvvigionamento di eventi prevede la riproduzione dello stato da tutti gli eventi, che può essere advert alta intensità di risorse per flussi di grandi dimensioni. Le tecniche di ottimizzazione chiave includono:
Istantanea
Creazione di istantanee salvate dello stato di un oggetto in versioni specifiche. Advert esempio, un’istantanea dello stato di un account può essere creata ogni 100 eventi. In questo modo, durante la riproduzione, il sistema inizia dall’ultima istantanea e applica solo nuovi eventi, riducendo il numero di operazioni richieste per ripristinare lo stato corrente.
Proiezioni
Rappresentare eventi in un formato conveniente per question, come una cronologia delle transazioni o un saldo del conto corrente. Le proiezioni possono essere aggiornate in tempo reale o periodicamente, a seconda del caso d’uso specifico.
CQRS (segregazione di responsabilità della question di comando)
Questo approccio Separa le operazioni di scrittura (creazione di eventi) dalle operazioni di lettura (question) in diversi modelli di dati. La scrittura viene eseguita tramite l’approvvigionamento di eventi, mentre la lettura viene eseguita attraverso proiezioni pre-costruite, che ottimizza le prestazioni del sistema.
Conclusione
Pertanto, mentre l’approvvigionamento di eventi presenta sfide come la gestione delle transazioni distribuite e il controllo della concorrenza, queste possono essere gestite efficacemente attraverso modelli e migliori pratiche stabilite. Implementando pensierosi questo concetto, i crew possono creare applicazioni più resistenti, mantenibili e scalabili, rendendolo una risorsa preziosa nello sviluppo moderno del software program.