Pregunta

Estamos intentando actualizar los objetos de memcached cuando escribimos en la base de datos para evitar tener que leerlos desde la base de datos después de las inserciones / actualizaciones.

Para nuestro objeto de publicación en el foro, tenemos un campo ViewCount que contiene el número de veces que se ve una publicación.

Tememos que estemos introduciendo una condición de carrera al actualizar el objeto memcached, ya que la misma publicación podría verse al mismo tiempo en otro servidor de la granja.

¿Alguna idea de cómo lidiar con este tipo de problemas? Parece que se necesita algún tipo de bloqueo pero, ¿cómo hacerlo de manera confiable en los servidores de una granja?

¿Fue útil?

Solución

Si está tratando con datos que no necesariamente necesitan actualizarse en tiempo real, y para mí el recuento de vistas es uno de ellos, entonces podría agregar un campo de caducidad a los objetos que se almacenan en memcache.

Una vez que ocurra la caducidad, volverá a la base de datos y leerá el nuevo valor, pero hasta entonces lo dejará en paz.

Por supuesto, para las nuevas publicaciones, es posible que desee que esto se actualice con más frecuencia, pero puede codificar para esto.

Memcache solo almacena una copia de su objeto en una de sus instancias, no en muchas de ellas, por lo que no me preocuparía por el bloqueo de objetos ni nada. Eso es para que la base de datos lo maneje, no su caché.

Editar:

Memcache no ofrece ninguna garantía de que, cuando esté obteniendo y configurando desde diversos servidores, sus datos no sean eliminados.

De los documentos de memcache:

  • Una serie de comandos no es atómica. Si emite un 'get' contra un ítem, opera con los datos, luego desea 'establecerlo' nuevamente en memcached, no se garantiza que sea el único proceso que funcione con ese valor. En paralelo, podría terminar sobrescribiendo un valor establecido por otra cosa.

Condiciones de carrera y datos obsoletos

Una cosa que debes tener en cuenta al diseñar tu aplicación para almacenar datos en caché, es cómo lidiar con las condiciones de carrera y los datos obsoletos ocasionales.

Supongamos que almacena en caché los últimos cinco comentarios para mostrarlos en una barra lateral de su aplicación. Usted decide que los datos solo deben actualizarse una vez por minuto. Sin embargo, olvida recordar que esta pantalla de barra lateral se muestra 50 veces por segundo. Por lo tanto, una vez que los 60 segundos vuelven y la memoria caché caduca, de repente, más de 10 procesos ejecutan la misma consulta SQL para volver a llenar esa memoria caché. Cada vez que la memoria caché expira, se producirá una ráfaga repentina de tráfico SQL.

Peor aún, tienes varios procesos que actualizan los mismos datos y el incorrecto termina fechando el caché. Entonces tienes datos obsoletos y obsoletos flotando alrededor.

Uno debe tener en cuenta los posibles problemas al rellenar o rellenar nuestro caché. ¡Recuerde que el proceso de comprobación de memcached, búsqueda de SQL y almacenamiento en memcached no es en absoluto atómico!

Otros consejos

Estoy pensando: podría ser una solución almacenar el recuento de visitas por separado del objeto Post y luego hacer un INCR en él. Por supuesto, esto requeriría leer 2 valores separados de memcached al mostrar la información.

Encontramos esto en nuestro sistema. Hemos modificado llegar tan

  • Si el valor no está establecido, lo establece con un indicador ('g') y [8] segundo TTL, y devuelve falso para que la función de llamada lo genere.
  • Si el valor no está marcado (! == 'g'), deserialice y devuélvalo.
  • Si el valor está marcado (=== 'g'), espere 1 segundo y vuelva a intentarlo hasta que no esté marcado. Eventualmente será establecido por el otro proceso, o expirado por el TTL.

La carga de nuestra base de datos se redujo en un factor de 100 cuando implementamos esto.

function get($key) {
  $value=$m->get($key);
  if ($value===false) $m->set($key, 'g', $ttl=8);
  else while ($value==='g') {
    sleep(1);
    $value=$m->get($key);
  }
  return $value;
}

las operaciones de memcached son atómicas. el proceso del servidor pondrá en cola las solicitudes y servirá cada una por completo antes de pasar a la siguiente, por lo que no es necesario bloquearlas.

editar: memcached tiene un comando de incremento, que es atómico. Solo tiene que almacenar el contador como un valor separado en el caché.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top