Quando si usa un'operazione coerente finale costituita da una serie di passaggi, il modello di transazione di compensazione può essere utile. In particolare, se uno o più passaggi hanno esito negativo, è possibile utilizzare il modello Transazione di compensazione per annullare il lavoro eseguito dai passaggi. In genere, si trovano operazioni che seguono il modello di coerenza finale nelle applicazioni ospitate nel cloud che implementano processi e flussi di lavoro aziendali complessi.
Contesto e problema
Le applicazioni eseguite nel cloud modificano frequentemente i dati. Questi dati vengono talvolta distribuiti tra varie origini dati in posizioni geografiche diverse. Per evitare conflitti e migliorare le prestazioni in un ambiente distribuito, un'applicazione non deve provare a offrire coerenza transazionale assoluta. Deve invece implementare la coerenza finale. Nel modello di coerenza finale, un'operazione aziendale tipica è costituita da una serie di passaggi separati. Mentre l'operazione esegue questi passaggi, la visualizzazione generale dello stato del sistema potrebbe essere incoerente. Tuttavia, al termine dell'operazione e tutti i passaggi sono stati eseguiti, il sistema dovrebbe diventare di nuovo coerente.
L'introduzione alla coerenza dei dati fornisce informazioni sul motivo per cui le transazioni distribuite non sono scalabili correttamente. Questa risorsa elenca anche i principi del modello di coerenza finale.
Una sfida nel modello di coerenza finale è come gestire un passaggio che ha esito negativo. Dopo un errore, potrebbe essere necessario annullare tutto il lavoro eseguito nei passaggi precedenti dell'operazione completata. Tuttavia, non è sempre possibile eseguire il rollback dei dati, perché altre istanze simultanee dell'applicazione potrebbero averlo modificato. Anche nei casi in cui le istanze simultanee non hanno modificato i dati, l'annullamento di un passaggio potrebbe essere più complesso rispetto al ripristino dello stato originale. Potrebbe essere necessario applicare diverse regole specifiche dell'azienda. Per un esempio, vedere il sito Web di viaggio descritto nella sezione Esempio più avanti in questo articolo.
Se un'operazione che implementa la coerenza finale si estende su più archivi dati eterogenei, annullare i passaggi dell'operazione richiede di visitare a sua volta ogni archivio dati. Per evitare che il sistema rimanga incoerente, è necessario annullare in modo affidabile il lavoro eseguito in ogni archivio dati.
I dati interessati da un'operazione che implementa la coerenza finale non sono sempre contenuti in un database. Si consideri, ad esempio, un ambiente SOA (Service-Oriented Architecture). Un'operazione SOA può richiamare un'azione in un servizio e causare una modifica nello stato mantenuto da tale servizio. Per annullare l'operazione, è anche necessario annullare questa modifica dello stato. Questo processo può comportare la chiamata del servizio di nuovo e l'esecuzione di un'altra azione che inverte gli effetti del primo.
Soluzione
La soluzione consiste nell'implementare una transazione di compensazione. I passaggi di una transazione di compensazione annullano gli effetti dei passaggi dell'operazione originale. Un approccio intuitivo consiste nel sostituire lo stato corrente con lo stato in cui si trovava il sistema all'inizio dell'operazione. Tuttavia, una transazione di compensazione non può sempre adottare questo approccio, perché potrebbe sovrascrivere le modifiche apportate ad altre istanze simultanee di un'applicazione. Al contrario, una transazione di compensazione deve essere un processo intelligente che tiene conto di qualsiasi lavoro svolto da istanze simultanee. Questo processo è in genere specifico dell'applicazione, in base alla natura del lavoro eseguito dall'operazione originale.
Un approccio comune prevede l'uso di un flusso di lavoro per implementare un'operazione coerente che richiede la compensazione. Man mano che l'operazione originale procede, il sistema registra informazioni su ogni passaggio, incluso come annullare il lavoro eseguito dal passaggio. Se l'operazione ha esito negativo in qualsiasi punto, il flusso di lavoro viene riavvolso attraverso i passaggi completati. In ogni passaggio, il flusso di lavoro esegue il lavoro che inverte tale passaggio.
Due punti importanti sono:
- Una transazione di compensazione potrebbe non dover annullare il lavoro nell'ordine inverso esatto dell'operazione originale.
- Potrebbe essere possibile eseguire alcuni dei passaggi di annullamento in parallelo.
Questo approccio è simile alla strategia sagas discussa nel blog di Clemens Vasters.
Una transazione di compensazione è un'operazione coerente alla fine, quindi può anche avere esito negativo. Il sistema deve essere in grado di riprendere la transazione di compensazione al momento dell'errore e continuare. Potrebbe essere necessario ripetere un passaggio che ha esito negativo, pertanto è necessario definire i passaggi in una transazione di compensazione come comandi idempotenti. Per altre informazioni, vedere Idempotency Patterns (Modelli di Idempotenza) nel blog di Jonathan Oliver.
In alcuni casi, l'intervento manuale potrebbe essere l'unico modo per eseguire il ripristino da un passaggio non riuscito. In queste situazioni, il sistema deve generare un avviso e fornire il maggior numero possibile di informazioni sul motivo dell'errore.
Considerazioni e problemi
Quando si decide come implementare questo modello, tenere presente quanto segue:
Potrebbe non essere facile determinare quando un passaggio di un'operazione che implementa la coerenza finale non riesce. Un passaggio potrebbe non riuscire immediatamente. Potrebbe invece essere bloccata. Potrebbe essere necessario implementare un meccanismo di timeout.
Non è facile generalizzare la logica di compensazione. Una transazione di compensazione è specifica dell'applicazione. Si basa sul fatto che l'applicazione possieda informazioni sufficienti per poter annullare gli effetti di ogni passaggio di un'operazione non riuscita.
Le transazioni di compensazione non funzionano sempre. È necessario definire i passaggi in una transazione di compensazione come comandi idempotenti. In tal caso, i passaggi possono essere ripetuti se la transazione di compensazione ha esito negativo.
L'infrastruttura che gestisce i passaggi deve soddisfare i criteri seguenti:
- È resiliente nell'operazione originale e nella transazione di compensazione.
- Non perde le informazioni necessarie per compensare un passaggio di errore.
- Monitora in modo affidabile lo stato di avanzamento della logica di compensazione.
Una transazione di compensazione non restituisce necessariamente i dati di sistema allo stato all'inizio dell'operazione originale. Al contrario, la transazione compensa il lavoro che l'operazione è stata completata correttamente prima che non sia riuscita.
L'ordine dei passaggi nella transazione di compensazione non è necessariamente l'esatto opposto dei passaggi dell'operazione originale. Ad esempio, un archivio dati potrebbe essere più sensibile alle incoerenze rispetto a un altro. I passaggi della transazione di compensazione che annullano prima le modifiche apportate a questo archivio.
Alcune misure possono contribuire ad aumentare la probabilità che l'attività complessiva abbia esito positivo. In particolare, è possibile inserire un blocco basato sul timeout a breve termine su ogni risorsa necessaria per completare un'operazione. È anche possibile ottenere queste risorse in anticipo. Eseguire quindi il lavoro solo dopo aver acquisito tutte le risorse. Finalizzare tutte le azioni prima della scadenza dei blocchi.
La logica di ripetizione dei tentativi che è più forgiving del solito può aiutare a ridurre al minimo gli errori che attivano una transazione di compensazione. Se un passaggio di un'operazione che implementa la coerenza finale non riesce, provare a gestire l'errore come eccezione temporanea e ripetere il passaggio. Arrestare l'operazione e avviare una transazione di compensazione solo se un passaggio ha esito negativo ripetutamente o non può essere recuperato.
Quando si implementa una transazione di compensazione, si affrontano molte delle stesse sfide affrontate quando si implementa la coerenza finale. Per altre informazioni, vedere la sezione "Considerazioni per l'implementazione della coerenza finale" in Informazioni di base sulla coerenza dei dati.
Quando usare questo modello
Usare questo modello solo per le operazioni che devono essere annullate in caso di errore. Se possibile, progettare soluzioni per evitare la complessità della richiesta di transazioni di compensazione.
Progettazione del carico di lavoro
Un architetto deve valutare il modo in cui il modello di transazione di compensazione può essere usato nella progettazione del carico di lavoro per soddisfare gli obiettivi e i principi trattati nei pilastri di Azure Well-Architected Framework. Ad esempio:
Concetto fondamentale | Come questo modello supporta gli obiettivi di pilastro |
---|---|
Le decisioni di progettazione dell'affidabilità consentono al carico di lavoro di diventare resilienti a malfunzionamenti e di assicurarsi che venga ripristinato in uno stato completamente funzionante dopo che si verifica un errore. | Le azioni di compensazione consentono di risolvere i malfunzionamenti nei percorsi critici del carico di lavoro usando processi come il rollback diretto delle modifiche dei dati, l'interruzione dei blocchi delle transazioni o persino l'esecuzione del comportamento del sistema nativo per invertire l'effetto. - Flussi critici RE:02 - RE:09 Ripristino di emergenza |
Come per qualsiasi decisione di progettazione, prendere in considerazione eventuali compromessi rispetto agli obiettivi degli altri pilastri che potrebbero essere introdotti con questo modello.
Esempio
I clienti usano un sito Web di viaggi per prenotare gli itinerari. Un singolo itinerario può essere costituito da una serie di voli e hotel. Un cliente che viaggia da Seattle a Londra e quindi a Parigi può seguire questa procedura durante la creazione di un itinerario:
- Prenotare un posto sul volo F1 da Seattle a Londra.
- Prenotare un posto sul volo F2 da Londra a Parigi.
- Prenotare un posto sul volo F3 da Parigi a Seattle.
- Prenotare una camera nell'hotel H1 a Londra.
- Prenotare una camera nell'hotel H2 a Parigi.
Questi passaggi costituiscono un'operazione coerente, anche se ogni passaggio è un'operazione separata. Oltre a eseguire questi passaggi, il sistema deve registrare anche le operazioni del contatore per annullare ogni passaggio. Queste informazioni sono necessarie nel caso in cui il cliente annulla l'itinerario. I passaggi necessari per eseguire le operazioni del contatore possono quindi essere eseguiti come transazione di compensazione.
I passaggi della transazione di compensazione potrebbero non essere l'esatto opposto dei passaggi originali. Inoltre, la logica in ogni passaggio della transazione di compensazione deve tenere conto delle regole specifiche dell'azienda. Ad esempio, l'annullamento di una prenotazione di volo potrebbe non autorizzare il cliente a un rimborso completo.
La figura seguente illustra i passaggi di una transazione a esecuzione prolungata per la prenotazione di un itinerario di viaggio. È anche possibile visualizzare i passaggi delle transazioni di compensazione che annullano la transazione.
Nota
Potrebbe essere possibile eseguire i passaggi della transazione di compensazione in parallelo, a seconda della modalità di progettazione della logica di compensazione per ogni passaggio.
In molte soluzioni aziendali, l'errore di un singolo passaggio non richiede sempre il rollback del sistema usando una transazione di compensazione. Si consideri, ad esempio, lo scenario del sito Web di viaggio. Si supponga che il cliente libri i voli F1, F2 e F3, ma non può prenotare una camera all'hotel H1. È preferibile offrire al cliente una camera in un hotel diverso nella stessa città invece di annullare i voli. Il cliente può comunque decidere di annullare. In tal caso, la transazione di compensazione viene eseguita e annulla le prenotazioni per i voli F1, F2 e F3. Ma il cliente deve prendere questa decisione, non il sistema.
Passaggi successivi
- Nozioni di base sulla coerenza dei dati. Il modello di transazioni di compensazione viene spesso usato per annullare le operazioni che implementano il modello di coerenza finale. Questa guida di base fornisce informazioni sui vantaggi e sui compromessi della coerenza finale.
- Modelli di Idempotenza. In una transazione di compensazione, è consigliabile usare i comandi idempotenti. Questo post di blog descrive i fattori da considerare quando si implementa l'idempotenza.
Risorse correlate
- Modello supervisore agente dell'utilità di pianificazione. Questo articolo descrive come implementare sistemi resilienti che eseguono operazioni aziendali che usano servizi e risorse distribuiti. In questi sistemi, a volte è necessario usare una transazione di compensazione per annullare il lavoro eseguito da un'operazione.
- Modello di ripetizione dei tentativi. Le transazioni di compensazione possono essere impegnative dal calcolo. È possibile provare a ridurre al minimo l'uso usando il modello Di ripetizione dei tentativi per implementare un criterio efficace di ripetizione delle operazioni non riuscite.
- Modello di transazioni distribuite saga. Questo articolo illustra come usare il modello Saga per gestire la coerenza dei dati tra microservizi in scenari di transazioni distribuite. Il modello Saga gestisce il ripristino degli errori con transazioni di compensazione.
- Modello Pipe e Filtri. Questo articolo descrive il modello Pipe e filtri, che è possibile usare per scomporre un'attività di elaborazione complessa in una serie di elementi riutilizzabili. È possibile usare il modello Pipe e filtri con il modello transazioni di compensazione come alternativa all'implementazione di transazioni distribuite.
- Progettazione per la correzione automatica. Questa guida illustra come progettare applicazioni di riparazione automatica. È possibile usare transazioni di compensazione come parte di un approccio di riparazione automatica.