2011-12-28 8 views
27

Potrei essere completamente fuori, ma la mia comprensione di come gli archivi di cache funzionavano prima che iniziassero ad aggiungere funzionalità di persistenza, è che gli elementi sarebbero scaduti in base al loro ttl. E se il negozio ha iniziato a riempire la RAM disponibile, ognuno di loro avrebbe i propri algoritmi per lo scadere delle chiavi meno "importanti" nel negozio.Come funziona Redis quando la RAM inizia a riempirsi?

Ora ho letto che Redis ha caratteristiche di persistenza. Ma puoi spegnerli. Supponendo di disattivare la persistenza, cosa succede quando la RAM si riempie? In che modo Redis decide cosa deve scadere?

Mi aspetto di avere molti dati senza TTL e voglio assicurarmi che sia sicuro lasciare che Redis capisca cosa deve scadere.

risposta

35

Non credo che la questione è legata alla gestione della memoria virtuale, ma di più la scadenza degli elementi di Redis, che è un argomento totalmente diverso.

Contrariamente a memcached, Redis non è solo una cache. Quindi l'utente dovrebbe scegliere la politica di sfratto dell'articolo usando vari meccanismi. Puoi sfrattare tutti i tuoi articoli o solo una parte di essi.

Il criterio generale deve essere selezionato nel file di configurazione con i parametri maxmemory e maxmemory-politica, misura descritto di seguito:

# Don't use more memory than the specified amount of bytes. 
# When the memory limit is reached Redis will try to remove keys with an 
# EXPIRE set. It will try to start freeing keys that are going to expire 
# in little time and preserve keys with a longer time to live. 
# Redis will also try to remove objects from free lists if possible. 
# 
# If all this fails, Redis will start to reply with errors to commands 
# that will use more memory, like SET, LPUSH, and so on, and will continue 
# to reply to most read-only commands like GET. 
# 
# WARNING: maxmemory can be a good idea mainly if you want to use Redis as a 
# 'state' server or cache, not as a real DB. When Redis is used as a real 
# database the memory usage will grow over the weeks, it will be obvious if 
# it is going to use too much memory in the long run, and you'll have the time 
# to upgrade. With maxmemory after the limit is reached you'll start to get 
# errors for write operations, and this may even lead to DB inconsistency. 
# 
maxmemory <bytes> 

# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory 
# is reached? You can select among five behavior: 
# 
# volatile-lru -> remove the key with an expire set using an LRU algorithm 
# allkeys-lru -> remove any key accordingly 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 all the kind of policies, Redis will return an error on write 
#  operations, when there are not suitable keys for eviction. 
# 
#  At the date of writing this 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 

# LRU and minimal TTL algorithms are not precise algorithms but approximated 
# algorithms (in order to save memory), so you can select as well the sample 
# size to check. For instance for default Redis will check three keys and 
# pick the one that was used less recently, you can change the sample size 
# using the following configuration directive. 
# 
maxmemory-samples 3 

Poi singolo elemento di scadenza può essere impostata utilizzando i seguenti comandi: EXPIRE EXPIREAT La proprietà di scadenza per elemento è utile con le politiche volatile- *. La scadenza può essere rimossa anche utilizzando PERSIST.

La proprietà di scadenza aggiunge un leggero sovraccarico di memoria, quindi dovrebbe essere utilizzato solo se necessario.

Infine, vale la pena ricordare che una parte di un oggetto non può essere scaduta, solo l'intero oggetto stesso. Ad esempio, un intero elenco o set corrispondente a un tasto può essere scaduto, ma non possono essere elencati singoli elenchi o elementi.

+0

Eccellente, grazie. Quindi l'algoritmo defaul LRU è esattamente quello che volevo. Basta impostarlo in modo che sia un server 'stato'. – joedevon

2

Leggere il capitolo Virtual Memory dalla documentazione di Redis. La parte rilevante:

L'impostazione L'impostazione vm-max-memory vm-max-memoria specifica quanta memoria Redis è libero di utilizzare prima di iniziare valori che scambiano su disco.

Fondamentalmente se questo limite di memoria non viene raggiunto, nessun oggetto sarà scambiato, Redis funzionerà con tutti gli oggetti in memoria come al solito. Tuttavia, una volta raggiunto questo limite, vengono sostituiti abbastanza oggetti per restituire la memoria appena sotto il limite.

Gli oggetti scambiati sono principalmente quelli con la "maggiore" età (ovvero il numero di secondi da quando non sono stati utilizzati), ma la "sostituibilità" di un oggetto è anche proporzionale al logaritmo della sua dimensione in memoria. Quindi, anche se gli oggetti più vecchi sono preferiti, gli oggetti più grandi vengono scambiati per primi quando hanno circa la stessa età.

ATTENZIONE: Perché chiavi non possono essere scambiati fuori, Redis non sarà in grado di onorare l'impostazione se le chiavi solo utilizzano più spazio rispetto al limite vm-max-memoria.

Il valore migliore per questa impostazione è RAM sufficiente per contenere il "working set" dei dati. In termini pratici, basta dare a Redis più memoria possibile, e lo scambio funzionerà meglio.

UPDATE Per quanto riguarda Redis 2.4 (sembra che la documentazione ufficiale in loco Redis non viene aggiornato a questa versione), non è raccomandato l'uso di VM.

redis.conf dice:

### WARNING! Virtual Memory is deprecated in Redis 2.4 
### The use of Virtual Memory is strongly discouraged. 
+0

Dato che la memoria virtuale è deprecata, qual è il modo migliore per utilizzare la memoria su disco quando si verifica un limite di memoria RAM? – harsimranb

+1

@harsimranb no. Se arrivi al punto in cui hai bisogno del disco, hai utilizzato in modo errato Redis (o dovresti aumentare la RAM, dipende dal tuo caso d'uso). –

2

O impostare TTL (e lasciare che Redis gestisca la scadenza per te) o pubblicare i tuoi articoli con i tuoi dati di invecchiamento, magari memorizzati come tuple ZSET (timestamp, chiave) da cui è possibile eseguire la pulizia della cache in base a i tuoi bisogni

8

Didier ha ragione a indicare come questo deve essere fatto. Basta indicare alcuni elementi aggiuntivi (uno dei quali sembra essere omessi dal suo incarico):

  1. Specifica la dimensione massima di memoria a prendere la maggior parte della memoria disponibile su quel nodo (lasciare un po 'per il sistema operativo e altri processi e qualche buffer). Ciò assicurerà che il contenuto non sia mai impaginato e in quanto tale le operazioni siano VELOCI.
    1. Se non si impostano le chiavi TTL/in scadenza nell'applicazione, è importante utilizzare l'approccio "allkeys-lru". Altrimenti, Redis non scadrà nulla (perché nessuna delle chiavi è volatile) e inizierai a ricevere errori una volta esaurita la memoria - in pratica non sarai più in grado di fare altre operazioni.
    2. Quando si utilizza il LRU per la rimozione di chiavi, è importante impostare le seguenti impostazioni:

maxmemory-campioni 10

Questo è il numero di campioni che REDIS avrà quindi rimuovere la chiave LRU tra questi. Il valore predefinito è 3, ma per tutti gli scopi pratici è troppo basso - e potrebbe significare che le chiavi più vecchie potrebbero ancora essere sopravvissute. Impostarlo troppo alto sarà un overhead per Redis. Si consiglia di sperimentare con questa impostazione un po 'prima di impostarlo. Stiamo usando un valore di 10.

+0

Grazie per l'utile aggiunta. – joedevon

+0

Hai perfettamente ragione @Gur, l'ho appena testato con diversi valori di maxmemory e maxmemory-policy. –

Problemi correlati