2008-11-27 17 views
12

Usamos Memcache básicamente como un pensamiento posterior para simplemente almacenar en caché los resultados de la consulta.Patrones de diseño de Memcache de PHP

La invalidación es una pesadilla debido a la forma en que se implementó. Desde entonces aprendimos algunas técnicas con Memcache a través de la lectura de la lista de correo, por ejemplo, el truco para permitir la invalidación grupal de un grupo de claves. Para aquellos que lo saben, omita el siguiente párrafo ..

Para aquellos que no saben y están interesados, el truco es agregar un número de secuencia a sus claves y almacenar ese número de secuencia en Memcache. Luego, cada vez que haces tu "obtener", tomas el número de secuencia actual y construyes tus llaves alrededor de eso. Luego, para invalidar todo el grupo, simplemente incrementa ese número de secuencia.

De todos modos, actualmente estoy revisando nuestro modelo para implementar esto.

Mi pregunta es ..

no sabíamos acerca de este patrón, y estoy seguro de que hay otros que no conocemos. He buscado y no he podido encontrar ningún patrón de diseño en la web para implementar Memcache, mejores prácticas, etc.

¿Alguien me puede indicar algo como esto o simplemente escribir un ejemplo? Me gustaría asegurarme de no cometer un error de principiante en nuestra nueva refactorización.

+0

Ver este hilo sobre el mismo tema http://stackoverflow.com/questions/276709/design-pattern-for-memcached-data-caching –

Respuesta

15

Un punto para recordar con el almacenamiento en memoria caché de objetos es que es solo eso: un caché de objetos/estructuras complejas. Muchas personas cometen el error de presionar sus cachés para realizar consultas sencillas y eficientes, lo que implica la sobrecarga de una comprobación de caché, cuando la base de datos hubiera obtenido el resultado mucho más rápido.

Este consejo es uno que me he tomado en serio desde que me lo enseñaron; saber cuándo no almacenar en caché, es decir, cuando la sobrecarga anula los beneficios percibidos. Sé que no responde la pregunta específica aquí, pero pensé que valía la pena señalarlo como una pista general.

+0

Gracias Rob muy buen punto. –

6

Lo que rob dice es un buen consejo. Según mi experiencia, existen dos formas comunes de identificar e invalidar etiquetas: identificación única e identificación basada en etiquetas. Los que se combinan generalmente para formar una solución completa en la que:

registro
  1. Una caché se le asigna un identificador único (que por lo general depende de alguna manera en los datos que se almacena en caché) y opcionalmente cualquier número de etiquetas.
  2. Los registros de caché se recuperan mediante su identificador único.
  3. Los registros de caché se pueden invalidar por su identificador único (uno a la vez) o por cualquier etiqueta con la que se etiqueten (posiblemente invalidando varios registros al mismo tiempo).

Esto es relativamente simple de implementar y generalmente funciona muy bien. Todavía tengo que encontrarme con un sistema que necesita más, aunque es probable que existan algunos casos extremos que requieren soluciones específicas.

+2

¿Cómo se implementa el etiquetado? ¿Estás utilizando esta http://code.google.com/p/memcached-tag/ memcached hackeada o lo estás haciendo en tu aplicación? Puede publicar un ejemplo? –

+1

Estoy usando algo similar a cómo se implementa Zend_Cache. Puede leer sobre esto aquí - http://framework.zend.com/manual/en/zend.cache.theory.html#zend.cache.tags y verificar la fuente para la implementación real –

+1

La implementación de la invalidación de la etiqueta Zend_Cache es extremadamente lento, ya que lee todos los archivos para verificar las etiquetas. (al menos en las versiones de Zend Framework 1) –

3

Utilizo el componente Zend Cache (no necesita usar todo el framework solo las cosas de zend cache si lo desea). Extrae algunas de las cosas del almacenamiento en caché (admite caché de agrupación mediante 'etiquetas', aunque esa función no es compatible con el back-end de Memcache. Lancé mi propio soporte para 'etiquetas' con relativa facilidad).Por lo que el patrón de uso para funciones que acceden a la memoria caché (en general, en mi modelo) es:

public function getBySlug($ignoreCache = true) 
{ 
    if($ignoreCache || !$result = $this->cache->load('someKeyBasedOnQuery')) 
    { 
     $select = $this->select() 
       ->where('slug = ?', $slug); 
     $result = $this->fetchRow($select); 

     try 
     { 
      $this->cache->save($result,'someKeyBasedOnQuery'); 
     } 
     catch(Zend_Exception $error) 
     { 
      //log exception 
     } 
    } 
    else 
    { 
     $this->registry->logger->info('someKeyBasedOnQuery came from cache'); 
    } 
    return $result; 

} 

basando la clave de caché en un hash de la consulta significa que si otro desarrollador no pasa por mis modelos o utiliza otra función en otro lugar que hace lo mismo que todavía se saca de la memoria caché. En general, etiqueto el caché con un par generar etiqueta (el nombre de la tabla es uno y el otro es el nombre de la función). De manera predeterminada, nuestro código invalida al insertar, eliminar y actualizar los elementos en la memoria caché con la etiqueta de la tabla. En general, el almacenamiento en caché es bastante automático en nuestro código base y los desarrolladores pueden estar seguros de que el almacenamiento en caché 'simplemente funciona' en los proyectos que hacemos. (también el gran efecto secundario de utilizar el etiquetado es que tenemos una página que ofrece una gestión/eliminación de caché granular, con opciones para borrar el caché mediante funciones de modelo o tablas).

1

También almacenamos los resultados de la consulta de nuestra base de datos (PostgreSQL) en memcache y estamos utilizando desencadenantes en las tablas para invalidar el caché - hay varias API (ej. pgmemcache, creo que mysql tiene algo así también pero No lo sé con certeza). El beneficio es que la auto base (disparadores) de la base de datos puede manejar la invalidación de los datos sobre los cambios (actualización, inserción, eliminación), no es necesario que escriba todo eso en su "aplicación".

0

mysqlnd_qc, que inserta memcaching en los resultados de la consulta de la base de datos nivel de retorno, almacena en caché automáticamente conjuntos de resultados de mysql. Es FANTÁSTICO y automático.