2011-10-26 16 views
11

Mi piacerebbe usare 2 cache - quella in memoria di default e una memcache, anche se in astratto non dovrebbe importare (credo) quale due.Come utilizzare più cache nelle guide? (per davvero)

Il valore predefinito in memoria è dove voglio caricare dati piccoli e che cambiano raramente. Ho usato la memoria fino ad oggi. Tengo un sacco di roba di tipo 'dati di dominio' dal database in là, ho anche alcuni piccoli dati da fonti esterne che aggiorno ogni 15 minuti - 1 ora.

Recentemente ho aggiunto memcache perché ora sto servendo alcune risorse più grandi. Un po 'più complesso di come sono entrato in questo, ma questi sono più grandi ~ kilobyte, relativamente piccoli in quantità (centinaia) e altamente memorizzabili nella cache - cambiano, ma un aggiornamento all'ora è probabilmente troppo. Questo set potrebbe aumentare, ma è condiviso su tutti gli host. I rinfreschi sono costosi.

La prima serie di dati è stato utilizzando la cache memoria predefinita per un po 'di tempo, ed è stato ben educati. Memcache è perfetto per il secondo set di dati.

Ho regolato memcache e funziona perfettamente per il secondo set di dati. Il problema è che a causa del mio codice esistente che è stato fatto "pensando" era nella memoria locale, sto facendo diversi viaggi su memcache per richiesta, il che sta aumentando la mia latenza.

Quindi, voglio utilizzare 2 cache. Pensieri?

(nota: memcache è in esecuzione su diversi computer rispetto al mio server. Anche se l'ho eseguito localmente, ho una flotta di host quindi non sarebbe locale a tutti. Inoltre, voglio evitare di aver bisogno solo per ottenere macchine più grandi Anche se probabilmente potrei risolvere questo problema aumentando la memoria e usando solo la memoria (i dati non sono poi così grandi), questo non risolve il problema man mano che scala, quindi sarà basta essere calci il barattolo.)

risposta

15

ActiveSupport :: cache :: MemoryStore è ciò che si desidera utilizzare. Rails.cache utilizza MemoryStore, FileStore o nel mio caso DalliStore :-)

È possibile avere un'istanza globale di ActiveSupport :: Cache :: MemoryStore e utilizzarlo o creare una classe con un modello singleton che trattiene questo oggetto (pulitore). Impostare Rails.cache l'altro negozio di cache e utilizzare questo Singleton per MemoryStore

Di seguito si riporta questa classe:

module Caching 
    class MemoryCache 
     include Singleton 

     # create a private instance of MemoryStore 
     def initialize 
     @memory_store = ActiveSupport::Cache::MemoryStore.new 
     end 

     # this will allow our MemoryCache to be called just like Rails.cache 
     # every method passed to it will be passed to our MemoryStore 
     def method_missing(m, *args, &block) 
     @memory_store.send(m, *args, &block) 
     end 
    end 
end 

Ecco come usarlo:

Caching::MemoryCache.instance.write("foo", "bar") 
=> true 
Caching::MemoryCache.instance.read("foo") 
=> "bar" 
Caching::MemoryCache.instance.clear 
=> 0 
Caching::MemoryCache.instance.read("foo") 
=> nil 
Caching::MemoryCache.instance.write("foo1", "bar1") 
=> true 
Caching::MemoryCache.instance.write("foo2", "bar2") 
=> true 
Caching::MemoryCache.instance.read_multi("foo1", "foo2") 
=> {"foo1"=>"bar1", "foo2"=>"bar2"} 
6

In un inizializzatore è possibile appena messo:

MyMemoryCache = ActiveSupport :: cache :: MemoryStore.new

Quindi è possibile utilizzarlo in questo modo:

MyMemoryCache.fetch('my-key', 'my-value') 

e così via.

Nota che, se è solo per l'ottimizzazione delle prestazioni (e dipende dal tempo di scadenza), potrebbe non essere una cattiva idea per disabilitarlo nel vostro ambiente di test, come segue:

if Rails.env.test? 
    MyMemoryCache = ActiveSupport::Cache::NullStore.new 
else 
    MyMemoryCache = ActiveSupport::Cache::MemoryStore.new 
end 

Rails fornisce già questo consentendo di impostare diversi valori config.cache_store nei propri inizializzatori dell'ambiente.

Problemi correlati