Кэширование в Django
Что является фундаментальным свойством динамических веб-сайтов? Правильно, динамичность. При каждом обращении к странице сервер производит самые разные вычисления - запросы к базе данных, отображение шаблонов и другие операции, - чтобы создать визуальный образ, видимый клиенту. С точки зрения накладных расходов это получается гораздо дороже, чем обычное чтение файла с диска.
Для большинства веб-приложений такие издержки не критичны. Ведь большая часть веб-приложений - не гиганты типа washingtonpost.com или slashdot.org, а сайты небольшого или среднего размера со скромным трафиком. Но для крупных сайтов сведение накладных расходов к минимуму - первоочередная задача.
Тут-то и приходит на помощь кэширование.
Кэширование - это сохранение результатов трудоемких вычислений, позволяющее не повторять эти же вычисления в следующий раз. Представленный ниже псевдокод объясняет, как этот подход работает для динамически генерируемой веб-страницы:
пытаемся найти в кэше страницу, соответствующую заданному URL если страница присутствует в кэше: вернуть кэшированную страницу иначе:
сгенерировать новую страницу
сохранить сгенерированную страницу в кэше (для следующего раза) вернуть сгенерированную страницу
В состав Django входит надежная система кэширования, позволяющая сохранять динамические страницы, чтобы их не приходилось заново вычислять при каждом запросе. Для удобства Django предлагает различные уровни кэширования: можно кэшировать результат работы отдельных представлений, только фрагменты, генерация которых обходится дорого, или весь сайт.
Django также прекрасно работает с промежуточными кэшами, расположенными выше по тракту прохождения запроса, например Squid (http://www.squid-cache.org/), и с кэшами на стороне броузера. Вы не можете контролировать их напрямую, зато можете отправлять инструкции (в виде HTTP-заголовков) о том, какие части сайта следует кэши- ровать и как.
Настройка кэша
Настройка системы кэширования не требует значительных усилий. В частности, ей необходимо сообщить, где должен находиться кэш - в базе данных, в файловой системе или непосредственно в памяти. Это важное решение, от которого зависит производительность кэша; понятно, что одни кэши работают быстрее, другие - медленнее.
Выбор механизма кэширования определяется параметром CACHE_BACKEND. Рассмотрим все возможные варианты значений параметра CACHE_BACKEND.
Memcached
Демон Memcached - это самый быстрый и эффективный механизм кэширования из всех поддерживаемых Django, поскольку в этом случае кэш хранится целиком в памяти. Этот механизм первоначально был разработан для высоконагруженного сайта LiveJournal.com, а затем компания Danga Interactive открыла его исходный код. Сейчас он применяется на таких сайтах, как Facebook и Wikipedia, чтобы уменьшить количество обращений к базе данных и резко повысить производительность.
Получить дистрибутив Memcached можно бесплатно на сайте http://danga. com/memcached/. Этот механизм действует как процесс-демон и захватывает строго определенный объем памяти, заданный в конфигурационном файле. Его единственная задача - предоставить быстрый интерфейс для добавления, выборки и удаления из кэша произвольных данных. Все данные хранятся в памяти, поэтому нет никаких издержек, связанных с доступом к базе данных или файловой системе.
После установки самого механизма Memcached понадобится еще установить интерфейс к нему для языка Python. Этот пакет не входит в комплект поставки Django. Существуют две разных версии, поэтому выберите и установите один из следующих модулей:
• Самым быстрым является модуль cmemcache, который можно получить на сайте http://gijsbert.org/cmemcache/.
• Если по какой-либо причине вы не можете использовать модуль cmemcache, установите дакет python-memcached, который можно получить по адресу ftp.\//ftp.tummy.com/pubt/python-memcached/. Если этот URL-адрес уже не существует, зайдите на сайт проекта Memcached по адресу http://www.danga.com/memcached/ и загрузите интерфейс для Python из раздела «Client APIs».
Чтобы воспользоваться механизмом Memcached в Django, установите параметр CACHE_BACKEND в значение memcached://ip:port/, где ip - IP-адрес демона Memcached, a port - номер порта, который этот демон использует для приема запросов.
В следующем примере демон Memcached запущен на сервере localhost (127.0.0.1) и прослушивает порт 11211:
CACHE_BACKEND = ‘memcached://127.0.0.1:11211/’
Одна из замечательных особенностей Memcached - возможность распределять кэш между несколькими серверами. Это означает, что демоны Memcached можно запустить на нескольких компьютерах, и программа будет рассматривать всю группу компьютеров как единый кэш, не дублируя его на каждой машине в отдельности. Чтобы воспользоваться этой возможностью, перечислите все серверы в параметре CACHE_BACKEND через точку с запятой.
В следующем примере кэш распределен между экземплярами Memcached, запущенными на компьютерах с адресами 172.19.26.240 и 172.19.26.242 (в обоих случаях используется порт 11211):
CACHE_BACKEND = ‘ memcached://172.19. 26. 240:11211;172.19.26.242:11211/’
А в примере ниже кэш распределен между экземплярами Memcached, запущенными на компьютерах с адресами 172.19.26.240 (порт 11211), 172.19.26.242 (порт 11212) и 172.19.26.244 (порт 11213):
CACHE_BACKEND = ‘ memcached :/Д*
172.19.26.240:11211;172.19.26.242:11212; 172.19. 26. 244:11213/’
Следует также отметить, что кэширование в памяти обладает одним недостатком: в случае выхода сервера из строя весь кэш теряется. Понятно, что оперативная память не предназначена для постоянного хранения данных, поэтому не полагайтесь на кэширование в памяти как на единственный механизм. Без сомнения, ни одну из используемых в Django систем кэширования не следует использовать для длительного хранения; все они предназначены лишь для краткосрочного кэширования, но подчеркнем, что кэширование в памяти особенно уязвимо к сбоям.
Кэширование в базе данных
Чтобы использовать в качестве кэша таблицу в базе данных, сначала создайте эту таблицу следующей командой:
python manage.ру createcachetable [cache_table_name]
где [cache_table_name] - произвольное имя таблицы. Эта команда создаст таблицу со структурой, необходимой для работы системы кэширования в базе данных.
Затем присвойте параметру CACHE_BACKEND значение "db://tablename", где table па те - имя только что созданной таблицы. В примере ниже таблица для кэша называется my_cache_table:
CACHE.BACKEND = ‘db://my_cache_table’
Для кэширования используется та же самая база данных, которая указана в файле параметров. Указать какую-то другую базу невозможно.
Для оптимальной работы механизма кэширования в базе необходим быстродействующий сервер базы данных с правильно настроенными индексами.
Кэширование в файловой системе
Для хранения кэша в файловой системе присвойте параметру САСНЕ_ BACKEND значение "file://". Например, чтобы котированные данные сохранялись в каталоге /var/tmp/django_cache, настройте этот параметр следующим образом:
CACHE_BACKEND = ‘file:///va r/tmp/dj ango_cache’
Обратите внимание на три символа слеша в начале. Первые два символа - это часть определения схемы file://, а последний - первый символ пути к каталогу /var/tmp/django_cache. На платформе Windows после префикса file:// следует указать букву диска, например:
file://с:/foo/bar
Пусть к каталогу должен быть абсолютным, то есть должен начинаться от корня файловой системы. Наличие или отсутствие символа слеша в конце пути несущественно.
Не забудьте создать каталог, на который указывает параметр, и сделайте его доступным для чтения и записи пользователю, от имени которого работает веб-сервер. Так, если сервер работает от имени пользователя apache, то каталог /var/tmp/django_cache должен существовать и быть доступен пользователю apache для чтения и записи.
Каждый кэшированный блок сохраняется в отдельном файле в формате сериализации, который определяется Python-модулем pickle. Имена файлов - это ключи кэша, экранированные с учетом соглашений файловой системы.
Кэширование в локальной памяти
Если вас привлекают преимущества кэширования в памяти, но нет возможности запустить Memcached, подумайте о кэшировании в локальной памяти. Это многопроцессный и безопасный относительно потоков выполнения механизм. Настраивается он путем определения в параметре CACHE_BACKEND значения "locmem:///", например:
CACHE_BACKEND = ‘locmem:///’
Отметим, что у каждого процесса будет свой собственный кэш, то есть таким способом невозможно будет организовать общий кэш для нескольких процессов. Отсюда с очевидностью следует, что этот механизм неэффективно расходует оперативную память, поэтому для промышленной эксплуатации он, скорее всего, не подходит. Но для разработки в самый раз.
Фиктивное кэширование (для разработки)
Наконец, в комплект поставки Django входит реализация «фиктивного» кэша, который на самом деле ничего не кэширует, а лишь реализует интерфейс кэша.
Его удобно использовать, когда имеется действующий сайт, на котором в разных местах активно применяется кэширование, и среда для разработки и тестирования, в которой вы ничего не хотите кэшировать и вообще не хотите вносить в код модификации специально для этого. Чтобы включить фиктивный кэш, определите параметр CACHE_BACKEND следующим образом:
CACHE_BACKEND = ‘dummy:///’
Пользовательский механизм кэширования
Хотя Django поддерживает целый ряд готовых систем кэширования, иногда возникает необходимость задействовать специализированный механизм. Чтобы использовать внешнюю систему кэширования, определите в параметре CACHE_BACKEND путь импорта Python в качестве схемы URI (часть, предшествующая двоеточию), например:
CACHE_BACKEND = ‘path.to.backend://’
При создании собственного механизма кэширования можно взять за образец реализации стандартных систем. Соответствующий исходный код находится в каталоге django/core/cache/backends/.
Примечание —————————————————————————-
При отсутствии достаточно веских причин (например, сервер не поддерживает стандартные механизмы) мы рекомендуем пользоваться системами кэширования, входящими в дистрибутив Django. Они хорошо протестированы и просты в употреблении.
Аргументы параметра CACHE_BACKEND
Все подсистемы кэширования могут иметь дополнительные настройки, которые определяются с помощью необязательных аргументов. Они задаются в формате строки запроса в параметре CACHE_BACKEND. Допустимыми являются следующие аргументы:
• timeout: время хранения в кэше в секундах. Значение по умолчанию равно 300 секундам (5 минутам).
• max_entries: для механизмов locmem, filesystem и database определяет максимальное количество элементов в кэше, по достижении которого старые значения начинают удаляться. Значение по умолчанию равно 300.
• cull_percentage: доля элементов кэша, удаляемых при достижении порога max_entries. Вычисляется как 1/cull_percentage, то есть при cull_percentage=2 будет удалена половина элементов кэша.
Значение 0 означает, что при достижении порога max_entries следует очистить кэш целиком. В этом случае очистка производится гораздо быстрее, но ценой потери данных в кэше.
В следующем примере определяется параметр timeout со значением 60:
CACHE_BACKEND = "memcached://127.0.0.1:11211/?timeout=60"
А здесь определяется параметр timeout со значением 30 и параметр тах_ entries со значением 400:
CACHE_BACKEND = "locmem:///?timeout=30&max_entries=400"
Неизвестные аргументы и недопустимые значения известных аргументов будут просто игнорироваться.
Источник: Головатый А., Каплан-Мосс Дж. Django. Подробное руководство, 2-е издание. - Пер. с англ. - СПб.: Символ- Плюс, 2010. - 560 е., ил.