Co robi Redis, gdy zabraknie pamięci?


111

To może być łatwe pytanie, ale trudno mi znaleźć odpowiedź. Jak Redis 2.0 radzi sobie z wyczerpaniem maksymalnej przydzielonej pamięci? W jaki sposób decyduje, które dane usunąć lub które mają zachować w pamięci?


Odpowiedzi:


94

Jeśli masz włączoną funkcję pamięci wirtualnej (wydaje mi się, że jest to nowość w wersji 2.0 lub 2.2), to Redis zaczyna zapisywać „rzadko używane” dane na dysk, gdy skończy się pamięć.

Jeśli pamięć wirtualna w Redis jest wyłączona, wygląda na to, że pamięć wirtualna systemu operacyjnego zaczyna się zużywać (tj. Wymiana), a wydajność znacznie spada.

Teraz możesz również skonfigurować Redis z parametrem maxmemory, który zapobiega używaniu przez Redis większej ilości pamięci (ustawienie domyślne).

Nowsze wersje Redis mają różne zasady po osiągnięciu maxmemory:

  • volatile-lru usuwa klucz spośród tych z ustawionym terminem ważności, próbując usunąć klucze, które nie były ostatnio używane.
  • volatile-ttl usuwa klucz spośród kluczy z ustawionym terminem ważności, próbując usunąć klucze z krótkim czasem pozostałym do życia.
  • volatile-random usuwa losowy klucz spośród tych, które wygasły.
  • allkeys-lru jak volatile-lru, ale usunie każdy rodzaj klucza, zarówno zwykłe klucze, jak i klucze z ustawionym terminem ważności.
  • allkeys-random jak volatile-random, ale usunie wszystkie rodzaje kluczy, zarówno zwykłe, jak i klucze z ustawionym terminem ważności.

Jeśli wybierzesz zasadę, która usuwa tylko klucze z ustawionym EXPIRE, to gdy w Redis zabraknie pamięci, wygląda na to, że program po prostu przerywa operację malloc (). Oznacza to, że jeśli spróbujesz zapisać więcej danych, operacja po prostu kończy się niepowodzeniem.

Kilka linków, aby uzyskać więcej informacji (ponieważ nie powinieneś wierzyć mi na słowo):


8
Pamięć wirtualna Redis jest teraz przestarzała. Zobacz redis.io/topics/virtual-memory
cgaldiolo.

19

Z redis.conf , wersja 2.8

# Don't use more memory than the specified amount of bytes.
# When the memory limit is reached Redis will try to remove keys
# according to the eviction policy selected (see maxmemory-policy).
#
# If Redis can't remove keys according to the policy, or if the policy is
# set to 'noeviction', Redis will start to reply with errors to commands
# that would use more memory, like SET, LPUSH, and so on, and will continue
# to reply to read-only commands like GET.
#
# This option is usually useful when using Redis as an LRU cache, or to set
# a hard memory limit for an instance (using the 'noeviction' policy).
#
# WARNING: If you have slaves attached to an instance with maxmemory on,
# the size of the output buffers needed to feed the slaves are subtracted
# from the used memory count, so that network problems / resyncs will
# not trigger a loop where keys are evicted, and in turn the output
# buffer of slaves is full with DELs of keys evicted triggering the deletion
# of more keys, and so forth until the database is completely emptied.
#
# In short... if you have slaves attached it is suggested that you set a lower
# limit for maxmemory so that there is some free RAM on the system for slave
# output buffers (but this is not needed if the policy is 'noeviction').
#
# maxmemory <bytes>

# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:
#
# volatile-lru -> remove the key with an expire set using an LRU algorithm
# allkeys-lru -> remove any key according to the LRU algorithm
# volatile-random -> remove a random key with an expire set
# allkeys-random -> remove a random key, any key
# volatile-ttl -> remove the key with the nearest expire time (minor TTL)
# noeviction -> don't expire at all, just return an error on write operations
#
# Note: with any of the above policies, Redis will return an error on write
#       operations, when there are no suitable keys for eviction.
#
#       At the date of writing these commands are: set setnx setex append
#       incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
#       sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
#       zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
#       getset mset msetnx exec sort
#
# The default is:
#
# maxmemory-policy volatile-lru

3
Wartość domyślna maxmemory-policyw Redis 3.2 to teraz noeviction: raw.githubusercontent.com/antirez/redis/3.2/redis.conf
LoicAG

5

Zaktualizuj Redis 4.0

127.0.0.1:6379> MEMORY HELP
1) "MEMORY DOCTOR                        - Outputs memory problems report"
2) "MEMORY USAGE <key> [SAMPLES <count>] - Estimate memory usage of key"
3) "MEMORY STATS                         - Show memory usage details"
4) "MEMORY PURGE                         - Ask the allocator to release memory"
5) "MEMORY MALLOC-STATS                  - Show allocator internal stats"

/usr/local/etc/redis.conf

############################## MEMORY MANAGEMENT ################################

# Set a memory usage limit to the specified amount of bytes.
# When the memory limit is reached Redis will try to remove keys
# according to the eviction policy selected (see maxmemory-policy).
#
# If Redis can't remove keys according to the policy, or if the policy is
# set to 'noeviction', Redis will start to reply with errors to commands
# that would use more memory, like SET, LPUSH, and so on, and will continue
# to reply to read-only commands like GET.
#
# This option is usually useful when using Redis as an LRU or LFU cache, or to
# set a hard memory limit for an instance (using the 'noeviction' policy).
#
# WARNING: If you have slaves attached to an instance with maxmemory on,
# the size of the output buffers needed to feed the slaves are subtracted
# from the used memory count, so that network problems / resyncs will
# not trigger a loop where keys are evicted, and in turn the output
# buffer of slaves is full with DELs of keys evicted triggering the deletion
# of more keys, and so forth until the database is completely emptied.
#
# In short... if you have slaves attached it is suggested that you set a lower
# limit for maxmemory so that there is some free RAM on the system for slave
# output buffers (but this is not needed if the policy is 'noeviction').
#
# maxmemory <bytes>

# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:
#
# volatile-lru -> Evict using approximated LRU among the keys with an expire set.
# allkeys-lru -> Evict any key using approximated LRU.
# volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU.
# volatile-random -> Remove a random key among the ones with an expire set.
# allkeys-random -> Remove a random key, any key.
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
# noeviction -> Don't evict anything, just return an error on write operations.
#
# LRU means Least Recently Used
# LFU means Least Frequently Used
#
# Both LRU, LFU and volatile-ttl are implemented using approximated
# randomized algorithms.
#
# Note: with any of the above policies, Redis will return an error on write
#       operations, when there are no suitable keys for eviction.
#
#       At the date of writing these commands are: set setnx setex append
#       incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
#       sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
#       zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
#       getset mset msetnx exec sort
#
# The default is:
#
# maxmemory-policy noeviction

# LRU, LFU and minimal TTL algorithms are not precise algorithms but approximated
# algorithms (in order to save memory), so you can tune it for speed or
# accuracy. For default Redis will check five keys and pick the one that was
# used less recently, you can change the sample size using the following
# configuration directive.
#
# The default of 5 produces good enough results. 10 Approximates very closely
# true LRU but costs more CPU. 3 is faster but not very accurate.
#
# maxmemory-samples 5

4

Niedawno zacząłem czytać o Redis, więc nie jestem pewien. Ale natknąłem się na kilka ciekawostek, które mogą być przydatne.

Oto fragment z http://antirez.com/post/redis-as-LRU-cache.html :

Innym sposobem wykorzystania Redis jako pamięci podręcznej jest dyrektywa maxmemory, funkcja, która umożliwia określenie maksymalnej ilości pamięci do wykorzystania. Po dodaniu nowych danych do serwera, a limit pamięci został już osiągnięty, serwer usunie niektóre stare dane usuwając klucz ulotny, czyli klucz z ustawionym EXPIRE (limitem czasu), nawet jeśli klucz jest nadal daleko wygasa automatycznie.

Ponadto Redis 2.0 ma tryb maszyny wirtualnej, w którym wszystkie klucze muszą mieścić się w pamięci, ale wartości rzadko używanych kluczy mogą znajdować się na dysku:


2

Jeśli zastanawiasz się, co tak naprawdę Redis (2.8) reaguje, gdy osiąga maksimum zdefiniowane w jego konfiguracji, wygląda to tak:

$ redis-cli
127.0.0.1:6379> GET 5
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
127.0.0.1:6379> SET 5 a
(error) OOM command not allowed when used memory > 'maxmemory'.

1

Niedawno doświadczyłem sytuacji braku wolnej pamięci i moja aplikacja zatrzymała się (zapisy nie były możliwe, odczyty były możliwe), uruchamianie skryptów PHP zatrzymało się w połowie drogi i musiałem zostać kill -9ręcznie (nawet po udostępnione).

Założyłem, że nastąpiła utrata danych (lub niespójność danych), więc zrobiłem flushdbi przywróciłem z kopii zapasowych. Wyciągnięta lekcja? Kopie zapasowe to twój przyjaciel.


-3

Redis nie jest pamięcią podręczną, taką jak memcached, domyślnie (gdzie maxmemory-policyparametr jest ustawiony na noeviction) wszystkie dane, które umieszczasz w redis, nie zostaną usunięte, jedynym wyjątkiem jest użycie EXPIRE.


2
Co więc robi, gdy zabraknie pamięci? Po prostu zapisze nowe dane na dysku, a nie w pamięci?
Cory,

1
Jest to (teraz) niepoprawne, Redis ma kluczowy mechanizm eksmisji, z kilkoma dostępnymi zasadami: redis.io/topics/lru-cache
LoicAG

@LoicAG: Wydaje mi się to całkowicie poprawne ... jeśli nie ma polityki dotyczącej wywłaszczania, Redis nie eksmituje żadnego klucza. I to dobrze: na przykład nie mogę sobie pozwolić na to, aby Redis samodzielnie pozbywał się kluczy.
Michael

@Cory: Jeśli istnieje polityka eksmisji, usunie ona istniejące klucze. Jeśli jednak nie ustawiłeś żadnych zasad eksmisji, powinien pojawić się błąd braku pamięci.
Michael

@Michael Przypuszczam, że to kwestia terminologii: zawsze obowiązuje zasada maxmemory, a domyślną wartością jest rzeczywiście „noeviction”; ale zasady „allkeys-lru” i „allkeys-random” usuwają klucze z całego zestawu, a inne („volatile- *”) wykluczają klucze z podzbioru kluczy, które mają zdefiniowaną wartość TTL.
LoicAG,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.