2012-05-14 11 views
13

Il sourcing di eventi viene lanciato come bonus per un numero di cose, ad es. cronologia degli eventi/audit trail, rigenerazione completa e coerente delle visualizzazioni, ecc. Sembra fantastico. Sono un fan. Ma questi sono dettagli di implementazione sul lato di lettura, e si potrebbe ottenere lo stesso spostando completamente l'archivio eventi sul lato di lettura come un altro sottoscrittore .. quindi perché no?Perché l'archivio eventi dovrebbe essere sul lato scrittura?

Ecco alcuni pensieri:

  1. I punti di vista/denormalizers stessi non si preoccupano di un negozio di evento. Gestiscono solo eventi dal dominio.
  2. Spostare l'archivio eventi sul lato lettura fornisce ancora cronologia eventi/controllo
  3. È ancora possibile rigenerare le visualizzazioni dall'archivio eventi. Tranne ora non deve essere una perdita di modello di scrittura. Dategli leggere la cittadinanza del modello!

Qui sembra essere un argomento tecnico per tenerlo sul lato della scrittura. Questo da Greg Young a http://codebetter.com/gregyoung/2010/02/20/why-use-event-sourcing/:

Ci sono tuttavia alcuni problemi che esistono con l'utilizzo di qualcosa che sta memorizzando un'istantanea dello stato corrente. Il problema più grande ruota attorno al fatto che hai introdotto due modelli per i tuoi dati. Hai un modello di eventi e un modello che rappresenta lo stato corrente.

La cosa che trovo interessante in questo è il termine "istantanea", che più recentemente è diventato un termine distinto anche in caso di sourcing di eventi. L'introduzione di un archivio eventi sul lato scrittura aggiunge un sovraccarico al caricamento degli aggregati. Puoi discutere su quanta overhead, ma è apparentemente un problema percepito o previsto, poiché ora c'è il concetto di caricamento di aggregati da un'istantanea e tutti gli eventi dallo snapshot. Quindi ora abbiamo ancora ... due modelli. E non solo, ma i suggerimenti per l'istantanea che ho visto sono pensati per essere implementati come una perdita di infrastruttura, con un processo in background che si estende all'intero archivio dati per mantenere le prestazioni.

E dopo aver scattato un'istantanea, gli eventi prima dello snapshot diventano inutilizzabili al 100% dalla prospettiva di scrittura, ad eccezione di ... per ricostruire il lato di lettura! Sembra sbagliato.

Un altro argomento correlato alle prestazioni: archiviazione di file. A volte abbiamo bisogno di allegare file binari di grandi dimensioni alle entità. Concettualmente, a volte questi sono associati alle entità, ma a volte sono le entità. Inserirli nell'archivio eventi significa che devi caricare fisicamente quei dati ogni volta che carichi l'entità. È già abbastanza brutto, ma immagina diverse o centinaia di queste in un grande aggregato. Ogni risposta che ho visto a questo è fondamentalmente mordere il proiettile e passare un uri al file. Questo è un limite e mina il sistema distribuito.

Poi c'è manutenzione. La ricostruzione delle viste richiede un processo che coinvolge l'archivio eventi. Così ora ogni attività di manutenzione di una vista che tu abbia mai scritto lega ulteriormente il tuo modello di scrittura all'uso dell'archivio degli eventi .. per sempre.

Non è l'intero punto della CQRS che i casi d'uso attorno al modello di lettura e al modello di scrittura sono fondamentalmente incompatibili? Quindi, perché dovremmo mettere il materiale in lettura sul lato della scrittura, sacrificando flessibilità e prestazioni, e accoppiandoli nuovamente. Perché passare il tempo?

Quindi, tutto sommato, sono confuso. Sotto tutti gli aspetti, da dove mi siedo, il negozio di eventi ha più senso come un dettaglio del modello letto. Continuerai a ottenere i numerosi vantaggi di mantenere un negozio di eventi, ma non eccessivamente la persistenza del lato di scrittura, possibilmente riducendo flessibilità e prestazioni.E non si accoppiano il backup di lettura/scrittura con le astrazioni che perdono e le attività di manutenzione.

Quindi qualcuno potrebbe spiegarmi uno o più motivi validi per tenerlo sul lato della scrittura? O in alternativa, perché non dovrebbe andare sul lato di lettura come un problema di manutenzione/segnalazione? Ancora una volta, non sto mettendo in dubbio l'utilità del negozio. Proprio dove dovrebbe andare :)

+2

anche l'istantanea con gli eventi non è un "nuovo concetto" questo è stato nel mio primo discorso sull'origine degli eventi nel 2006 :) –

risposta

4

Penso che questa sia davvero una domanda eccellente. Trattare il tuo aggregato come una sequenza di eventi è utile a sé stante sul lato di scrittura, rendendo più facile il tentativo di comando e simili. Ma sono d'accordo sul fatto che sembra sconvolgente lavorare per creare i tuoi eventi, quindi dobbiamo fare ancora un altro modello dell'oggetto per la persistenza, se hai bisogno di questo miglioramento delle prestazioni di scatto.

Un sistema in cui gli aggregati memorizzavano solo istantanee, ma inviava gli eventi al modello di lettura per la proiezione in modelli di lettura, si direbbe che si chiami "CQRS", ma non "Event Sourcing". Se hai tenuto gli eventi in giro per la riproposizione, suppongo che tu avresti un sistema che è stato molto entrambi.

Ma allora non avresti tre definizioni? Uno per la persistenza dei tuoi aggregati, uno per comunicare le modifiche di stato e qualsiasi altro numero per rispondere alle domande?

In tale sistema si sarebbe tentati di iniziare a rispondere alle domande caricando i propri aggregati e ponendo loro le domande direttamente. Anche se questo non è vietato in alcun modo, tende a iniziare a causare quegli aggregati a funzionalità di cui non potrebbero altrimenti avere bisogno, per non parlare di complicare il threading e le transazioni.

+0

Grazie per questo. Non ha aumentato il numero di definizioni. Ricorda che con l'event sourcing + snapshotting hai davvero 2 integrati in 1. Quindi hai EventStore + Snapshot per gli aggregati, Eventi per i modelli di lettura e EventStore per la lettura di regen. L'altro modo ha Snapshot per gli aggregati, Eventi per i modelli di lettura e EventStore per la lettura di regen. È lo stesso, solo con la divisione EventStore + Snapshot. –

+0

Potresti espandere il commento "Rendere il comando più facile e più semplice"? cioè, cosa è più facile per questo quando il lato scrittura persiste contro gli eventi? –

+0

Inoltre, per l'ultimo punto, supponiamo che non sia ancora possibile interrogare gli aggregati in base alla progettazione. IMO la scelta dell'archivio eventi non influisce su questa decisione progettuale. Grazie ancora per la tua risposta. –

0

Un motivo per cui l'archivio eventi sul lato scrittura potrebbe essere per la risoluzione dei problemi di concorrenza prima che gli eventi diventino "fatti" e vengano distribuiti/inviati, ad es. attraverso il blocco ottimistico sul commit di flussi di eventi. In questo modo, sul lato scrittura è possibile assicurarsi che i "commit" simultanei allo stesso flusso di eventi (aggregato) siano risolti, uno di loro attraversi, l'altro deve risolvere i conflitti in modo intelligente confrontando gli eventi o propagandoli il conflitto con il cliente, rifiutando così il comando.

+0

Puoi fare un esempio? La concorrenza può essere ed è sempre stata gestita senza un negozio di eventi. Ma mi interessa esattamente cosa intendi per "confrontare gli eventi", poiché è qualcosa che sembra non poter essere gestito senza memorizzare gli eventi. C'è una sorta di risoluzione intelligente che potresti praticamente implementare più facilmente con gli eventi? –

+0

@JeremyRosenberg Penso che quello che sta arrivando romanb qui è che ogni evento dovrebbe generalmente mantenere una proprietà "versione" che indica la versione corrente di quell'aggregato. Pertanto, sul lato scrittura, prima che l'evento venga effettivamente eseguito, è possibile eseguire un controllo ottimistico della concorrenza in base alla versione aggregata * prevista * rispetto alla versione aggregata * effettiva * (ovvero l'ultima versione dell'evento nello stream). Questo approccio risolve i problemi in un sistema distribuito in cui il tuo aggregato potrebbe diventare obsoleto, cioè gli eventi sono stati commessi nel mezzo. – James

10

Questa è una domanda lunga e morta a cui qualcuno mi ha indirizzato. Ci sono diversi motivi per cui è meglio memorizzare eventi sul lato della scrittura.

Dal mio punto di vista l'architettura di cui si sta parlando è una cosa molto comune che vedo ... fallire. Archiviamo il nostro modello di dominio in un database relazionale e poi pubblichiamo eventi. Si aggiunge il tocco di loro salvando gli eventi sul lato di lettura in un negozio di eventi. Questo probabilmente porterà ad un disastro.

Il primo numero che incontrerete riguarda la pubblicazione dei vostri eventi. Cosa succede quando salgo nel database e pubblico per dire MSMQ (muoio nel mezzo). Quindi DTC viene introdotto tra di loro. Questa è una cosa enorme da portare, le transazioni distribuite dovrebbero essere evitate come la peste. È anche abbastanza inefficiente dato che probabilmente sto facendo durare i dati due volte (una volta per fare la coda una volta al database). Ciò limiterà il throughput del sistema di molto (i benchmark DTC di 200-300 messaggi/secondo sono comuni, con eventi solo 20-30k/secondo è comune).

Alcuni aggirare la necessità di DTC inserendo una tabella nel loro database che ha gli eventi e opera come una coda. Ciò eviterà la necessità di DTC, tuttavia ciò continuerà a verificarsi nel prossimo numero.

Cosa succede quando si verifica un errore? So che non si scriverà mai codice buggato ma uno degli sviluppatori di Jrs/manutenzione in seguito collaborerà con il progetto. Ad esempio, cosa succede quando l'oggetto dominio cambia e l'evento generato non corrisponde? Supponiamo che tu abbia impostato lo stato sul tuo oggetto dominio su "LA" (hardcoded) ma che tu abbia impostato correttamente lo stato sull'evento su cmd.State ("CT").

Come verranno rilevati tali errori? Il problema più grande di ciò che viene discusso è che ora ci sono due fonti di "verità": c'è il database sul lato di scrittura e il flusso di eventi che esce. Non c'è modo di dimostrare che sono equivalenti. Ciò causerà tutti i tipi di bug strani lungo la linea.

+2

L'argomento per avere una ** singola fonte di verità ** è il punto principale di event sourcing (IMO) e ciò ti obbliga a mantenere un archivio eventi sul lato scrittura. –

Problemi correlati