Modelli per mantenere la coerenza in un sistema distribuito, basato su eventi?

13

Ho letto su event sourcing ultimamente e mi piacciono molto le idee che ci stanno dietro, ma sono bloccato con il seguente problema .

Supponiamo che tu abbia N processi concorrenti che ricevono comandi (ad esempio server web), generano eventi come risultato e li memorizzano in un archivio centralizzato. Supponiamo inoltre che tutti gli stati transitori di applicazione siano mantenuti nella memoria dei singoli processi applicando in sequenza gli eventi dallo store.

Ora diciamo che abbiamo la seguente regola aziendale: ogni utente distinto deve avere un nome utente univoco.

Se due processi ricevono un comando di registrazione utente per lo stesso nome utente X, entrambi controllano che X non sia nella loro lista di nomi utente, la regola convalida per entrambi i processi e entrambi memorizzano un evento "nuovo utente con nome utente X" nel negozio.

Ora abbiamo inserito uno stato globale incoerente perché la regola aziendale è stata violata (ci sono due utenti distinti con lo stesso nome utente).

In un server N tradizionale < - > 1 sistema stile RDBMS, il database viene utilizzato come punto centrale di sincronizzazione che aiuta a prevenire tali incoerenze.

La mia domanda è: in che modo i sistemi basati sugli eventi in genere affrontano questo problema? Elaborano semplicemente tutti i comandi in sequenza (ad esempio, limita la quantità di processo che può scrivere nel negozio su 1)?

    
posta Olivier Lalonde 19.05.2016 - 20:35
fonte

2 risposte

6

In a traditional N server <-> 1 RDBMS style system, the database is used as a central point of synchronisation which helps prevent such inconsistencies.

Nei sistemi basati su eventi, l '"archivio eventi" svolge lo stesso ruolo. Per un oggetto di origine evento, la tua scrittura è un'appunta dei tuoi nuovi eventi a una particolare versione del flusso di eventi. Quindi, proprio come con la programmazione simultanea, è possibile acquisire un blocco su quella cronologia durante l'elaborazione del comando. È più comune per i sistemi basati su eventi adottare un approccio più ottimistico: caricare la cronologia precedente, calcolare la nuova cronologia, quindi confrontare e scambiare. Se qualche altro comando ha scritto anche su quel flusso, allora il tuo confronto e scambio falliscono. Da lì, puoi rieseguire il comando o abbandonare il comando o persino unire i risultati nella cronologia.

La contesa diventa un grosso problema se tutti i server N con i loro comandi M stanno cercando di scrivere in un singolo stream. La solita risposta qui è di assegnare una cronologia a ciascuna entità originata da eventi nel modello. Quindi Utente (Bob) avrebbe una cronologia distinta da Utente (Alice), e le scritture su uno non bloccherebbero le scritture sull'altro.

My question is: how do event sourced systems typically approach this problem? Do they simply process every commands sequentially?

Greg Young on Set Validation

Esiste un modo elegante per controllare i punti di riferimento unici sugli attributi degli oggetti di dominio senza spostare la business logic nel livello di servizio?

Risposta breve, in molti casi, indagare su tale requisito rivela più profondamente che (a) si tratta di un proxy poco conosciuto per qualche altro requisito, o (b) che le violazioni della "regola" sono accettabili se possono essere rilevate ( rapporto sulle eccezioni), mitigato all'interno di una finestra temporale, o sono a bassa frequenza (es .: i client possono verificare se un nome è disponibile prima di inviare un comando per usarlo).

In alcuni casi, dove il tuo archivio eventi è valido per la convalida dell'insieme (es .: un database relazionale), allora implementi il requisito scrivendo su una tabella "nomi univoci" nella stessa transazione che persiste gli eventi.

In alcuni casi, puoi solo applicare il requisito pubblicando tutti i nomi utente nello stesso stream (che ti consente di valutare il set di nomi in memoria, come parte del tuo modello di dominio). - In questo caso, due processi aggiorneranno il tentativo di aggiornare "la" cronologia del flusso, ma una delle operazioni di confronto e scambio fallirà e il tentativo di tale comando sarà in grado di rilevare il conflitto.

    
risposta data 19.05.2016 - 21:11
fonte
2

Sembra che tu possa implementare un processo aziendale ( saga nel contesto di Domain Driven Design ) per la registrazione dell'utente in cui l'utente viene trattato come CRDT .

Risorse

  1. link link

  2. "CRDT con dati distribuiti Akka" link per informazioni su

    • CmRDT s - CRDT basati sull'operazione
    • CvRDT s - CRTD basati sullo stato
  3. Esempi di codice in Scala link . Forse "carrello della spesa" è più adatto.

  4. Tour di Akka Cluster - Akka Distributed Data link
risposta data 03.02.2018 - 16:16
fonte