2012-02-03 22 views
18

Mi modelo tiene entidades diferentes que me gustaría calcular una vez como los empleados de una empresa. Para evitar hacer la misma consulta una y otra vez, la lista calculada se guarda en Memcache (duración = 1 día). El problema es que la aplicación a veces me da un error de que hay más bytes almacenados en Memcache de lo permitido:Evitar el límite de Memcache "1000000 bytes de longitud" en los valores

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

¿Está almacenando una lista de objetos que debería estar haciendo con Memcache? De ser así, ¿cuáles son las mejores prácticas para evitar el error anterior? Actualmente estoy tirando de 1000 objetos. ¿Limita los valores a < 200? Comprobar el tamaño de un objeto en la memoria no parece una idea demasiado buena porque probablemente se procesen (en serie o algo así) antes de entrar en Memcache.

+0

La primera vez que leí el título de la pregunta, pensé que Memcache aquí solo puede almacenar 1M como en 1 millón de valores.¿Se puede cambiar el título a "Evitar el límite de valores de Memcache 1MB"? –

Respuesta

28

David, usted no dice qué idioma usa, pero en Python puede hacer lo mismo que Ibrahim sugiere utilizar pickle. Todo lo que necesita hacer es escribir dos pequeñas funciones auxiliares que leen y escriben un objeto grande en Memcache. He aquí un (no probado) boceto:

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

Gracias a Guido por el boceto, me da la base adecuada para seguir adelante. –

+0

Tuve un problema similar al de @Nikolay, la línea pickle.loads estaba fallando porque los valores volvían en un orden diferente del que se habían guardado en escabeche. Utilicé serialized_data = [result [key] para key in keys si key in result y result [key] no es None] para resolver mi problema. – John

+0

Tengo problemas para entender este código por completo. ¿Puedo pedirle a alguien que me explique lo que hace paso a paso? – puoyaahhh

8

Con frecuencia almaceno objetos con el tamaño de varios megabytes en el Memcache. No puedo comentar si esta es una buena práctica o no, pero mi opinión es que a veces simplemente necesitamos una forma relativamente rápida de transferir megabytes de datos entre las instancias de nuestros motores de aplicaciones.

Dado que estoy usando Java, lo que hice fue serializar mis objetos sin formato usando el serializador de Java, produciendo una matriz serializada de bytes. Dado que ahora se conoce el tamaño del objeto serializado, podría cortar en fragmentos de matrices de bytes de 800 KB. Luego, encapsulo la matriz de bytes en un objeto contenedor y almaceno ese objeto en lugar de los objetos brutos.

Cada objeto contenedor podría tener un puntero a la siguiente clave de Memcache donde podría obtener el siguiente fragmento de matriz de bytes, o nulo si no hay más fragmentos que deban recuperarse de Memcache. (es decir, como una lista vinculada), luego vuelvo a fusionar los fragmentos de matrices de bytes en una matriz de bytes grande y lo deserializo utilizando el deserializador de Java.

+0

Gracias Ibrahim, definitivamente es una solución creativa. Estoy buscando ver qué más simples son los enfoques más estándar para almacenar listas de objetos en Memcache. –

5

¿Siempre tiene que acceder a todos los datos que almacena? De lo contrario, se beneficiará al particionar el conjunto de datos y acceder solo a la parte de los datos que necesita.

Si muestra una lista de 1000 empleados probablemente lo va a paginar. Si paginas, definitivamente puedes dividir.

Puede hacer dos listas de su conjunto de datos: una más liviana con solo la información más esencial que puede caber en 1 MB y otra lista que se divide en varias partes con información completa. En la lista de luces, podrá aplicar las operaciones más esenciales, por ejemplo, filtrar a través del nombre o la paginación de los empleados. Y luego, cuando sea necesario, cargue el conjunto de datos pesados, podrá cargar solo las piezas que realmente necesite.

Pero bien estas sugerencias toman tiempo para implementarse. Si puede vivir con su diseño actual, simplemente divida su lista en grumos de ~ 300 elementos o el número que sea seguro y cárguelos y fusione.

+1

Spot on ideas Skirmantas! Tienes razón, necesitarán tiempo de implementación, pero vale la pena investigarlo. Gracias por compartir tu consejo. –

3

Si sabe qué tan grande serán los objetos se puede utilizar la opción de memcached para permitir que objetos más grandes:

memcached -I 10m 

Esto permitirá a los objetos de hasta 10 MB.

+2

Gracias. Es útil saberlo, pero parece que esta no es una opción en AppEngine etiquetada como la plataforma de la pregunta original: https://cloud.google.com/appengine/docs/python/memcache/#Python_Limits – Michael

Cuestiones relacionadas