2012-02-05 37 views
6

APC le permite almacenar datos dentro de las claves, pero no puede agrupar estas claves.Grupos clave con memoria caché APC

Así que si quiero tener un grupo llamado "artículos", y dentro de este grupo tendría claves que toman la forma de la ID del artículo. No puedo hacer esto fácilmente.

articles -> 5 -> cached data 
     -> 10 -> cached data 
     -> 17 -> cached data 

     ... 

pude prefijar la tecla con el nombre de "grupo" como:

article_5 -> cached data 
article_10 -> cached data 
article_17 -> cached data 

... 

Pero esto hace que sea imposible eliminar todo el grupo si quiero :(

Un trabajo La solución sería almacenar matrices multidimensionales (esto es lo que estoy haciendo ahora), pero no creo que sea bueno porque cuando quiero acceder/eliminar datos almacenados en caché, necesito obtener todo el grupo primero. Por lo tanto, si el grupo tiene un trillón de artículos en el que puede imaginar qué tipo de matriz voy a iterar y se arqueando

¿Tiene mejores ideas sobre cómo podría lograr lo del grupo?


edición: encontró otra solución, no está seguro de si es mucho mejor porque no sé qué tan confiable es todavía. Estoy agregando una clave especial llamada __paths que es básicamente una matriz multidimensional que contiene las rutas de clave prefijadas completas para todas las otras entradas en la memoria caché. Y cuando solicito o elimino la caché, uso esta matriz como referencia para encontrar rápidamente la clave (o grupo de claves) que necesito eliminar, para no tener que almacenar matrices e iterar a través de todas las claves ...

Respuesta

18

Sobre la base de sus observaciones, miré a la implementación subyacente C del modelo de almacenamiento en caché APC 's (apc_cache.c) para ver qué podía encontrar.

La fuente corrobora sus observaciones de que no existe estructura de agrupación en el almacén de datos de respaldo, de modo que cualquier colección de objetos agrupada libremente tendrá que hacerse en función de alguna restricción de espacio de nombres o una modificación de la capa de caché. Esperaba encontrar alguna puerta trasera confiando en el encadenamiento de claves a través de una lista vinculada, pero desafortunadamente parece que las colisiones se reconcilian mediante una reasignación directa de la ranura que colisiona en lugar de chaining.

Además de confundir este problema, APC parece utilizar un modelo de caché explícito para las entradas de usuario, lo que evita que envejezcan. Por lo tanto, the solution Emil Vikström provided que se basa en el modelo LRU de memcached, desafortunadamente, no funcionará.

sin modificar el código fuente de la misma APC, esto es lo que yo haría:

  1. definir una restricción de espacio de nombres que sus entradas se ajustan a. Como definió originalmente, esto sería algo así como article_ antes de cada una de sus entradas.

  2. Defina un por separado lista de elementos en este conjunto. Efectivamente, este sería el esquema 5, 10 y 17 que describió anteriormente, pero en este caso, podría usar algún tipo numérico para hacerlo más eficiente que almacenar un montón de valores de cadena.

  3. definir una interfaza la actualización de este conjunto de punteros y la conciliación de ellos con la memoria caché de soporte, incluyendo (como mínimo) los métodos insert, delete, y clear. Cuando se llama al clear, recorra cada uno de sus punteros, reconstruya la clave que utilizó en el almacén de datos de respaldo y vacíe cada uno de su caché.

Lo que estoy abogando por que aquí es un objeto bien definido que realiza las operaciones que buscan eficazmente. Esto se escala linealmente con el número de entradas en su subcaché, pero debido a que está utilizando un tipo numérico para cada elemento, necesitaría más de 100 millones de entradas más o menos antes de comenzar a experimentar un dolor de memoria real con una restricción de, por ejemplo, unos cientos de megabytes.


Tamas Imrei golpearme a suggesting an alternate strategy yo ya estaba en el proceso de documentación, pero esto tiene algunos defectos importantes que me gustaría hablar.

Tal como se define en el código de soporte C, APCIterator es una operación de tiempo lineal sobre los datos del sistema completo de al realizar búsquedas (utilizando su constructor, public __construct (string $cache [, mixed $search = null ...]])).

Esto es completamente indeseable en el caso en que los elementos de respaldo que está buscando representan un pequeño porcentaje de sus datos totales, ya que caminaría cada elemento de su caché para encontrar los que desea. Citando apc_cache.c:

/* {{{ apc_cache_user_find */ 
apc_cache_entry_t* apc_cache_user_find(apc_cache_t* cache, char *strkey, \ 
    int keylen, time_t t TSRMLS_DC) 
{ 
    slot_t** slot; 
    ... 
    slot = &cache->slots[h % cache->num_slots]; 
    while (*slot) { 
     ... 
     slot = &(*slot)->next; 
    } 
} 

Por lo tanto, yo recomendaría más fuertemente utilizando una solución de agrupación virtual eficiente, basada en el puntero a su problema lo que he descrito anteriormente.Aunque, en el caso de que esté severamente restringido por la memoria, el enfoque del iterador puede ser el más correcto para conservar tanta memoria como sea posible a expensas del cálculo.

La mejor de las suertes con su aplicación.

+1

¡Buen trabajo! Recomiendo leer esta publicación. –

+1

@ EmilVikström ¡Gracias! Estoy feliz de que mi trabajo haya sido perspicaz. – MrGomez

4

he tenido este problema una vez con memcached y yo resuelto mediante el uso de un número de versión en mis llaves, así:

version -> 5 
article_5_5 -> cached data 
article_10_5 -> cached data 
article_17_5 -> cached data 

Sólo cambia el número de versión y el grupo será efectiva "ido"!

memcached utiliza una política de uso mínimo reciente para eliminar los datos antiguos, por lo que el grupo versionado anterior se eliminará de la memoria caché cuando sea necesario. No sé si APC tiene la misma función.


Según MrGomez esto no está funcionando para APC. Lea su publicación y tenga en cuenta mi publicación solo para otros sistemas de caché que utilizan una política de uso mínimo reciente (no APC).

+0

APC no tiene una política de LRU, pero apc_add permite un TTL, Time To Live. Sin embargo, Memcache sería una mejor opción en este caso para este tipo de datos, debido a su LRU. –

3

Usted puede utilizar el APCIterator class que parece existe especialmente para este tipo de tareas:

clase

El APCIterator hace que sea más fácil para iterar a través de grandes cachés de APC. Esto es útil ya que permite iterar sobre grandes cachés de los pasos ...

1

Desafortunadamente, APC no puede hacer esto. Me deseé lo suficiente como para poder hacerlo. Entonces busqué alternativas.

Zend_Cache tiene una forma interesante de hacerlo, pero simplemente utiliza cachés para almacenar en caché la información de etiquetado. Es un componente que puede usar back-end (como apc).

Si quiere dar un paso más, puede instalar Redis. Este tiene todo lo que se incluye de forma nativa y algunas otras características realmente interesantes. Esta sería probablemente la solución más limpia para ir. Si fue capaz de usar APC, también debería poder usar Redis.

Cuestiones relacionadas