Het Saga-ontwerppatroon helpt de consistentie van gegevens in gedistribueerde systemen te behouden door transacties over meerdere services te coördineren. Een saga is een reeks lokale transacties waarbij elke service zijn werking uitvoert en de volgende stap door gebeurtenissen of berichten initieert. Als een stap in de reeks mislukt, voert de saga compenserende transacties uit om de voltooide stappen ongedaan te maken, waarbij de gegevensconsistentie behouden blijft.
Context en probleem
Een transactie vertegenwoordigt een werkeenheid, die meerdere bewerkingen kan bevatten. Binnen een transactie verwijst een gebeurtenis verwijst naar een statuswijziging die van invloed is op een entiteit. Een opdracht bevat alle informatie die nodig is om een actie uit te voeren of een volgende gebeurtenis te activeren.
Transacties moeten voldoen aan de principes van atomiciteit, consistentie, isolatie en duurzaamheid (ACID).
- Atomiciteit: alle bewerkingen slagen of geen bewerkingen.
- consistentie: gegevens worden van de ene geldige status naar de andere overgestapt.
- Isolatie: gelijktijdige transacties leveren dezelfde resultaten op als opeenvolgende transacties.
- Duurzaamheid: zodra ze zijn doorgevoerd, blijven wijzigingen zelfs in fouten bestaan.
In één service volgen transacties ACID-principes omdat ze binnen één database werken. Het bereiken van ACID-naleving voor meerdere services is echter complexer.
Uitdagingen in microservicesarchitecturen
Microservicesarchitecturen wijzen doorgaans een toegewezen database toe aan elke microservice, wat verschillende voordelen biedt:
- Elke service bevat zijn eigen gegevens.
- Elke service kan gebruikmaken van de meest geschikte databasetechnologie en het schema voor de specifieke behoeften.
- Onafhankelijk schalen van databases voor elke service.
- Fouten in de ene service worden geïsoleerd van andere services.
Ondanks deze voordelen maakt deze architectuur de consistentie van gegevens in meerdere services ingewikkeld. Traditionele databasegaranties zoals ACID zijn niet rechtstreeks van toepassing op meerdere onafhankelijk beheerde gegevensarchieven. Vanwege deze beperkingen zijn architecturen die afhankelijk zijn van IPC(Interprocess Communication) of traditionele transactiemodellen, zoals het protocol voor twee fasen doorvoeren (2PC), vaak beter geschikt voor het Saga-patroon.
Oplossing
Het Saga-patroon beheert transacties door ze op te breken in een reeks lokale transacties (zie afbeelding 1).
Afbeelding 1. Een saga met drie diensten.
Elke lokale transactie:
- Voltooit het werk atomisch binnen één service.
- Hiermee wordt de database van de service bijgewerkt.
- Start de volgende transactie via een gebeurtenis of bericht.
- Als een lokale transactie mislukt, voert de saga een reeks compenserende transacties uit om de wijzigingen die door de voorgaande lokale transacties zijn aangebracht, om te keren.
Belangrijkste concepten in het Saga-patroon
compensable transacties: transacties waarvoor andere transacties ongedaan kunnen maken of compenseren met het tegenovergestelde effect. Als een stap in de saga mislukt, maken compenserende transacties de wijzigingen ongedaan die de compenserende transacties hebben aangebracht.
draaitransactie: de draaitransactie fungeert als het "punt van geen terugkeer" in de saga. Zodra de draaitransactie is geslaagd, zijn compenserende transacties (die ongedaan kunnen worden gemaakt) niet langer relevant. Alle volgende acties moeten worden voltooid voor het systeem om een consistente eindstatus te bereiken. Een draaitransactie kan in verschillende rollen vallen, afhankelijk van de stroom van de saga:
kan niet ongedaan worden gemaakt (niet-compatibel): het kan niet ongedaan worden gemaakt of opnieuw worden geprobeerd.
Grens tussen omkeerbare en vastgelegde: het kan de laatste ondoeerbare (compensable) transactie zijn, of het kan de eerste bewerking zijn die opnieuw kan worden geprobeerd in de saga.
opnieuw te proberen transacties: deze transacties volgen de draaitransactie. Opnieuw te proberen transacties zijn idempotent en zorgen ervoor dat de saga de uiteindelijke status kan bereiken, zelfs als er tijdelijke fouten optreden. Het garandeert dat de saga uiteindelijk een consistente toestand bereikt.
Saga-implementatiemethoden
Er zijn twee algemene saga-implementatiemethoden, choreografie en indeling. Elke benadering heeft een eigen set uitdagingen en technologieën om de werkstroom te coördineren.
Choreografie
In choreografie wisselen diensten gebeurtenissen uit zonder gecentraliseerde controller. Met choreografie publiceert elke lokale transactie domeingebeurtenissen die lokale transacties in andere services activeren (zie afbeelding 2).
Afbeelding 2. Een saga die gebruikmaakt van choreografie.
Voordelen van choreografie | Nadelen van choreografie |
---|---|
Geschikt voor eenvoudige werkstromen met weinig services en geen coördinatielogica nodig. | Werkstroom kan verwarrend worden bij het toevoegen van nieuwe stappen. Het is moeilijk om bij te houden welke saga-deelnemers naar welke opdrachten luisteren. |
Er is geen andere service vereist voor coördinatie. | Er bestaat een risico op cyclische afhankelijkheid tussen saga-deelnemers, omdat ze elkaars opdrachten moeten gebruiken. |
Introduceert geen single point of failure, omdat de verantwoordelijkheden worden verdeeld over de saga-deelnemers. | Integratietests zijn moeilijk omdat alle services moeten worden uitgevoerd om een transactie te simuleren. |
Orkestratie
In orchestration verwerkt een gecentraliseerde controller (orchestrator) alle transacties en vertelt de deelnemers welke bewerking moet worden uitgevoerd op basis van gebeurtenissen. De orchestrator voert saga-aanvragen uit, slaat en interpreteert de statussen van elke taak en verwerkt foutherstel met compenserende transacties (zie afbeelding 3).
Afbeelding 3. Een saga die gebruikmaakt van orchestration.
Voordelen van indeling | Nadelen van indeling |
---|---|
Beter geschikt voor complexe werkstromen of bij het toevoegen van nieuwe services. | Andere ontwerpcomplexiteit vereist een implementatie van een coördinatielogica. |
Vermijd cyclische afhankelijkheden omdat de orchestrator de stroom beheert. | Introduceert een foutpunt omdat de orchestrator de volledige werkstroom beheert. |
Duidelijke scheiding van verantwoordelijkheden vereenvoudigt servicelogica. |
Problemen en overwegingen
Houd rekening met de volgende punten bij het implementeren van het Saga-patroon:
Shift in ontwerpdenken: Het toepassen van het Saga-patroon vereist een andere mindset, waarbij u zich richt op het coördineren van transacties en het garanderen van gegevensconsistentie in meerdere microservices.
Complexiteit van foutopsporing van saga's: foutopsporingssages kunnen complex zijn, met name naarmate het aantal deelnemende services groeit.
onherstelbare lokale databasewijzigingen: Gegevens kunnen niet worden teruggedraaid omdat saga-deelnemers wijzigingen doorvoeren in hun respectieve databases.
Afhandeling van tijdelijke fouten en idempotentie: het systeem moet tijdelijke fouten effectief afhandelen en idempotentie garanderen, waarbij het herhalen van dezelfde bewerking het resultaat niet wijzigt. Zie Idempotent message processingvoor meer informatie.
Behoefte aan monitoring en tracering van saga's: Bewaking en tracering van de werkstroom van een saga zijn essentieel om operationeel toezicht te houden.
Beperkingen van compenserende transacties: compenserende transacties slagen mogelijk niet altijd, waardoor het systeem mogelijk inconsistent blijft.
Mogelijke gegevensafwijkingen in saga's
Gegevensafwijkingen zijn inconsistenties die kunnen optreden wanneer saga's worden uitgevoerd in meerdere services. Omdat elke service zijn eigen gegevens (deelnemergegevens) beheert, is er geen ingebouwde isolatie tussen services. Deze installatie kan leiden tot inconsistenties van gegevens of duurzaamheidsproblemen, zoals gedeeltelijk toegepaste updates of conflicten tussen services. Veelvoorkomende problemen zijn:
Verloren updates: wanneer een saga gegevens wijzigt zonder wijzigingen door een andere saga te overwegen, leidt dit tot overschreven of ontbrekende updates.
Dirty leest: Wanneer een saga of transactie gegevens leest die een andere saga heeft gewijzigd maar nog niet is voltooid.
Fuzzy (niet-onrepeatable) leest: Wanneer verschillende stappen in een saga inconsistente gegevens lezen omdat er updates plaatsvinden tussen de leesbewerkingen.
Strategieën voor het aanpakken van gegevensafwijkingen
Als u deze afwijkingen wilt verminderen of voorkomen, kunt u deze tegenmaatregelen overwegen:
Semantische vergrendeling: gebruik vergrendelingen op toepassingsniveau waarbij de compensable transactie van een saga een semaphore gebruikt om aan te geven dat er een update wordt uitgevoerd.
commutatieve updates: Ontwerpupdates zodat ze in elke volgorde kunnen worden toegepast terwijl ze hetzelfde resultaat produceren, waardoor conflicten tussen saga's worden verminderd.
pessimistische weergave: de volgorde van de saga wijzigen zodat gegevensupdates plaatsvinden in opnieuw te proberen transacties om vuile leesbewerkingen te elimineren. Anders kan één saga vuile gegevens lezen (niet-doorgevoerde wijzigingen) terwijl een andere saga tegelijkertijd een compenserende transactie uitvoert om de updates terug te draaien.
Waarden opnieuw lezen: controleer of de gegevens ongewijzigd blijven voordat er updates worden uitgevoerd. Als de gegevens veranderen, moet u de huidige stap afbreken en de saga indien nodig opnieuw starten.
versiebestanden: onderhoud een logboek van alle bewerkingen op een record en zorg ervoor dat ze in de juiste volgorde worden uitgevoerd om conflicten te voorkomen.
op risico gebaseerde gelijktijdigheid (op waarde): kies dynamisch het juiste gelijktijdigheidsmechanisme op basis van het potentiële bedrijfsrisico. Gebruik bijvoorbeeld saga's voor updates met een laag risico en gedistribueerde transacties voor risicovolle transacties.
Wanneer gebruikt u dit patroon?
Gebruik het Saga-patroon wanneer u het volgende moet doen:
- Zorg voor gegevensconsistentie in een gedistribueerd systeem zonder strakke koppeling.
- Terugdraaien of compenseren als een van de bewerkingen in de reeks mislukt.
Het Saga-patroon is minder geschikt voor:
- Nauw gekoppelde transacties.
- Compenserende transacties die plaatsvinden in eerdere deelnemers.
- Cyclische afhankelijkheden.
Volgende stappen
Gerelateerde resources
De volgende patronen kunnen ook nuttig zijn bij het implementeren van dit patroon:
- Choreografie elk onderdeel van het systeem heeft deelgenomen aan het besluitvormingsproces over de werkstroom van een zakelijke transactie, in plaats van te vertrouwen op een centraal controlepunt.
- compenserende transacties het ongedaan maken van werk dat door een reeks stappen wordt uitgevoerd, en uiteindelijk een consistente bewerking definiëren als een of meer stappen mislukken. In de cloud gehoste toepassingen die complexe bedrijfsprocessen en werkstromen implementeren, volgen vaak dit uiteindelijke consistentiemodel.
- kan een toepassing tijdelijke fouten afhandelen wanneer deze verbinding probeert te maken met een service of netwerkresource door de mislukte bewerking transparant opnieuw uit te voeren. Opnieuw proberen kan de stabiliteit van de toepassing verbeteren.
- circuitonderbreker fouten verwerkt die een variabele hoeveelheid tijd in beslag nemen om van te herstellen, wanneer er verbinding wordt gemaakt met een externe service of resource. Circuitonderbreker kan de stabiliteit en tolerantie van een toepassing verbeteren.
- statuseindpuntbewaking functionele controles implementeert in een toepassing waartoe externe hulpprogramma's met regelmatige tussenpozen toegang hebben via blootgestelde eindpunten. Statuseindpuntbewaking kan helpen controleren of toepassingen en services correct presteren.