sql >> Databáze >  >> NoSQL >> Redis

Výpis transakcí a sledování v Redis

Je zde několik otázek.

1) Proč nemůžeme provést přírůstek v transakci, kterou nelze přerušit jiným příkazem?

Nejprve si prosím povšimněte, že „transakce“ Redis jsou zcela odlišné od toho, co si většina lidí myslí, že transakce jsou v klasickém DBMS.

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

Musíte rozumět tomu, co se spouští na straně serveru (v Redis) a co se spouští na straně klienta (ve vašem skriptu). Ve výše uvedeném kódu budou příkazy GET a SET provedeny na straně Redis, ale přiřazení k proudu a výpočet proudu + 1 se předpokládá na straně klienta.

Aby byla zaručena atomicita, blok MULTI/EXEC zpožďuje provádění příkazů Redis až do spuštění exec. Klient tedy pouze nahromadí příkazy GET a SET do paměti a provede je najednou a nakonec atomicky. Samozřejmě, že pokus o přiřazení proudu k výsledku GET a inkrementaci proběhne mnohem dříve. Metoda redis.get ve skutečnosti vrátí pouze řetězec "QUEUED" jako signál, že příkaz je zpožděn, a inkrementace nebude fungovat.

V blocích MULTI/EXEC můžete používat pouze příkazy, jejichž parametry mohou být plně známy před začátkem bloku. Možná si budete chtít přečíst dokumentaci pro více informací.

2) Proč musíme před zahájením transakce opakovat a čekat, až nikdo nezmění hodnotu?

Toto je příklad souběžného optimistického vzoru.

Pokud bychom nepoužili žádné WATCH/MULTI/EXEC, měli bychom potenciální závod:

# 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

Nyní přidáme blok WATCH/MULTI/EXEC. S klauzulí WATCH se příkazy mezi MULTI a EXEC provádějí pouze v případě, že se hodnota nezměnila.

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

Nemusíte tedy opakovat a čekat, dokud nikdo nezmění hodnotu, ale spíše se pokoušet o operaci znovu a znovu, dokud si Redis nebude jist, že hodnoty jsou konzistentní, a signalizuje, že je úspěšná.

Ve většině případů, pokud jsou „transakce“ dostatečně rychlé a pravděpodobnost sporu je nízká, jsou aktualizace velmi účinné. Nyní, pokud dojde ke sporu, bude třeba provést některé operace navíc pro některé „transakce“ (kvůli iteraci a opakování). Data však budou vždy konzistentní a není vyžadováno žádné zamykání.




  1. Mongoose - Jak seskupit podle a naplnit?

  2. 4 způsoby aktualizace dokumentu v MongoDB

  3. Mongo Change Streams běžící vícekrát (druh):Aplikace Node spouští více instancí

  4. Zřetězte řetězcové hodnoty v poli do jednoho pole v MongoDB