Evitar el límite de Memcache “1000000 bytes de longitud” en los valores

Mi modelo tiene diferentes entidades 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:

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

¿Está almacenando una lista de objetos algo 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.

David, no dices qué idioma usas, pero en Python puedes hacer lo mismo que Ibrahim sugiere usar Pickle. Todo lo que necesita hacer es escribir dos pequeñas funciones auxiliares que leen y escriben un objeto grande en Memcache. Aquí hay un boceto (no probado):

 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) 

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 procesar usando el serializador de Java, produciendo una serie 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 de 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, al igual que una lista vinculada), luego vuelvo a fusionar los fragmentos de matrices de bytes en una matriz de bytes grande y la deserializo utilizando el deserializador de Java.

¿Siempre necesita 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 la 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 bueno, 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.

Si sabe qué tan grandes serán los objetos, puede usar la opción de memcached para permitir objetos más grandes:

 memcached -I 10m 

Esto permitirá objetos de hasta 10MB.