Web, кеширование и memcached: часть 1

Все сегодня знают, что нагруженный веб-проект не может постоянно обращаться к БД с запросами, знают, что БД не выдержит. Все знают, что надо кешировать результаты. Можно кешировать сгенерированный HTML-контент, но лучше кешировать данные (результаты запросов), т.к. одни и те же данные могут отображаться разными способами (разные блоки, ответы по API, JSON, что-то еще).

Итак, мы договорились кешировать результаты запросов. Самый простой вариант - кешировать в файлах, однако если проект имеет кластерную (распределенную) архитектуру, кеши дублируются локальными для каждой вебморды (что приводит к большему числу запросов и к проблеме когерентности одного и того же кеша на разных мордах). Поэтому вместо файлового кеша в таких ситуациях используют замечательный продукт memcached.

Ну вот, мы всё замечательно закешировали, однако проблемы всё равно остались. Какие бывают проблемы и как с ними можно бороться? В серии постов на эту тему постараемся с этим разобраться.

Проблема №1. Именование кеша


Как назвать ключ в мемкеше, под которым мы сохраним закешированный результат выборки? У нас есть ORM-прослойка, и параметры выборки, которые представляют из себя ассоциативный массив, мы превращаем в ключ так:

$key = md5(serialize($options));

Что работает достаточно неплохо, т.к. при любом изменении параметров выборки меняется её результат, и меняется кеш. Всё хорошо.

Проблема №2. Сброс кеша


Если данные в БД поменялись, надо сбросить соответствующий кеш (удалить ключ из мемкеша), чтобы пользователи увидели актуальную информацию. Знаем параметры выборки, строим ключ, удаляем его, при следующем обращении к кешу будет произведена выборка и построен новый кеш.

Однако, этого не всегда достаточно. Например, у нас изменился объект XXX. Однако этот объект может являться частью большего числа выборок, например, входит в отдельную выборку объекта XXX (такой кеш легко очистить), а также может входить в различные списки, которые также закешированы. Сбрасывать все такие списки невозможно или даже неразумно. Было бы классно, если бы мемкеш мог "теггировать" ключи некоторыми метками и сбрасывать ключи с указанным набором меток, но эта операция вряд ли будет иметь сложность O(1), как другие его операции. В таких ситуациях сбросить кеш оказывается сложно, можно выставить таким кешам достаточно небольшое время жизни, чтобы неактуальная информация надолго не задерживалась.

Comments

Comments powered by Disqus
Contents © 2015 Andrey - Powered by Nikola