Переполнение стека, Redis и Cache - PullRequest
26 голосов
/ 07 марта 2012

Теперь, когда переполнение стека использует redis, они так же обрабатывают аннулирование кэша?т. е. список идентификаторов, хэшированный к строке запроса + имя (я думаю, имя - это какое-то название цели или типа объекта).

Возможно, они затем извлекают отдельные элементы, которые отсутствуют в кеше, напрямую по идентификатору (который обходит множество индексов базы данных и, возможно, использует более эффективный кластерный индекс).Это было бы разумно (регидратация, о которой упоминает Джефф?).

Прямо сейчас, я изо всех сил пытаюсь найти способ кратко все это изменить.Существуют ли примеры такого рода вещей, которые я мог бы использовать, чтобы прояснить свое мышление, прежде чем делать первый разрез сам?

Кроме того, мне интересно, где находится разрыв между использованием кеша .net (Система.Runtime.Caching или System.Web.Caching) и выход с использованием redis.Или Redis просто работает быстрее?

Вот оригинальный SO вопрос 2009 года:

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

Несколько других ссылок:

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

1 Ответ

43 голосов
/ 07 марта 2012

Честно говоря, я не могу решить, является ли это вопрос SO или вопрос MSO, но:

Выход на другую систему никогда не быстрее, чем запрос к локальной памяти (если она включена); простой ответ: мы используем оба! Поэтому мы используем:

  • локальная память
  • иначе проверьте redis и обновите локальную память
  • еще получить из источника и обновить redis и локальную память

Это, как вы говорите, вызывает проблему аннулирования кэша - хотя на самом деле это не является критическим в большинстве мест. Но для этого - события redis (pub / sub) позволяют легко транслировать ключи, которые меняются на все узлы, поэтому они могут отбросить свою локальную копию - это означает: в следующий раз, когда это потребуется, мы заберем новую копию из redis. , Следовательно, мы транслируем имена ключей, которые меняются по отношению к одному имени канала события.

Инструменты: redis на сервере Ubuntu; BookSleeve в качестве оболочки для redis; protobuf-net и GZipStream (включается / отключается автоматически в зависимости от размера) для упаковки данных.

Итак: события redis pub / sub используются для аннулирования кэша для данного ключа от одного узла (того, который знает, что состояние изменилось) немедленно (в значительной степени) до всех узлы.

Относительно отдельных процессов (из комментариев: «Используете ли вы какую-либо модель совместно используемой памяти для нескольких различных процессов, использующих одни и те же данные?»): Нет, мы этого не делаем. Каждый блок веб-уровня действительно содержит только один процесс (любого данного уровня) с мультитенантностью в пределах , поэтому в одном и том же процессе у нас может быть 70 сайтов. По унаследованным причинам (т. Е. «Он работает и не нуждается в исправлении») мы в основном используем http-кеш с идентификатором сайта как часть ключа.

Для нескольких частей системы, требующих большого объема данных, у нас есть механизмы для сохранения на диске, чтобы модель в памяти могла передаваться между последовательными доменами приложений, когда сеть естественным образом перезагружается (или перераспределяется), но это не имеет отношения к Redis.

Вот связанный пример, который показывает только широкое разнообразие того, как это может работать - раскрутите несколько экземпляров следующего, а затем введите некоторые имена ключей в:

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

Что вы должны увидеть, так это то, что когда вы набираете имя ключа, оно сразу отображается во всех запущенных экземплярах, которые затем выдают свою локальную копию этого ключа. Очевидно, что при реальном использовании эти два соединения должны быть где-то размещены и оставаться открытыми, поэтому не будет в using операторах. Для этого мы используем почти синглтон.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...