2012-02-03 3 views
18

Il mio modello ha entità diverse che vorrei calcolare una volta come i dipendenti di un'azienda. Per evitare di ripetere la stessa query più volte, l'elenco calcolato viene salvato in Memcache (durata = 1 giorno). Il problema è che a volte l'app mi dà un errore sul numero di byte memorizzati in Memcache di quanto consentito:Evitare Memcache limite "1000000 byte di lunghezza" sui valori

Values may not be more than 1000000 bytes in length; received 1071339 bytes 

Memorizza un elenco di oggetti qualcosa che dovresti fare con Memcache? In tal caso, quali sono le migliori pratiche per evitare l'errore sopra riportato? Attualmente sto tirando 1000 oggetti. Limite i valori a < 200? Controllare la dimensione di un oggetto in memoria non sembra un'idea troppo buona perché probabilmente vengono elaborati (serializzati o qualcosa di simile) prima di andare in Memcache.

+0

La prima volta che ho letto il titolo della domanda ho pensato che Memcache qui può solo memorizzare 1M come in 1 milione di valori.È possibile modificare il titolo in "Evitare il limite di valori di Memcache 1 MB"? –

risposta

28

David, tu non dici quale lingua usi, ma in Python puoi fare la stessa cosa che Ibrahim suggerisce di usare pickle. Tutto ciò che devi fare è scrivere due piccole funzioni di supporto che leggono e scrivono un oggetto di grandi dimensioni su memcache. Ecco un (non testata) schizzo:

def store(key, value, chunksize=950000): 
    serialized = pickle.dumps(value, 2) 
    values = {} 
    for i in xrange(0, len(serialized), chunksize): 
    values['%s.%s' % (key, i//chunksize)] = serialized[i : i+chunksize] 
    return memcache.set_multi(values) 

def retrieve(key): 
    result = memcache.get_multi(['%s.%s' % (key, i) for i in xrange(32)]) 
    serialized = ''.join([v for k, v in sorted(result.items()) if v is not None]) 
    return pickle.loads(serialized) 
+1

Grazie Guido per lo sketchout, mi dà la base giusta per andare avanti. –

+0

Ho avuto un problema simile a @Nikolay, la linea pickle.loads non funzionava perché i valori tornavano in ordine diverso da quello in cui erano stati decapitati. Ho usato serialized_data = [result [chiave] per la chiave in chiave se la chiave in risultato e risultato [chiave] non è nessuno] per risolvere il mio problema. – John

+0

Non riesco a comprendere completamente questo codice. Posso chiedere a qualcuno di spiegare cosa fa passo-passo? – puoyaahhh

8

Memorizzo spesso oggetti con dimensioni di diversi megabyte sul memcache. Non posso commentare se questa è una buona pratica o no, ma la mia opinione è che a volte abbiamo semplicemente bisogno di un modo relativamente veloce per trasferire megabyte di dati tra le istanze del nostro motore di app.

Dal momento che sto usando Java, ciò che ho fatto è serializzare i miei oggetti grezzi usando il serializzatore di Java, producendo una matrice serializzata di byte. Poiché la dimensione dell'oggetto serializzato è ora nota, potrei tagliare blocchi di matrici di byte da 800 KB. Quindi incapsula l'array di byte in un oggetto contenitore e lo memorizzo invece degli oggetti non elaborati.

Ogni oggetto contenitore può avere un puntatore alla successiva chiave memcache in cui posso recuperare il successivo blocco di array di byte o null se non ci sono più blocchi che devono essere recuperati dal memcache. (Ad esempio, proprio come una lista collegata), quindi ri-unisco i blocchi di matrici di byte in un grande array di byte e lo deserializza utilizzando il deserializzatore di Java.

+0

Grazie Ibrahim, è sicuramente una soluzione creativa. Sto cercando di vedere quali più semplici approcci standard ci sono per memorizzare gli elenchi di oggetti in memcache. –

5

Hai sempre bisogno di accedere a tutti i dati che memorizzi? In caso contrario, trarrete vantaggio dal partizionamento del set di dati e dall'accesso solo alla parte dei dati necessari.

Se si visualizza un elenco di 1000 dipendenti, è probabile che lo si debba impaginare. Se impagini allora puoi sicuramente partizionare.

È possibile creare due elenchi del set di dati: un accendino con solo le informazioni essenziali che possono essere contenute in 1 MB e un altro elenco suddiviso in più parti con informazioni complete. Sulla light list sarete in grado di applicare le operazioni più essenziali per esempio filtrando attraverso il nome o l'impaginazione dei dipendenti. E poi quando è necessario caricare il set di dati pesante, sarai in grado di caricare solo le parti di cui hai veramente bisogno.

Ma bene questi suggerimenti richiedono tempo per implementare. Se riesci a vivere con il tuo design attuale, dividi l'elenco in grumi di ~ 300 elementi o qualsiasi numero sia sicuro e caricali tutti e unisci.

+1

Spot on ideas Skirmantas! Hai ragione che impiegheranno dei tempi di implementazione, ma vale la pena esaminarli. Grazie per aver condiviso il tuo consiglio. –

3

Se si sa quanto grande sarà gli oggetti è possibile utilizzare l'opzione memcached per consentire oggetti più grandi:

memcached -I 10m 

Questo permetterà oggetti fino a 10 MB.

+2

Grazie. Utile sapere, ma sembra che questa non sia un'opzione su AppEngine che viene taggata come piattaforma della domanda originale: https://cloud.google.com/appengine/docs/python/memcache/#Python_Limits – Michael