Redis biedt twee mechanismen voor het afhandelen van transacties:op MULTI/EXEC gebaseerde transacties en evaluatie van Lua-scripts. Redis Lua-scripting is de aanbevolen aanpak en is redelijk populair in gebruik.
Onze Redis™-klanten die Lua-scripts hebben geïmplementeerd, melden deze fout vaak:"BUSY Redis is bezig met het uitvoeren van een script. Je kunt alleen SCRIPT KILL of SHUTDOWN NOSAVE bellen ”. In dit bericht leggen we uit wat de transactie-eigenschap Redis van scripts is, waar deze fout over gaat en waarom we er extra voorzichtig mee moeten zijn op door Sentinel beheerde systemen die een failover kunnen uitvoeren.
Transactionele aard van Redis Lua-scripts
Redis-"transacties" zijn niet echt transacties zoals conventioneel begrepen - in het geval van fouten is er geen terugdraaiing van schrijfbewerkingen die door het script zijn gemaakt.
"Atomiciteit" van Redis-scripts wordt op de volgende manier gegarandeerd:
- Zodra een script wordt uitgevoerd, worden alle andere opdrachten/scripts geblokkeerd totdat het script is voltooid. Dus andere clients zien de wijzigingen die door het script zijn aangebracht of niet. Dit komt omdat ze alleen vóór het script of na het script kunnen worden uitgevoerd.
- Redis doet echter geen rollbacks, dus bij een fout in een script worden alle wijzigingen die al door het script zijn gemaakt behouden en toekomstige commando's/scripts zullen die gedeeltelijke wijzigingen zien.
- Aangezien alle andere clients worden geblokkeerd terwijl het script wordt uitgevoerd, is het van cruciaal belang dat het script zich goed gedraagt en op tijd klaar is.
De 'lua-time-limit'-waarde
Het wordt ten zeerste aanbevolen dat het script binnen een tijdslimiet wordt voltooid. Redis handhaaft dit op een zwakke manier met de waarde ‘lua-time-limit’. Dit is de maximaal toegestane tijd (in ms) dat het script mag worden uitgevoerd. De standaardwaarde is 5 seconden. Dit is erg lang voor CPU-gebonden activiteit (scripts hebben beperkte toegang en kunnen geen opdrachten uitvoeren die toegang hebben tot de schijf).
Het script wordt echter niet afgebroken wanneer het na deze tijd wordt uitgevoerd. Redis begint opnieuw clientopdrachten te accepteren, maar reageert hierop met een BUSY-fout.
Als u het script op dit punt moet beëindigen, zijn er twee opties beschikbaar:
- SCRIPT DOOD commando kan worden gebruikt om een script te stoppen dat nog niet is geschreven.
- Als het script al schrijfacties naar de server heeft uitgevoerd en nog steeds moet worden uitgeschakeld, gebruik dan de SHUTDOWN NOSAVE om de server volledig af te sluiten.
Het is meestal beter om gewoon te wachten tot het script zijn bewerking voltooit. De volledige informatie over methoden om de uitvoering van het script en het bijbehorende gedrag te stoppen, is beschikbaar in de documentatie.
Redis-transacties en langlopende Lua-scriptsKlik om te tweetenGedrag op door Sentinel bewaakte systemen met hoge beschikbaarheid
Sentinel-beheerde hoge-beschikbaarheidssystemen voegen hieraan een nieuwe rimpel toe. In feite is deze discussie van toepassing op elk systeem met hoge beschikbaarheid dat afhankelijk is van de gezondheid van de Redis-servers:
- Langlopende scripts zullen in eerste instantie clientcommando's blokkeren. Later, wanneer de 'lua-time-limit' is verstreken, begint de server te reageren met BUSY-fouten.
- Schildwachten beschouwen een dergelijk knooppunt als niet-beschikbaar, en als dit langer duurt dan de waarde voor down-na-milliseconden die is geconfigureerd op de Sentinels, zullen ze bepalen dat het knooppunt niet beschikbaar is.
- Als een dergelijk knooppunt de master is, wordt een failover gestart. Een replica-knooppunt kan worden gepromoot en nieuwe verbindingen van clients gaan accepteren.
- Ondertussen zal de oudere master uiteindelijk het script voltooien en weer online komen. Sentinel zal het uiteindelijk echter opnieuw configureren als een replica en het zal beginnen te synchroniseren met de nieuwe master. Alle gegevens die door het script zijn geschreven, gaan verloren.
|
Demonstratie
We hebben een gevoelig systeem voor hoge beschikbaarheid opgezet om dit failover-gedrag te demonstreren. De setup heeft 2 Redis-servers die draaien in een master/replica-configuratie die wordt bewaakt door een quorum van 3 schildwachten.
De lua-time-limit-waarde is ingesteld op 500 ms, zodat het begint te reageren op clients met fouten als een script langer dan 500 ms wordt uitgevoerd. De waarde voor down-after-milliseconds op de Sentinels is ingesteld op 5 seconden, zodat een node die fouten meldt na 5 seconden wordt gemarkeerd als DOWN.
We voeren het volgende Lua-script uit op de master:
local i = 0 while (true) do local key = "Key-" .. i local value = "Value-" .. i redis.call('set', key, value) i = i + 1 redis.call('time') end
Hiermee blijft u items in de Redis-master schrijven. We abonneren ons op de gebeurtenissen op een van de schildwachten om het gedrag te observeren.
Het script wordt gestart op de master:
$ redis-cli -a --eval test.lua Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
Hier is een verkorte reeks activiteiten zoals te zien op Sentinel:
3) "+vote-for-leader" 4) "9096772621089bb885eaf7304a011d9f46c5689f 1" 1) "pmessage" 2) "*" 3) "+sdown" <<< master marked DOWN 4) "master test 172.31.2.48 6379" 1) "pmessage" 2) "*" 3) "+odown" 4) "master test 172.31.2.48 6379 #quorum 3/2" 1) "pmessage" 2) "*" 3) "-role-change" << role change initiated 4) "slave 172.31.28.197:6379 172.31.28.197 6379 @ test 172.31.2.48 6379 new reported role is master" 1) "pmessage" 2) "*" 3) "+config-update-from" 4) "sentinel 9096772621089bb885eaf7304a011d9f46c5689f 172.31.2.48 26379 @ test 172.31.2.48 6379" 1) "pmessage" 2) "*" 3) "+switch-master" 4) "test 172.31.2.48 6379 172.31.28.197 6379"
Later, wanneer de oude master online wordt gebracht, wordt deze gewijzigd in een replica:
3) "-role-change" 4) "slave 172.31.2.48:6379 172.31.2.48 6379 @ test 172.31.28.197 6379 new reported role is master" 1) "pmessage" 2) "*" 3) "-sdown" 4) "slave 172.31.2.48:6379 172.31.2.48 6379 @ test 172.31.28.197 6379" 1) "pmessage" 2) "*" 3) "+role-change" 4) "slave 172.31.2.48:6379 172.31.2.48 6379 @ test 172.31.28.197 6379 new reported role is slave"
Alle gegevens die via het script naar de oude master zijn geschreven, gaan verloren.
Aanbevelingen
- U moet de kenmerken van uw langlopende scripts van tevoren kennen voordat u ze in productie kunt nemen.
- Als je script regelmatig de lua-tijdslimiet overtreedt, moet je het script grondig controleren op mogelijke optimalisaties. Je kunt het ook opsplitsen in stukjes die binnen een acceptabele tijd worden voltooid.
- Als u scripts moet uitvoeren die de lua-tijdslimiet overschrijden, overweeg dan om deze scripts te plannen in perioden waarin andere clientactiviteit laag is.
- De waarde van de lua-tijdslimiet kan ook worden verhoogd. Dit zou een acceptabele oplossing zijn als andere clienttoepassingen die parallel met het script worden uitgevoerd, extreem vertraagde reacties kunnen verdragen in plaats van een BUSY-fout en het later opnieuw proberen.
Aanvullende overwegingen bij door Sentinel bewaakte hoge-beschikbaarheidssystemen:
- Als de scripts alleen leesbewerkingen uitvoeren en u replica's beschikbaar heeft, kunt u deze scripts naar de replica's verplaatsen.
Verander de Sentinel-parameter down-after-milliseconds in een waarde die ervoor zorgt dat er geen failovers worden gestart. U moet dit alleen doen na zorgvuldige overweging, omdat een drastische verhoging van de waarde de kenmerken van hoge beschikbaarheid van uw systeem in gevaar brengt. Dit kan er ook toe leiden dat echte serverstoringen worden genegeerd.
|