Débordement de la pile, Redis, et invalidation du Cache

maintenant que Stack Overflow utilise redis, gèrent-ils l'invalidation de cache de la même manière? c'est à dire une liste d'identités haché à une chaîne de requête + nom (je suppose que le nom est une sorte de but ou un type d'objet nom).

peut-être qu'ils récupèrent alors des éléments individuels qui sont manquants dans le cache directement par id (qui contourne un tas d'index de base de données et utilise l'index groupé plus efficace à la place peut-être). Ce serait intelligent (la réhydratation que Jeff mentionne?).

en ce moment, je me bats pour trouver un moyen de faire pivoter tout cela d'une manière succincte. Y a-t-il des exemples de ce genre de choses que je pourrais utiliser pour aider à clarifier ma pensée avant de faire une première coupure moi-même?

aussi, je me demande Où est la coupure entre l'utilisation d'un cache.Net (Système.Runtime.La mise en cache ou d'un Système.Web.Cache) et sortir et utiliser redis. Ou est-ce que Redis est plus rapide?

voici le question SO originale de 2009:

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

quelques autres liens:

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

24
demandé sur STLDeveloper 2012-03-07 10:37:28

1 réponses

Je ne peux honnêtement pas décider si c'est une question SO ou une question MSO, mais:

d'Aller à un autre système est jamais plus rapide que l'interrogation de la mémoire locale (tant qu'il est muni d'un détrompeur); réponse est simple: nous utilisons à la fois! Nous utilisons donc:

  • mémoire locale
  • sinon vérifier redis, et mettre à jour la mémoire locale
  • d'autre d'extraction de la source, et la mise à jour et redis mémoire locale

cela provoque alors, comme vous le dites, un problème d'invalidation de cache - bien qu'en fait ce ne soit pas critique dans la plupart des endroits. Mais pour cela-les événements redis (pub/sub) permettent un moyen facile de diffuser les clés qui changent à tous les noeuds, de sorte qu'ils peuvent laisser tomber leur copie locale - Signification: la prochaine fois qu'il est nécessaire, nous allons ramasser la nouvelle copie à partir de redis. Par conséquent, nous diffusons les noms de clés qui changent en fonction d'un nom de canal d'événement unique.

Outils: redis sur le serveur ubuntu; BookSleeve comme un Redis wrapper; protobuf-net et GZipStream (activé / désactivé automatiquement en fonction de la taille) pour les données d'emballage.

ainsi: les événements Redis pub/sub sont utilisés pour invalider le cache pour une clé donnée à partir du un noeud (celui qui connaît l'État a changé) immédiatement (à peu près) en tous les noeuds.

en ce qui concerne les processus distincts (à partir des commentaires, " do vous utilisez tout type de mémoire partagée modèle pour plusieurs processus distincts nourrissent les mêmes données?"): non, nous ne le faisons pas. Chaque boîte de niveau de web n'héberge vraiment qu'un processus (de n'importe quel niveau donné), avec la multi-location dans que, donc dans le même processus nous pourrions avoir 70 sites. Pour des raisons historiques (i.e. "it works and doesn't need fixing") nous utilisons principalement le cache http avec l'identité du site comme partie de la clé.

Pour les quelques massivement nous avons des mécanismes pour persister sur le disque afin que le modèle en mémoire puisse être passé d'un domaine d'application à l'autre au fur et à mesure que le web recycle naturellement (ou est re-déployé), mais cela n'est pas lié à redis.

voici un exemple apparenté qui montre le "flaveur large seulement de la façon dont cela pourrait fonctionner-faites tourner un certain nombre d'instances des suivants, puis tapez quelques noms clés dans:

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));
        }
    }
}

quoi vous devriez voir est que lorsque vous tapez un nom de clé, il est affiché immédiatement dans toutes les instances en cours d'exécution, qui viderait alors leur copie locale de cette clé. De toute évidence, dans l'usage réel, les deux connexions devraient être placées quelque part et gardées ouvertes, de même que ne serait pas être dans using déclarations. Nous utilisons presque un singleton pour cela.

40
répondu Marc Gravell 2015-01-06 18:35:56