Come emettere eventi in modo idempotativo

6

Se ho un servizio che consuma eventi di tipo A ed emette eventi di tipo B, come posso assicurarmi che l'evento B venga emesso una volta sola per ogni evento A? Il servizio dovrebbe anche sottoscrivere eventi di tipo B per vedere che un evento B con lo stesso ID di correlazione / con un riferimento all'evento A non è stato ancora scritto? Sembra un sacco di ulteriori responsabilità per il servizio.

    
posta Mihail Malostanidis 12.09.2018 - 23:18
fonte

4 risposte

5

Assicurati che gli eventi vengano elaborati una sola volta e solo una volta in un sistema distribuito è davvero difficile.

Ma stiamo parlando di guasti alla rete e crash del programma. In un normale sistema di messaggi in coda, se emetti B quando ottieni A e imposti le code correttamente e non hai bug importanti, non dovresti preoccuparti eccessivamente.

Detto questo, quando hai interruzioni sarà una possibilità. Dovresti quindi disporre di sistemi per raccogliere eventi duplicati significativi, ad esempio prendere il pagamento due volte, dopo il fatto e correggerli.

    
risposta data 13.09.2018 - 00:35
fonte
1

Questo è possibile con l'aiuto delle attività. Pat Helland discute di Attività nel suo articolo Vita oltre le transazioni distribuite: l'opinione di un apostata . Vaughn Vernon parla anche di questo in questo video .

L'idea è che un destinatario di un messaggio debba memorizzare nella propria memoria locale gli ID di tutti i messaggi che ha visto. Se riceve un messaggio che ha già visto, lo ignora. Se il destinatario non ha visto il messaggio, lo elabora e quindi emette i suoi nuovi messaggi.

In Sorgente di eventi questo significa che i nuovi messaggi dovrebbero contenere nel loro corpo l'ID del messaggio che era la causa di quei nuovi messaggi.

Quindi, nel tuo caso, il messaggio B dovrebbe contenere l'ID del messaggio A. Quindi, quando il messaggio A viene ritentato, il servizio riproduce tutti i messaggi precedenti che ha emesso, incluso il messaggio B e poi lo vede ha già elaborato il messaggio A e lo ignora.

Questa tecnica, combinata con almeno una consegna, ti dà quello che vuoi, nel modo più scalabile.

    
risposta data 13.09.2018 - 14:13
fonte
1

Sembra che tu stia mescolando due idee abbastanza diverse per l'elaborazione degli eventi qui. Puoi

  1. cerca di trasmettere / elaborare ciascun evento almeno una volta e al massimo una volta, anche nei casi più esotici. Questi sono due problemi difficili che sono entrambi risolvibili solo in parte nei sistemi distribuiti.
  2. cerca di trasmettere / elaborare ogni evento almeno una volta e progetta i tuoi eventi in modo che non importi quando ricevi più eventi per un cambio di dominio . Per questo, l'idempotenza dell'elaborazione dell'evento è un buon approccio.

La seconda soluzione è spesso più semplice e (a volte molto) più performante, a spese di dover riflettere attentamente sulla struttura e il significato dei tuoi eventi. Probabilmente dovrai anche progettare il tuo sistema distribuito in modo che l'ordine, nel quale vengono ricevuti gli eventi, non abbia importanza. E anche gli altri eventi attivati come risultato del secondo arrivo di un evento sono OK.

Un modo per farlo sarebbe quello di mantenere tutti gli ID evento ricevuti in tempi ragionevoli e scartare i duplicati. Ma puoi anche strutturare i tuoi eventi in modo che non importi se vengono ricevuti due volte. È qui che entra in scena l'idemotività: un'operazione (l'elaborazione degli eventi) non cambia più nulla, quando viene ripetuta più di una volta. Ad esempio, se si riceve un evento "l'utente aggiunge l'indirizzo" e l'utente ha già quell'indirizzo, è possibile semplicemente scartare quell'evento.

Nel tuo esempio, questo significa che puoi assicurarti che il servizio emetta un evento di tipo B per ogni evento di tipo A, ma puoi omettere qualsiasi precauzione speciale che non emette mai mai due eventi di tipo B in caso di guasti, dal momento che hai progettato i tuoi eventi in modo che questo non faccia alcun danno (oltre a un po 'più di dati trasmessi). Organizzi le cose che normalmente gli eventi vengono ricevuti una volta, ma in caso di guasti può accadere che venga ricevuto due o più volte.

    
risposta data 20.09.2018 - 08:03
fonte
0

If I have a service that consumes events of type A and emits events of type B, how can I make sure that event B is only emitted once for every event A?

L'unico modo per farlo è quello di garantire che tutti i consumatori dell'evento B facciano parte della stessa transazione dell'evento A.

In un mondo distribuito? nessuna possibilità.

Al massimo una volta che la consegna è banale, è sufficiente inghiottire l'evento B senza mai emetterlo.

Almeno una volta che la consegna è gestibile.

Esattamente una volta che la consegna è al di là economicamente praticabile.

Nella maggior parte dei casi, i punti importanti sono (a) fare il massimo sforzo per garantire che i consumatori riconoscano gli eventi che sono stati elaborati con successo e (b) per avere protocolli in atto per gestire le circostanze quando gli eventi sono stati elaborati più di una volta.

(Esempio: sugli aerei, siamo legalmente limitati a un passeggero per posto, ma a volte può accadere che due passeggeri siano assegnati allo stesso posto. Anche in questa crisi, l'aereo di solito riesce a raggiungere la sua destinazione ... .)

With just at least once delivery, it seems like this would cause an amplification of duplicate messages?

Certamente potrebbe - penso che dipenda da cosa seguono i punti di sincronizzazione e quali strategie vengono applicate dai gestori quando riconoscono un messaggio duplicato.

Ad esempio, se un destinatario sta elaborando messaggi in batch, potrebbe ricevere due copie di un messaggio e riconoscerne la duplicazione.

D'altra parte, il messaggio duplicato può essere un'indicazione che un riconoscimento è stato perso durante il transito, nel qual caso il riconoscimento dovrebbe essere rispedito, in modo che il partecipante a monte possa sapere che il requisito almeno una volta è stato rispettato .

Un buon punto di partenza per questo genere di cose è Messaggistica affidabile senza transazioni distribuite di Udi Dahan. Puoi riconoscere alcune somiglianze con il Pat Helland articolo a cui fa riferimento Constantin

    
risposta data 13.09.2018 - 03:35
fonte

Leggi altre domande sui tag