Redis
 sql >> Baza danych >  >> NoSQL >> Redis

Transakcje i obserwuj wyciąg w Redis

Jest tu kilka pytań.

1) Dlaczego nie możemy wykonać przyrostu w transakcji, którego nie można przerwać innym poleceniem?

Proszę zauważyć, że "transakcje" Redis są zupełnie inne niż te, które większość ludzi uważa za transakcje w klasycznym DBMS.

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

Musisz zrozumieć, co jest wykonywane po stronie serwera (w Redis), a co jest wykonywane po stronie klienta (w twoim skrypcie). W powyższym kodzie polecenia GET i SET będą wykonywane po stronie Redis, ale przypisanie do prądu i obliczenie prądu + 1 powinno być wykonywane po stronie klienta.

Aby zagwarantować niepodzielność, blok MULTI/EXEC opóźnia wykonanie poleceń Redis do wykonania. Tak więc klient zgromadzi tylko polecenia GET i SET w pamięci i wykona je za jednym zamachem, a na końcu atomowo. Oczywiście próba przypisania prądu do wyniku GET i inkrementacji nastąpi dużo wcześniej. W rzeczywistości metoda redis.get zwróci tylko ciąg „QUEUED”, aby zasygnalizować, że polecenie jest opóźnione, a inkrementacja nie będzie działać.

W blokach MULTI/EXEC można używać tylko poleceń, których parametry można w pełni poznać przed rozpoczęciem bloku. Możesz przeczytać dokumentację, aby uzyskać więcej informacji.

2) Dlaczego zamiast tego musimy iterować i czekać, aż nikt nie zmieni wartości przed rozpoczęciem transakcji?

To jest przykład jednoczesnego optymistycznego wzorca.

Gdybyśmy nie korzystali z funkcji WATCH/MULTI/EXEC, mielibyśmy potencjalny stan wyścigu:

# 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

Teraz dodajmy blok WATCH/MULTI/EXEC. Z klauzulą ​​WATCH, polecenia między MULTI i EXEC są wykonywane tylko wtedy, gdy wartość nie uległa zmianie.

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

Nie musisz więc powtarzać, aby czekać, aż nikt nie zmieni wartości, ale raczej próbować operacji raz za razem, aż Redis upewni się, że wartości są spójne i zasygnalizuje, że zakończyło się powodzeniem.

W większości przypadków, jeśli „transakcje” są wystarczająco szybkie, a prawdopodobieństwo wystąpienia rywalizacji jest niskie, aktualizacje są bardzo wydajne. Teraz, jeśli istnieje rywalizacja, trzeba będzie wykonać dodatkowe operacje dla niektórych „transakcji” (z powodu iteracji i ponownych prób). Ale dane zawsze będą spójne i nie jest wymagane blokowanie.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Jak ustawić klaster Elasticache Redis jako niewolnika?

  2. Aby rozpocząć ładowanie YCSB z włączoną opcją klastra dla REDIS

  3. Jak zaimplementować tę pojedynczą rozproszoną kolejkę współbieżności na dowolnej platformie MQ?

  4. Tworzenie nowego zestawu z zakresu posortowanego zestawu w Redis

  5. Obsługa przejściowych błędów sieciowych za pomocą StackExchange.Redis