sql >> Database teknologi >  >> NoSQL >> Redis

Transaktioner og uropgørelse i Redis

Der er flere spørgsmål her.

1) Hvorfor kan vi ikke udføre stigninger i transaktionen, der ikke kan afbrydes af andre kommandoer?

Bemærk først, at Redis "transaktioner" er helt anderledes end hvad de fleste mennesker tror, ​​transaktioner er i klassisk DBMS.

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

Du skal forstå, hvad der udføres på serversiden (i Redis), og hvad der udføres på klientsiden (i dit script). I ovenstående kode vil GET- og SET-kommandoerne blive udført på Redis-siden, men tildeling til strøm og beregning af strøm + 1 formodes at blive udført på klientsiden.

For at garantere atomicitet forsinker en MULTI/EXEC-blok udførelsen af ​​Redis-kommandoer indtil exec. Så klienten vil kun samle GET- og SET-kommandoerne i hukommelsen og udføre dem i ét skud og atomisk til sidst. Selvfølgelig vil forsøget på at tildele strøm til resultatet af GET og inkrementering forekomme i god tid før. Faktisk vil redis.get-metoden kun returnere strengen "QUEUED" for at signalere, at kommandoen er forsinket, og inkrementeringen vil ikke fungere.

I MULTI/EXEC-blokke kan du kun bruge kommandoer, hvis parametre kan kendes fuldt ud før begyndelsen af ​​blokken. Du kan eventuelt læse dokumentationen for mere information.

2) Hvorfor skal vi i stedet gentage og vente, indtil ingen ændrer værdi, før transaktionen starter?

Dette er et eksempel på samtidig optimistisk mønster.

Hvis vi ikke brugte WATCH/MULTI/EXEC, ville vi have en potentiel løbstilstand:

# 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

Lad os nu tilføje en WATCH/MULTI/EXEC-blok. Med en WATCH-sætning udføres kommandoerne mellem MULTI og EXEC kun, hvis værdien ikke er ændret.

# 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.

Så du behøver ikke at gentage for at vente, indtil ingen ændrer værdien, men snarere at forsøge operationen igen og igen, indtil Redis er sikker på, at værdierne er konsistente og signalerer, at den er vellykket.

I de fleste tilfælde, hvis "transaktionerne" er hurtige nok, og sandsynligheden for at have strid er lav, er opdateringerne meget effektive. Nu, hvis der er uenighed, skal der udføres nogle ekstra operationer for nogle "transaktioner" (på grund af iterationen og genforsøg). Men dataene vil altid være konsistente, og der kræves ingen låsning.




  1. Sådan kalder du db.Collection.stats() fra Mongo java-driver

  2. Sådan adskilles redis-database for samme to app i node.js

  3. Sådan eksporteres MongoDB-forespørgselsresultater til en CSV-fil

  4. Hvordan bruger jeg Map/Reduce i MongoDB?