Model kompenzační transakce
Akce prováděné pomocí posloupnosti kroků, které společně definují operaci s konečnou konzistencí, můžete v případě, že se některé kroky nezdaří, vrátit zpět. Operace používající model konečné konzistence se běžně nacházejí v aplikacích hostovaných v cloudu, které implementují komplexní obchodní procesy a pracovní postupy.
Kontext a problém
Aplikace spuštěné v cloudu často upravují data. Tato data můžou být rozložená v různých zdrojích dat, které se nacházejí v různých geografických umístěních. Pokud chcete zabránit kolizím a zlepšit výkon v distribuovaném prostředí, neměla by se aplikace pokoušet o poskytování silné konzistence transakcí. Místo toho by aplikace měla implementovat konečnou konzistenci. V tomto modelu se obvyklá obchodní operace skládá z posloupnosti samostatných kroků. Během provádění těchto kroků může být celkový pohled na stav systému nekonzistentní, ale po dokončení operace a po provedení všech kroků by měl být systém opět konzistentní.
Úvod do konzistence dat poskytuje informace o důvodech, proč se distribuované transakce dobře neškálují, a zásady modelu konečné konzistence.
Problémem v modelu konečné konzistence může být způsob, jak zacházet s krokem, který se nezdařil. V takovém případě může být nutné všechny akce provedené předchozími kroky v operaci vrátit zpět. Data však nelze jednoduše vrátit zpět, protože je mohly změnit jiné souběžné instance dané aplikace. Dokonce i v případech, kdy souběžná instance data nezměnila, nemusí vrácení kroku zpět znamenat pouhé obnovení původního stavu. Může být nutné použít různá pravidla specifická pro daný obor podnikání (viz web pro plánování cest v oddílu Příklad).
Pokud operace, která implementuje konečnou konzistenci, zahrnuje několik heterogenních úložišť dat, bude vrácení kroků v operaci zpět vyžadovat postupné návštěvy jednotlivých úložišť dat. Aby se zabránilo tomu, že systém zůstane nekonzistentní, je nutné akce prováděné v jednotlivých úložištích dat spolehlivě vrátit zpět.
Některá data ovlivněná operací, která implementuje konečnou konzistenci, se nemusí uchovávat v databázi. V prostředí architektury SOA (Service Oriented Architecture) může operace vyvolat akci ve službě a způsobit změnu stavu uchovávaného touto službou. Při zrušení operace je nutné tuto změnu stavu také vrátit zpět. Může to zahrnovat opětovné vyvolání služby a provedení další akce, která vrátí účinky první akce zpět.
Řešení
Řešením je implementace kompenzační transakce. Kroky v kompenzační transakci musí vrátit zpět účinky kroků v původní operaci. Kompenzační transakce nemusí jednoduše nahrazovat aktuální stav stavem, ve kterém byl systém na začátku operace, protože takový přístup by mohl přepsat změny provedené jinými souběžnými instancemi aplikace. Spíše to tedy musí být inteligentní proces, který bere v úvahu veškeré akce provedené souběžnými instancemi. Tento proces bude obvykle specifický pro danou aplikaci a bude se řídit povahou akcí, které provedla původní operace.
Běžným přístupem je použití pracovního postupu pro implementaci operace s konečnou konzistencí, která vyžaduje kompenzaci. Při provádění původní operace systém zaznamenává informace o jednotlivých krocích a o tom, jak se akce prováděné v každém kroku dají vrátit zpět. Pokud operace v nějakém okamžiku selže, pracovní postup zruší dokončené kroky tak, že provede akce, které vrátí jednotlivé kroky zpět. Upozorňujeme, že kompenzační transakce nemusí akce vracet zpět v přesně opačném pořadí jako původní operace a že některé akce pro vrácení kroků zpět se můžou provádět souběžně.
Tento přístup se podobá strategii Sagas, která je vysvětlená v příspěvku na blogu Clemense Vasterse.
Kompenzační transakce je také operace s konečnou konzistencí a může také selhat. Systém by měl být schopen obnovit kompenzační transakci v bodě selhání a pokračovat. Krok, který selhal, může být nutné zopakovat, a proto by kroky v kompenzační transakci měly být definované jako idempotentní příkazy. Další informace najdete v tématu Idempotence vzory na blogu Jonathana Olivera.
Někdy je možné provést obnovení od kroku, který selhal, jenom pomocí ručního zásahu. V takových situacích by měl systém zobrazit upozornění a poskytnout co nejvíce informací o příčině selhání.
Problémy a důležité informace
Když se budete rozhodovat, jak tento model implementovat, měli byste vzít v úvahu následující skutečnosti:
Zjištění selhání kroku v operaci implementující konečnou konzistenci nemusí být jednoduché. Selhání kroku se nemusí projevit okamžitě, ale může způsobit zablokování. Může být nutná implementace nějaké formy mechanismu časového limitu.
Kompenzační logika se nezobecňuje snadno. Kompenzační transakce je specifická pro danou aplikaci. Spoléhá na to, že aplikace má dostatek informací, aby bylo možné účinky jednotlivých kroků v nezdařené operaci vrátit zpět.
Kroky v kompenzační transakci byste měli definovat jako idempotentní příkazy. Pokud pak sama kompenzační transakce selže, bude možné tyto kroky zopakovat.
Infrastruktura zpracovávající kroky v původní operaci a v kompenzační transakci musí být odolná. Nesmí dojít ke ztrátě informací potřebných ke kompenzaci případného nezdařeného kroku a musí být možné spolehlivě monitorovat průběh kompenzační logiky.
Kompenzační transakce nemusí nutně vrátit data v systému do stavu, ve kterém se nacházela na začátku původní operace. Měla by však kompenzovat akce provedené v krocích, které se úspěšně dokončily před selháním operace.
Pořadí kroků v kompenzační transakci nemusí být nutně přesným opakem kroků v původní operaci. Některé úložiště dat například může být citlivější na nekonzistence než jiné, a proto by se měly kroky v kompenzační transakci, které vrátí zpět změny v tomto úložišti, provést nejdříve.
Použití krátkodobého uzamknutí s časovým limitem u jednotlivých prostředků, které jsou nutné k dokončení operace, a přednostní získání přístupu k těmto prostředkům můžou zvýšit pravděpodobnost, že celá aktivita bude úspěšná. Akce by se měly provést až po získání přístupu ke všem prostředkům. Všechny akce se musí dokončit, než platnost těchto uzamknutí vyprší.
Aby se minimalizovaly chyby aktivující kompenzační transakci, zvažte použití logiky pro opakování pokusů, která je méně striktní než obvykle. Pokud se krok v operaci implementující konečnou konzistenci nezdaří, zkuste s touto chybou zacházet jako s přechodnou výjimkou a opakovat krok. Zastavení operace a spuštění kompenzační transakce proveďte až v případě, že dojde k opakovanému nebo neobnovitelnému selhání daného kroku.
Řada problémů při implementaci kompenzační transakce je stejných jako při implementaci konečné konzistence. Další informace najdete v tématu Úvod do konzistence dat v části týkající se aspektů implementace konečné konzistence.
Kdy se má tento model použít
Tento model používejte jenom pro operace, které je nutné při jejich selhání vrátit zpět. Pokud je to možné, navrhujte řešení, která nebudou vyžadovat složité kompenzační transakce.
Příklad
Web pro plánování cest umožňuje zákazníkům provádět rezervace pro cesty. Plán cesty může tvořit posloupnost letů a hotelů. Zákazník cestující ze Seattlu do Londýna a pak do Paříže může při vytváření plánu cesty provést tyto kroky:
- Rezervace letenky na let F1 ze Seattlu do Londýna
- Rezervace letenky na let F2 z Londýna do Paříže
- Rezervace letenky na let F3 z Paříže do Seattlu
- Rezervace pokoje v hotelu H1 v Londýně
- Rezervace pokoje v hotelu H2 v Paříži
Každý krok je sice samostatnou akcí, ale tyto kroky tvoří operaci s konečnou konzistencí. Při provádění těchto kroků tedy musí systém zaznamenat také operace, kterými je možné vrátit jednotlivé kroky zpět v případě, že se zákazník rozhodne cestu zrušit. Kroky potřebné k provedení těchto operací se pak můžou spustit jako kompenzační transakce.
Upozorňujeme, že kroky v kompenzační transakci nemusí být přesným opakem původních kroků a že logika v jednotlivých krocích v kompenzační transakci musí brát v úvahu pravidla specifická pro daný obor podnikání. Například při zrušení rezervace letenky nemusí mít zákazník nárok na plnou refundaci uhrazené ceny. Obrázek znázorňuje vygenerování kompenzační transakce, která zruší dlouhodobou transakci provádějící rezervace pro plán cesty.

Poznámka
V závislosti na tom, jak jste navrhli kompenzační logiku pro jednotlivé kroky, se kroky v kompenzační transakci můžou provádět souběžně.
U řady obchodních řešení nevyžaduje selhání jednoho kroku vždycky vrácení systému zpět pomocí kompenzační transakce. Pokud se například ve scénáři s webem pro plánování cest zákazníkovi po rezervaci letů F1, F2 a F3 nepodaří provést rezervaci pokoje v hotelu H1, je vhodnější místo zrušení letů nabídnout tomuto zákazníkovi pokoj v jiném hotelu ve stejném městě. Zákazník se přesto může rozhodnout zrušit lety (v tom případě se spustí kompenzační transakce a zruší rezervace na lety F1, F2 a F3), ale toto rozhodnutí by měl udělat zákazník a ne systém.
Související informace
Při implementaci tohoto modelu můžou být relevantní také následující modely a pokyny:
Úvod do konzistence dat Model kompenzační transakce se často používá ke zrušení operací, které implementují model konečné konzistence. Tento úvod poskytuje informace o výhodách a nevýhodách konečné konzistence.
Scheduler – vzor vedoucího agenta. Popisuje implementaci odolných systémů provádějících obchodní operace, které používají distribuované služby a prostředky. Někdy může být nutné vrátit akce provedené nějakou operací zpět pomocí kompenzační transakce.
Vzor opakování. Provádění kompenzačních transakcí může být nákladné. Jejich používání lze minimalizovat implementací efektivních zásad pro opakování neúspěšných operací podle modelu opakování.