2010-10-23 16 views
5

Sto spostando un'applicazione web di Google App Engine all'esterno del "cloud" in un framework Web standard (webpy) e vorrei sapere come implementare una funzione memcache disponibile su Gae.Memcache minuscoli fatti in casa

Nella mia app uso solo questa cache per archiviare una serie di dati recuperati da una API remota ogni X ore; in altre parole non sottolineo troppo questo cache.

ho ingenuamente implementato qualcosa di simile:

class TinyCache(): 
    class _Container(): 
     def __init__(self, value, seconds): 
      self.value = value 
      self.cache_age = datetime.now() 
      self.cache_time = timedelta(seconds = seconds) 
     def is_stale(self): 
      return self.cache_age + self.cache_time < datetime.now() 

    def __init__(self): 
     self.dict_cache={} 

    def add(self, key, value, seconds = 7200): 
     self.dict_cache[key] = self._Container(value, seconds) 

    def get(self, key): 
     if key in self.dict_cache: 
      if self.dict_cache[key].is_stale(): 
       del self.dict_cache[key] 
       return None 
      else: 
       return self.dict_cache[key].value 
     else: 
      return None 

Un utilizzo tipico potrebbe essere:

data = tinycache.get("remote_api_data") 
if data is not None: 
    return data 
else: 
    data = self.api_call() 
    tinycache.add("remote_api_data", data, 7200) 
    return data 

Come potrei migliorare?
Devo renderlo thread-safe?

+1

La maggior parte del supporto "standard web framework" che si collega a un back-end cache ... Perché non implementare un wrapper che tenta il backend GAE, e se non è disponibile, torna a 'memcached' (o all'API di Django Cache, se ti capita di usare Django). Avete accesso a un'istanza di memcache "out of the cloud"? –

+0

No, memcached non è un'opzione perché non è supportato dal mio provider. Inoltre, anche il backend GAE non è un'opzione ... perché ho bisogno di un viaggio così lungo per qualcosa che deve essere veloce? – systempuntoout

risposta

2

Mi sembra che la cache possa crescere in modo inefficiente dal momento che manterrà le voci che vengono utilizzate raramente. Perché sembra che le voci nella cache non vengano rimosse a meno che non venga richiesta un'operazione get per una chiave specifica.

Se si vuole migliorare la cache mi piacerebbe aggiungere le seguenti due funzioni semplici:

  1. quando un elemento viene richiesto avrei riavviare seconds al valore iniziale. Quindi per mantenere gli elementi che il tuo sistema usa spesso.
  2. Implementare in un thread separato un meccanismo per attraversare la cache ed eliminare voci troppo vecchie.

è anche possibile ottenere alcune idee da questo Fixed size cache

cura

Ho appena trovato questa ricetta, è super-cool. Fondamentalmente è possibile racchiudere con i decoratori di funzioni la logica che si desidera memorizzare nella cache. Qualcosa di simile:

@lru_cache(maxsize=20) 
def my_expensive_function(x, y): 
    # my expensive logic here 
    return result 

Questi LRU and LFU cache decorator decoratori realizzerà per voi la logica cache. Meno recente utilizzato (LRU) o Meno frequentemente utilizzato (LFU) (vedere Cache_algorithms per riferimento su questi)

+0

nice points, grazie – systempuntoout

+0

@systempuntoout appena modificato con un'altra soluzione basata su decoratori di funzioni. –

+0

In realtà ho già una cache LRU sul mio progetto. Quello di cui ho veramente bisogno è una cache per gli articoli che scade nel tempo. – systempuntoout

0

Nella mia app uso solo questa cache per archiviare una serie di dati recuperati da un'API remota ogni X ore; in altre parole non sottolineo troppo questo cache.

...

Come potrei migliorare?

Se il codice funziona per te, perché preoccuparsi?

Tuttavia, come richiesto esplicitamente per i commenti, cerco comunque di aggiungere le mie idee. A me sembra che si possa usare una memoria tradizionale come i file o un database per archiviare i dati poiché vengono aggiornati periodicamente. In molti casi si ha solo bisogno di una pre-elaborazione (potenzialmente costosa), quindi si potrebbe essere in grado di concentrarsi sul lavoro una sola volta e semplicemente memorizzare i dati in un modulo in modo che l'accesso/consegna al client sia veloce.

Vantaggi:

  • semplici
  • problemi con più processi (ad esempio FastCGI)
  • stampa ridotto piede memoria

Devo rendere thread-safe?

Questo dipende molto dal modello di utilizzo. Comunque dalla tua API immagino che non sia realmente necessario quando calcoli un valore due volte (caso peggiore).