Кеширование. Инвалидация сигналами. Аперитив
Как я обещал ранее, реализация кеширования с инвалидацией по-средствам сигналов - стала моей целью на прошедших каникулах. И была сделана в легкой и непринужденной атмосфере благополучия и меланхолии(я в первые с первого курса заработал стипендию!:)).
Как вы поняли из заголовка, этот пост лишь начало моего повествования об этой концепции и её первичной реализации. Сейчас я расскажу об особенностях такого подхода к инвалидации, проблемах, достоинствам, ну и конечно некоторых результатах.
Ещё хочу отметить, что система уже некоторое время успешно применяется в данном блоге.
Кратко суть. Идея состоит в том чтобы кеш протухал не по таймауту, а при возникновении некоторого события, которое порождает сигнал, который потом обрабатывается и может справоцировать инвалидацию. Следовательно данный подход должен быть боле логичен и более оптимален чем классический. Поскольку использование таймаута может быть неэффективено, когда периодичность изменения не детерминирована. Либо получается, что кеш слишком часто обновляется, либо наоборот долго висит старый. Первый вариант сказывается на производительности, а второй на актуальности информации, которую получает пользователь сайта. И того и другого хочется избежать.
Используя такой мощный инструмент как сигналы в django, который позволяет независимым приложениям и компонентам в них взаимодействовать друг с другом, можно решить эти проблемы. Обычно сигналы сообщают, что в системе произошло некоторое событие и на него ожидается реакция. Это нам и надо: событие -> инвалидация. Пробежимся по сигналам.
К одним из самых распространенных и полезных сигналов можно отнести pre/post_save
, которые сообщает о сохранение, а следовательно, в большинстве случаев, об изменении данных.
Отследить, действительно ли были изменены данные или сигнал был послан “вхолостую” нельзя, что конечно будет порождать ложные срабатывания. Но, к счастью, таких случаев очень мало по сравнению с реальными.
Ещё одними маркерами изменения данных являются pre/post_delete
. Тут всё понятно, они рассылаются когда объект модели удаляется из базы. Они тоже играют важную роль.
На них в основном и ляжет груз ответственности за ивалидацию.
Но, одной из ключевых особенностей системы сигналов в джанго является возможность создания своих собственных сигналов, в соответствии с бизнес логикой приложения. Это мощнейший инструмент, который позволяет очень четко и лаконично интегрировать сторонние приложения с имеющимися, абсолютно прозрачно и независимо друг от друга. Следовательно и для инвалидации они могут быть использованы с большим успехом, если встроенные вдруг окажутся менее удобными.
Теперь немного расскажу о принципе действия кеширования с сигнальной инвалидацией. Первым делом мы определяемся с данными которые необходимо кешировать. Второе, необходим некий контекст в котором эти данные получены, существуют и актуальны. Этот самый контекст будет использовался для создания уникального суффикса для ключа кеша. Чтобы не было конфликта, это контекст должен быть правильно подобран и обеспечивать актуальность. На основе этого суффикса и будет осуществляться проверка необходимости инвалидации.
Но тут как раз и появляться одна из проблем. Контекст создания данных для кеширования и контекст генерации сигнала может очень сильно отличаться. Поэтому за этим необходимо внимательно следить и подбирать оптимальные варианты.
Далее, после того как данные записываются в кеш, вешается обработчик на соответствующий сигнал (чаще сигналы), который при его срабатывании проверяет контекст от сигнала и если нужно очищает соответствующий кеш.
По схеме всё достаточно просто. И как вы увидите через некоторое время, реализация тоже не слишком сложная. Но тут самая большая проблема вовсе не реализация, а правильная подборка мета-информации о контексте и сигналах.(уж простите мне частое упоминание слова контекст
, но оно очень важное, и как мне кажется точно отражает суть).
Необходимо учесть все возможные варианты при которых закешированиые данные могут потерять актуальность и повесить обработчик на все возможные сигналы. Это один из самых трудоёмких процессов в проектировании, как я понял:) Поскольку не всё так очевидно с первого взгляда.
Ещё одна особенность, что таймаут в любом случае для пары ключ-значение должен быть установлен и тут надо подобрать достаточно большое число, чтобы интервал например сутки был или любой другой крупное (но не надо забывать об ограничения бекэнда на таймаут).
Для этого блога я использую memcache бекэнд. Для теста, на описанный выше способ кеширования, я перевел некоторые “пады” в правом блоке, где меню. И комментарии к каждому посту. Результаты я точно не мерил, но шустрее стало значительно. Опираясь на время рендеринга страницы(внизу слева) могу чказать, что производительность повысилась в разы. Но тут уже особенности моего сервера играют главную роль.
Да и производительность по сравнению с классическим способом кеширования не должна отличаться совсем. Не с чего:) Главное я выигрываю в актуальности - я точно знаю, что вижу реальные данные, а не их “снимок” со времени предыдущего истечения таймаута. Это я считаю главным и основным достоинством данной концепции.
Особенно такая схема должна помочь в высоко-динамических сайтах, коим мой блог пока не является:) Так что в следующей раз(скоро), подробно опишу реализацию и предложу на суд общественности всю систему с потрохами целиком.
Ну как, аппетит разыгрался?:)