Все сегодня знают, что нагруженный веб-проект не может постоянно обращаться к БД с запросами, знают, что БД не выдержит. Все знают, что надо кешировать результаты. Можно кешировать сгенерированный HTML-контент, но лучше кешировать данные (результаты запросов), т.к. одни и те же данные могут отображаться разными способами (разные блоки, ответы по API, JSON, что-то еще).
Итак, мы договорились кешировать результаты запросов. Самый простой вариант - кешировать в файлах, однако если проект имеет кластерную (распределенную) архитектуру, кеши дублируются локальными для каждой вебморды (что приводит к большему числу запросов и к проблеме когерентности одного и того же кеша на разных мордах). Поэтому вместо файлового кеша в таких ситуациях используют замечательный продукт memcached.
Ну вот, мы всё замечательно закешировали, однако проблемы всё равно остались. Какие бывают проблемы и как с ними можно бороться? В серии постов на эту тему постараемся с этим разобраться.
Проблема №1. Именование кеша
Как назвать ключ в мемкеше, под которым мы сохраним закешированный результат выборки? У нас есть ORM-прослойка, и параметры выборки, которые представляют из себя ассоциативный массив, мы превращаем в ключ так:
$key = md5(serialize($options));
Что работает достаточно неплохо, т.к. при любом изменении параметров выборки меняется её результат, и меняется кеш. Всё хорошо.
Проблема №2. Сброс кеша
Если данные в БД поменялись, надо сбросить соответствующий кеш (удалить ключ из мемкеша), чтобы пользователи увидели актуальную информацию. Знаем параметры выборки, строим ключ, удаляем его, при следующем обращении к кешу будет произведена выборка и построен новый кеш.
Однако, этого не всегда достаточно. Например, у нас изменился объект XXX. Однако этот объект может являться частью большего числа выборок, например, входит в отдельную выборку объекта XXX (такой кеш легко очистить), а также может входить в различные списки, которые также закешированы. Сбрасывать все такие списки невозможно или даже неразумно. Было бы классно, если бы мемкеш мог "теггировать" ключи некоторыми метками и сбрасывать ключи с указанным набором меток, но эта операция вряд ли будет иметь сложность O(1), как другие его операции. В таких ситуациях сбросить кеш оказывается сложно, можно выставить таким кешам достаточно небольшое время жизни, чтобы неактуальная информация надолго не задерживалась.
Comments
Comments powered by Disqus