2012-03-07 35 views
24

Ahora que Stack Overflow usa redis, ¿manejan la invalidación de caché de la misma manera? es decir, una lista de identidades asignadas a una cadena + nombre de consulta (supongo que el nombre es algún tipo de propósito o nombre de tipo de objeto).Anulación de desbordamiento de pila, redis y caché

Tal vez luego recuperen los elementos individuales que faltan de la memoria caché directamente por id (que en su lugar omite un grupo de índices de base de datos y utiliza el índice agrupado más eficiente). Eso sería inteligente (la rehidratación que menciona Jeff).

En este momento, estoy luchando para encontrar una manera de pivotar todo esto de una manera concisa. ¿Hay algún ejemplo de este tipo de cosas que podría utilizar para ayudar a aclarar mi pensamiento antes de hacer un primer corte yo mismo?

Además, me pregunto dónde está el corte entre usar un caché .net (System.Runtime.Caching o System.Web.Caching) y salir y usar redis. ¿O Redis simplemente baja la mano más rápido?

Ésta es la pregunta original SO a partir de 2009:

https://meta.stackexchange.com/questions/6435/how-does-stackoverflow-handle-cache-invalidation

Un par de otros enlaces:

https://meta.stackexchange.com/questions/69164/does-stackoverflow-use-caching-and-if-so-how/69172#69172

https://meta.stackexchange.com/questions/110320/stack-overflow-db-performance-and-redis-cache

Respuesta

40

honestamente no puede decidir si esto es una pregunta AS o una pregunta MSO, pero:

Ir a otro sistema es nunca más rápido que consultar la memoria local (siempre que esté codificada); respuesta simple: ¡usamos ambos! Por eso, utilizamos:

  • memoria local
  • Redis verificación más, y actualizar la memoria local
  • demás buscarlo a la fuente, y Redis de actualización y memoria local

Esto entonces, como usted dice, causa un problema de invalidación de caché, aunque en realidad no es critical en la mayoría de los lugares. Pero para esto, los eventos redis (pub/sub) permiten una manera fácil de transmitir claves que cambian a todos los nodos, para que puedan descartar su copia local, lo que significa que la próxima vez que sea necesario, tomaremos la nueva copia de redis. . Por lo tanto, transmitimos los nombres de clave que están cambiando frente a un solo nombre de canal de evento.

Herramientas: redis en servidor ubuntu; BookSleeve como una envoltura de redis; protobuf-net y GZipStream (habilitado/deshabilitado automáticamente según el tamaño) para los datos de empaquetado.

Por lo tanto: el pub Redis/eventos subdirección se utiliza para invalidar el caché para una clave dada desde uno nodo (el que conoce el estado ha cambiado) inmediatamente (más o menos) a todos los nodos.

En cuanto a procesos distintos (a partir de comentarios, "¿utiliza algún tipo de modelo de memoria compartida para múltiples procesos distintos que se alimentan de los mismos datos?"): No, no hacemos eso. Cada cuadro de nivel web solo hospeda un proceso (de cualquier nivel), con varios clientes dentro de, por lo que dentro del mismo proceso podríamos tener 70 sitios. Por razones de herencia (es decir"funciona y no necesita arreglo") utilizamos principalmente la memoria caché http con la identidad del sitio como parte de la clave.

Para las pocas partes del sistema que requieren gran cantidad de datos, tenemos mecanismos para mantener en el disco de modo que el modelo en memoria se pueda pasar entre sucesivos dominios de aplicación a medida que la web se recicla de forma natural (o se vuelve a implementar) , pero eso no está relacionado con redis.

Aquí está un ejemplo relacionado que muestra el amplio sabor única de cómo podría funcionar esto - girar un número de instancias del siguiente, y luego escribir algunos nombres clave en:

static class Program 
{ 
    static void Main() 
    { 
     const string channelInvalidate = "cache/invalidate"; 
     using(var pub = new RedisConnection("127.0.0.1")) 
     using(var sub = new RedisSubscriberConnection("127.0.0.1")) 
     { 
      pub.Open(); 
      sub.Open(); 

      sub.Subscribe(channelInvalidate, (channel, data) => 
      { 
       string key = Encoding.UTF8.GetString(data); 
       Console.WriteLine("Invalidated {0}", key); 
      }); 
      Console.WriteLine(
        "Enter a key to invalidate, or an empty line to exit"); 
      string line; 
      do 
      { 
       line = Console.ReadLine(); 
       if(!string.IsNullOrEmpty(line)) 
       { 
        pub.Publish(channelInvalidate, line); 
       } 
      } while (!string.IsNullOrEmpty(line)); 
     } 
    } 
} 

Lo que debe ver es que cuando escribe un nombre de clave, se muestra inmediatamente en todas las instancias en ejecución, que luego vuelcan su copia local de esa clave. Obviamente, en el uso real, las dos conexiones tendrían que colocarse en algún lugar y mantenerse abiertas, por lo que no estar en using declaraciones. Usamos casi un singleton para esto.

+0

¿El evento también vuelve e invalida la versión en memoria también? Si es así, genial. re: in-memory: ¿utiliza algún tipo de modelo de memoria compartida para múltiples procesos distintos que se alimentan de los mismos datos? Estoy viendo un potencial de duplicación del componente en memoria. – sgtz

+0

@sgtz editará –

+0

gracias Marc. Ahora digiriendo información (dientes mentales no han terminado de girar aún). Administrar la caducidad en memoria desde el exterior es un * muy * lindo toque. No había pensado en eso. (!) – sgtz

Cuestiones relacionadas