2013-05-30 11 views
15

Stiamo eseguendo un'applicazione Web e siamo passati da memcached a redis (2.4) per la memorizzazione nella cache. Ora siamo un po 'delusi dalle prestazioni dei redis. Redis è in esecuzione sullo stesso server e usiamo solo operazioni GET e SET molto semplici. Su alcune richieste che fanno un uso pesante dei valori memorizzati nella cache, abbiamo fino a 300 richieste GET per redis, ma quelle richieste richiedono fino a 150 ms. Abbiamo circa 200.000 chiavi attive e circa 1.000 richieste redis al secondo. Non ci sono problemi con il disco io, ram o cpu. A causa del nostro codice esistente non possiamo semplicemente raggruppare le richieste di redis insieme. Memcached è stato circa 4 volte più veloce. Quello che ci piace di redis, è che non abbiamo bisogno di alcun riscaldamento della cache, e in futuro potremmo usare funzionalità di datastore più avanzate. Ci aspettavamo che i redis funzionassero in modo simile a memcached. Quindi forse abbiamo perso qualcosa nella nostra configurazione, che è fondamentalmente la configurazione di default.Redis Ottimizzazione delle prestazioni

Conoscete le migliori pratiche per l'ottimizzazione delle prestazioni redis?

+0

Redis è in esecuzione sullo stesso server di cosa? Il client o quello in esecuzione memcached? 150 ms per una richiesta Redis suona come se si stesse scambiando lo swap/disco, non la memoria, o intendi 150 ms per tutte le 300 richieste? –

+0

È un'applicazione Web con circa 100 richieste di apache al secondo. Redis è in esecuzione sullo stesso host dell'applicazione Web stessa e sul server di database mysql, ma pianifichiamo di spostare presto l'apache su 3 server con carico bilanciato. Il server attuale ha circa 64 GB di RAM, il rosso richiede circa 100 MB. C'è abbastanza RAM gratis e nessun problema con cpu o io. Il server non si scambia su disco. E sì, intendo 150ms per 300 richieste, ma memcached ha impiegato solo 40ms nelle stesse condizioni. – ak2

+1

L'unica cosa che posso pensare è se si sta utilizzando una connessione condivisa a Redis per tutte le richieste invece di una per ogni richiesta web, si possono avere problemi di latenza con Redis, ma a 1000 richieste al secondo non si dovrebbe vedere quella cattiva latenza. Scusa, niente di veramente utile dalla mia direzione oggi :) –

risposta

21

Innanzitutto, è possibile leggere the Redis benchmark page. Fornisce un buon riassunto dei punti principali da verificare per regolare i Redis.

Anche supponendo che non si usi la pipeline, 300 GET in 150 ms non sono così efficienti. Significa che la latenza media è di 500 us. Tuttavia, in realtà dipende dalla dimensione dei tuoi oggetti. Oggetti più grandi, più latenza. Sulla mia vecchia scatola AMD da 2 GHz, posso misurare 150 latenze per piccoli oggetti (pochi byte).

Per controllare rapidamente la latenza media dell'istanza Redis, è possibile utilizzare:

$ redis-cli --latency 

essere sicuri di utilizzare una versione recente Redis (non 2.4) per ottenere questa opzione. Nota: 2.4 è piuttosto vecchio ora, usa Redis 2.6 - compila la tua versione Redis se necessario, è davvero semplice.

Per eseguire rapidamente un punto di riferimento per studiare la latenza, è possibile avviare:

$ redis-benchmark -q -n 10000 -c 1 -d average_size_of_your_objects_in_bytes 

Funziona con una connessione univoca e non pipelining, quindi la latenza può essere dedotto dalla produttività. Cerca di confrontare il risultato di questi benchmark con le cifre misurate con la tua applicazione.

Ci sono una serie di punti che si consiglia di controllare:

  • Quali libreria client Redis si usa? Con quale linguaggio di sviluppo? Per alcuni linguaggi di scripting, è necessario installare il modulo hiredis per ottenere un client efficiente.
  • La macchina è una macchina virtuale? Su quale sistema operativo?
  • Le connessioni a Redis sono persistenti? (cioè non dovresti connetterti/disconnetterti ad ogni richiesta HTTP del tuo server delle app).

Perché è meglio con memcached? Bene, una singola istanza memcached è sicuramente più scalabile e può essere più reattiva di una singola istanza Redis, poiché può essere eseguita su più thread. Redis è veloce, ma single-threaded: l'esecuzione di tutti i comandi è serializzata. Quindi, quando un comando è in corso per una connessione, tutti gli altri client devono attendere: una cattiva latenza su un determinato comando influirà anche su tutti i comandi in sospeso. Generalmente, a basse prestazioni, le prestazioni sono paragonabili.

A 1000 q/s (un throughput basso da Redis o memcached standard), direi che è più probabile che il problema sia sul lato client (ad es.scelta della libreria client, connessione/disconnessione, ecc ...), rispetto al server Redis stesso.

Infine, dovrei ricordare che se si genera un numero di query Redis per richiesta HTTP, considerare pipelining i comandi inviati a Redis il più lontano possibile. È davvero un punto chiave per sviluppare efficienti applicazioni Redis.

Se i server delle applicazioni si trovano nella stessa casella di Redis, è possibile utilizzare anche i socket di dominio unix anziché il loopback TCP per connettersi a Redis. Migliora leggermente le prestazioni (fino al 50% in più di throughput quando il pipeline NON è utilizzato).

+0

"l'esecuzione di tutti i comandi è serializzata": daresti maggiori dettagli su questa affermazione? a me sembra che tu stia dicendo che mentre un comando è in esecuzione non possono essere eseguiti altri comandi, anche su altre connessioni. è questo il modo in cui redis raggiunge il comando di atomicità? – akonsu

+0

Sì esattamente. Vedi http://stackoverflow.com/questions/10489298/redis-is-single-threaded-then-how-do-it-do-concurrent-io/10495458#10495458 –

+0

Vedi anche http://redis.io/topics /latenza –

0

Verificare se redis utilizza la memoria di scambio OS. Se è così, ciò aggiungerà la latenza. Per scoprire, cercare "Latenza indotta dallo scambio" qui: http://redis.io/topics/latency

Se l'hardware del server è compatibile con NUMA, è meglio avviare redis-server con numactl. Non dimenticare di disattivare la modalità di recupero zona (vm.zone_reclaim_mode = 0) in sysctl se stai iniziando con redis-server con NUMA.

0

Provare a scrivere la richiesta 300 GET in uno script Lua. Dovrebbe funzionare più velocemente perché si risparmia tempo sul touch allo stack TCP/IP anche se il codice client è in esecuzione localmente su Redis.

Problemi correlati