Практическая (Джанго) стратегия кеширования и ее реализация?Длинный кэш, недействительный кэш при изменении данных - PullRequest
7 голосов
/ 23 сентября 2011

У меня есть приложение Django, которое получает данные почти в реальном времени (твиты и голоса), хотя обновления происходят в среднем каждую минуту или две. Однако мы хотим показать данные, обновив сайт и результаты API сразу после его поступления.

Мы можем увидеть целую тонну загрузки на этом сайте, поэтому моя первоначальная мысль, конечно, кеширование!

Целесообразно ли иметь какой-то кэш Memcached, который вручную аннулируется другим процессом или событием? Другими словами, я бы долгое время кешировал представления, а затем получал новые твиты и голоса, делающие недействительными все представление.

  • Оправдывают ли незначительные улучшения производительности дополнительную сложность?
  • Есть ли практическая реализация, которую я мог бы создать (я работаю с другими разработчиками, так что взламывать кучу вещей вокруг каждого ответного вызова не очень хороший вариант)?

Меня не беспокоит недействительность только некоторых объектов, и я решил создать подкласс MemcachedCache для добавления некоторых функций после этой стратегии . Но, конечно, сессии Django также используют Memcached в качестве кэша записи, и я не хочу аннулировать , что .

Ответы [ 2 ]

7 голосов
/ 23 сентября 2011

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

  • У вас есть какой-то API, который получает новые обновления информации и НЕ выполняет опрос. Например: каждую минуту или две вы получаете запрос API и сохраняете некоторую информацию в своей базе данных.
  • Вы уже используете Memcached для кеширования материала для чтения. Возможно, через cronjob или аналогичный процесс, который периодически сканирует вашу базу данных и обновляет ваш кеш.

Предполагая, что вышеупомянутые две вещи верны, аннулирование кэша определенно является подходящим способом. Вот лучший способ сделать это в Django:

  1. На ваш сервер поступает новый запрос API, содержащий новые данные для хранения. Вы сохраняете его в базе данных и используете сигнал пост-сохранения в классе вашей модели (например, Tweet, Poll и т. Д.) Для обновления ваших данных в кэше памяти.
  2. Пользователь посещает ваш сайт и просит прочитать его последние твиты, опросы и т. Д.
  3. Вы извлекаете данные твита, опроса и т. Д. Из memcached и отображаете их для них.

По сути, это то, для чего предназначены сигналы Джанго . Они будут работать автоматически после того, как ваш объект будет сохранен / обновлен, что является отличным временем для обновления хранилищ кеша самой свежей информацией.

Выполнение этого означает, что вам никогда не потребуется запускать фоновое задание, которое периодически сканирует вашу базу данных и обновляет ваш кэш - ваш кэш всегда будет обновляться мгновенно с учетом последних данных.

4 голосов
/ 28 сентября 2011

Благодаря @ rdegotiations я смог найти отличный способ сделать это.

Я придерживаюсь этой парадигмы:

  • Кэш визуализированфрагменты шаблона и вызовы API в течение пяти минут (или дольше)
  • При каждом добавлении новых данных кеш становится недействительным.
    • Простая аннулирование кэша лучше, чем повторное сохранение при сохранении, поскольку новые кэшированные данные генерируются автоматически и органически, когда кэшированные данные не обнаруживаются.
  • Вручную аннулировать кэш послеЯ сделал полное обновление (скажем, из поиска в твиттере), но не для каждого объекта.
    • Преимущество этого заключается в том, что кэш-память становится недействительной несколько раз, но с другой стороны это не так автоматически.

Вот весь необходимый кодчтобы сделать это следующим образом:

from django.conf import settings
from django.core.cache import get_cache
from django.core.cache.backends.memcached import MemcachedCache
from django.utils.encoding import smart_str
from time import time

class NamespacedMemcachedCache(MemcachedCache):

    def __init__(self, *args, **kwargs):
        super(NamespacedMemcachedCache, self).__init__(*args, **kwargs)
        self.cache = get_cache(getattr(settings, 'REGULAR_CACHE', 'regular'))
        self.reset()

    def reset(self):
        namespace = str(time()).replace('.', '')
        self.cache.set('namespaced_cache_namespace', namespace, 0)
        # note that (very important) we are setting
        # this in the non namespaced cache, not our cache.
        # otherwise stuff would get crazy.
        return namespace

    def make_key(self, key, version=None):
        """Constructs the key used by all other methods. By default it
        uses the key_func to generate a key (which, by default,
        prepends the `key_prefix' and 'version'). An different key
        function can be provided at the time of cache construction;
        alternatively, you can subclass the cache backend to provide
        custom key making behavior.
        """
        if version is None:
            version = self.version

        namespace = self.cache.get('namespaced_cache_namespace')
        if not namespace:
            namespace = self.reset()
        return ':'.join([self.key_prefix, str(version), namespace, smart_str(key)])

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

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

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

from django.core.cache import cache
cache.clear()

Вы можете получить доступ к любомукеш с:

from django.core.cache import get_cache
some_cache = get_cache('some_cache_key')

Наконец, я рекомендую не помещать свою сессию в этот кеш.Вы можете использовать этот метод, чтобы изменить ключ кэша для вашего сеанса.(Как settings.SESSION_CACHE_ALIAS).

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