sql >> Database >  >> NoSQL >> Redis

Transacties en wachtverklaring in Redis

Er zijn hier verschillende vragen.

1) Waarom kunnen we geen stapsgewijze transactie uitvoeren die niet kan worden onderbroken door een ander commando?

Houd er eerst rekening mee dat Redis-'transacties' totaal anders zijn dan wat de meeste mensen denken dat transacties in klassieke DBMS zijn.

# Does not work
redis.multi() 
current = redis.get('powerlevel') 
redis.set('powerlevel', current + 1) 
redis.exec()

U moet begrijpen wat er aan de serverzijde (in Redis) wordt uitgevoerd en wat er aan de clientzijde (in uw script) wordt uitgevoerd. In de bovenstaande code worden de GET- en SET-commando's uitgevoerd aan de Redis-kant, maar toewijzing aan stroom en berekening van stroom + 1 moeten worden uitgevoerd aan de kant van de klant.

Om de atomiciteit te garanderen, vertraagt ​​een MULTI/EXEC-blok de uitvoering van Redis-commando's totdat de exec. Dus de client zal alleen de GET- en SET-commando's in het geheugen opstapelen en ze in één keer en uiteindelijk atomair uitvoeren. Natuurlijk zal de poging om stroom toe te wijzen aan het resultaat van GET en incrementatie ruim van tevoren plaatsvinden. Eigenlijk retourneert de redis.get-methode alleen de tekenreeks "QUEUED" om aan te geven dat de opdracht is vertraagd, en de verhoging zal niet werken.

In MULTI/EXEC-blokken kunt u alleen commando's gebruiken waarvan de parameters volledig bekend kunnen zijn voor het begin van het blok. Misschien wilt u de documentatie lezen voor meer informatie.

2) Waarom moeten we in plaats daarvan herhalen en wachten tot niemand de waarde verandert voordat de transactie begint?

Dit is een voorbeeld van een gelijktijdig optimistisch patroon.

Als we geen WATCH/MULTI/EXEC zouden gebruiken, zouden we een mogelijke raceconditie hebben:

# Initial arbitrary value
powerlevel = 10
session A: GET powerlevel -> 10
session B: GET powerlevel -> 10
session A: current = 10 + 1
session B: current = 10 + 1
session A: SET powerlevel 11
session B: SET powerlevel 11
# In the end we have 11 instead of 12 -> wrong

Laten we nu een WATCH/MULTI/EXEC-blok toevoegen. Met een WATCH-clausule worden de opdrachten tussen MULTI en EXEC alleen uitgevoerd als de waarde niet is gewijzigd.

# Initial arbitrary value
powerlevel = 10
session A: WATCH powerlevel
session B: WATCH powerlevel
session A: GET powerlevel -> 10
session B: GET powerlevel -> 10
session A: current = 10 + 1
session B: current = 10 + 1
session A: MULTI
session B: MULTI
session A: SET powerlevel 11 -> QUEUED
session B: SET powerlevel 11 -> QUEUED
session A: EXEC -> success! powerlevel is now 11
session B: EXEC -> failure, because powerlevel has changed and was watched
# In the end, we have 11, and session B knows it has to attempt the transaction again
# Hopefully, it will work fine this time.

U hoeft dus niet te herhalen om te wachten totdat niemand de waarde verandert, maar om de bewerking steeds opnieuw uit te voeren totdat Redis zeker weet dat de waarden consistent zijn en aangeeft dat het gelukt is.

In de meeste gevallen, als de "transacties" snel genoeg zijn en de kans op twist laag is, zijn de updates zeer efficiënt. Nu, als er onenigheid is, zullen enkele extra bewerkingen moeten worden uitgevoerd voor sommige "transacties" (vanwege de iteratie en nieuwe pogingen). Maar de gegevens zullen altijd consistent zijn en er is geen vergrendeling vereist.




  1. Mongoose optionele zoekopdracht parameters?

  2. Een MongoDB-weergave converteren naar een verzameling

  3. Spring-sessie instellen op redis-server

  4. Introductie van Apache HBase Medium Object Storage (MOB) verdichtingspartitiebeleid