2009-10-22 11 views
19

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

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

Nos tememos que estamos introduciendo una condición de carrera al actualizar el objeto memcached, ya que la misma publicación se puede ver al mismo tiempo en otro servidor de la granja.

¿Alguna idea sobre 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 todos los servidores de una granja?

Respuesta

15

Si se trata de datos que no necesariamente necesitan para 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 están almacenados en Memcache .

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

Por supuesto, para las publicaciones nuevas es posible que desee actualizar esto más a menudo, pero puede codificar para esto.

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

Editar:

Memcache no ofrece ninguna garantía de que cuando se está recibiendo y el establecimiento de diversos servidores que sus datos no se consiguen Demolí.

a partir de documentos memcache:

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

Las condiciones de carrera y datos obsoletos

Una cosa a tener en cuenta al diseñar su aplicación a los datos de la caché, es cómo hacer frente a las condiciones de carrera y datos obsoletos ocasionales.

Digamos que almacena en caché los últimos cinco comentarios para mostrar en una barra lateral en su aplicación. Usted decide que los datos solo necesitan actualizarse una vez por minuto. ¡Sin embargo, olvidas recordar que esta pantalla de la barra lateral se renderiza 50 veces por segundo! Por lo tanto, una vez que transcurren 60 segundos y el caché expira, de repente más de 10 procesos están ejecutando la misma consulta SQL para volver a llenar ese caché. Cada vez que caché, se producirá una explosión repentina de tráfico SQL.

Peor aún, tiene múltiples procesos actualizando los mismos datos, y el incorrecto termina saliendo con la caché. Entonces tienes datos desactualizados y obsoletos flotando.

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

+0

El problema es que nos gustaría que el recuento de vistas (en este caso, pero hay otras situaciones con el mismo problema) se actualice en vivo: haga clic en la publicación y aumente la cantidad de reproducciones. También nos gustaría que el objeto de caché viva el mayor tiempo posible, por razones de rendimiento, por supuesto. – Micael

+1

No puede garantizar lo que intenta hacer de la manera que desea hacerlo. Lo que Memcache le da es escalabilidad, no rendimiento en bruto. Es cierto, pero – Nathan

1

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

edición: memcached tiene un comando de la subasta, que es atómica. Solo tiene que almacenar el contador como un valor separado en la memoria caché.

+6

i este caso que sería conseguir el artículo, incrementando el número de reproducciones y ponerlo de nuevo, y como Nathan también afirma, esto no es una operación atómica – Micael

3

Estoy pensando: podría ser una solución para almacenar viewcount por separado desde el objeto Post, y luego hacer un INCR en él. Por supuesto, esto requeriría leer 2 valores separados de memcached cuando se muestra la información.

1

Hemos encontrado esto en nuestro sistema. Hemos modificado obtener

  • Si el valor no está configurado, lo establece con un indicador ('g') y [8] segundo TTL, y devuelve falso para que la función que lo llama lo genere.
  • Si no se marca el valor (! == 'g'), entonces unserialize y lo devuelve.
  • Si se marca el valor (=== 'g') luego esperar 1 segundo y vuelve a intentarlo hasta que no está marcado. Eventualmente será establecido por el otro proceso o vencido por el TTL.

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

+0

Mejor uso cas() insetad de lance() http: // php .net/manual/ru/memcached.cas.php – Hett