Кеширование в сайтовом движке, как реализовать?

kanaris

Новичок
Кеширование в сайтовом движке, как реализовать?

Хочу услышать советы тех, кто делал кеширование в своих движках или сталкивался с подобными проблемами ну и вообще всех кто знает:)
Придумываю алгоритм кеширования веб-страниц в движке. Обычно это делается в след. этапы:

1) из БД извлекается инфа о последнем обновлении страницы (по заданному урлу, кукам, и др)
2) извлекается последний образ кеширования страницы (по заданному урлу, кукам, и др)
3) если последний образ страницы устарел, сгенерить страницу по новой и обновить последний образ в базе.
4) если образ не устарел, в браузер выдать эту готовую страницу и пропустить процесс генерирования страницы (инклуд модулей, обработка данных, парсинг, етс).

Возникает вопрос: как узнать, изменилась ли страница, не генерируя ее заново? На обновление страницы влияют такие факторы (не полный список):
1) изменение конкретной таблицы в БД
2) изменение файлов на сервере (если скрипт считывает какую-то директорию)
3) фактор времени (например, текущее число на календаре) - страница уже будет другой следующего числа
4) Залогиненный юзер (для каждого юзера одна и та же страница будет другой, например панель "Здравствуйте Пользователь! У вас 20 новых сообщений")
5) скин
6) язык
7) ...

Также нужно предусмотреть такую проблему: если изменилась одна таблица (добавили/удалили/отредактировали запись), то должна измениться только та страница, на которую повлияла эта запись, а не все страницы, использующие эту таблицу (которые бы не изменились при редактировании таблицы), и чтобы страница не перегенеривалась, если она не изменилась.
В общем нужно придумать самый гибкий и универсальный вариант. кто что посоветует...
 

Alexandre

PHPПенсионер
изменилась ли страница, не генерируя ее заново? На обновление страницы влияют такие факторы (не полный список):
1) изменение конкретной таблицы в БД
2) изменение файлов на сервере (если скрипт считывает какую-то директорию)
3) фактор времени (например, текущее число на календаре) - страница уже будет другой следующего числа
4) Залогиненный юзер (для каждого юзера одна и та же страница будет другой, например панель "Здравствуйте Пользователь! У вас 20 новых сообщений")
1) реализуется алгоритмом, готовых рецептов нет.
Обычно время регенерации страниц - задаешь самомтоятельно 10 мин или 10 дней...
в моем случае это было 12 часов, связано с репликацией БД.
вообще-то я писал специальный умный кешер, как раз связано с пп.1
2) не понял о каких файлах - речь? о закешированных страницах?
3) не надо кешировать всю страницу, кешируй блоки. Я, вообще кешировал только данные.
4) см 3)

вообще-то одно из решений для кеширования http://labyrinter.ru/dbcache
есть другие разработки, но они более сложные и еще будут дорабатываться.
 

Иван 76

Новичок
Alexandre
>3) не надо кешировать всю страницу, кешируй блоки. Я, вообще кешировал только данные.

Интересно было бы услышать аргументы.
Кеширование страницы целиком позволяет легко организовать кеширование на стороне клиента. Что, в принципе, довольно актуально, особенно, если учитывать, что поисковики так же руководствуются статусом 304.

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

Было бы неплохо организовать "дырки" в кеше, куда можно проставлять данные в зависимости от условий (права доступа и пр.). Что-то подобное реализовано в Smarty.

Впервые я организовал дырки в кеше в связке с xml-шаблонизатором. Меня устраивало все, кроме зависимости от шаблонного движка. Примерно в это же время, Popoff решил эту же задачу в своем движке http://popoff.donetsk.ua/text/work/light/ несколько иным путем. Поизучав его подход, я переделал свой механизм на основу простых replace & call_user_func, а гарантом защиты от посторонних иньекций из данных пользователя выступила секретная цифровая комбинация в "метке подстановки".

В принципе, получилось неплохо, - я доволен. Привязка к кешированию на стороне клиента очень сильно сократило нагрузку на сервер. Поисковые Боты начали "летать". Качество поискового индекса заметно увеличилось (страницы перестали повторно загружаться (статус 304), - а значит, отпала вероятность некорректной передачи данных).

Естественно, в качестве Last-Modified, для достижения эффекта, использовалось время обновления строки в БД, а не время создания кеша, как это часто бывает.
 

CHEM_Eugene

Новичок
Тоже очень интересует тема кэширование на php, но пока не много уделял ей внимания. Поэтому есть несколько вопросов, т.к. топик подходящий, решил ещё одного не открывать:
1. Где лучше всего в архитектуре MVC организовать управление кэшем? (имеется FrontController, ActionController-ы и им соответствующие модели по типу dataMapper)
2. Заморачиваться ли с кэшированием на стороне клиента? Если да, то как организовать блочное кэширование в соответствии в этим требованием?
3. Что делать с формами, как пропускать их при кэшировании?
 

Иван 76

Новичок
CHEM_Eugene

>3. Что делать с формами, как пропускать их при кэшировании?
По желанию. Как правило, формы не требуют много ресурсов. Но бывают и исключения. В принципе, можно кешировать форму с пустыми значениями. Для подстановки значений в кешированную форму можно использовать xml-парсер или http://dklab.ru/lib/HTML_FormPersister/

>2. Заморачиваться ли с кэшированием на стороне клиента?
Да, окупится сторицей. Особенно, если важны ресурсы (например, на виртуальном хостинге).

>1. Где лучше всего в архитектуре MVC организовать управление кэшем?
Готового рецепта здесь нет. Много взглядов.
У каждого - своя философия (у меня тоже).
Один из неплохих способов решения этого вопроса изложен здесь. http://framework.zend.com/manual/en/zend.cache.frontends.html#zend.cache.frontends.page

Кстати, кеширование Zend FrameWork активно развивается и модифицируется. В перспективе будет реализовано и кеширование на стороне клиента.
 

Alexandre

PHPПенсионер
Кеширование страницы целиком позволяет легко организовать кеширование на стороне клиента. Что, в принципе, довольно актуально, особенно, если учитывать, что поисковики так же руководствуются статусом 304.
Иван 76 где ты кешировать собрался страницу? это я к статусу 304.
Аргументы: сокращаются объемы информации до 5 раз минимум, а вообще проблемы с кешем в несколько Гиг ты имел?
 

itprog

Cruftsman
iceman, Иван 76
а как ссылки на эти врапперы для кэш-драйверов ответят на вопросы?

kanaris
Есть книжка такая, Web Caching and Its Applications. Сам пока не читал, но думаю это единственный объемный материал
 

Иван 76

Новичок
Alexandre

где ты кешировать собрался страницу? это я к статусу 304.
Аргументы: сокращаются объемы информации до 5 раз минимум, а вообще проблемы с кешем в несколько Гиг ты имел?
В принципе, я храню кеш в MySQL, с разнесением по разным таблицам. Я сделал эммулятор файловой системы, т.е. таблицы образуют древовидную иерархию. Можно одним махом очистить или профильтровать по тегам несколько таблиц одной ветки дерева.

Не все страницы можно и нужно кешировать целиком.

Обычно требуют ресурсов страницы, которые содержат выборки (например список объявлений). Вывод же самого объявления (выборка по первичному) можно вообще не кешировать на стороне сервера (или блочно), а только на стороне клиента.

Обычно размер кеша одной таблицы не превышает 50 Мб (при включенном сжатии данных кеша). Общий размер кеша может составлять до 10 Гб.

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

Естественно, кеширование страницы целиком ни в коем случае не отменяет блочного кеширования, а только дополняет его.

Если страница простая (шапка - тело - ноги), то под кешированием страницы можно понимать кеширование тела. Шапку и ноги можно отдельно кешировать и инклюдить. Но у меня, по ряду причин, этот способ не проходит.

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

Alexandre

PHPПенсионер
В принципе, я храню кеш в MySQL, с разнесением по разным таблицам.
дополнительно нагружать и так нагруженный мускуль. хотя особенности у каждого проекта свои
Вывод же самого объявления (выборка по первичному) можно вообще не кешировать на стороне сервера (или блочно), а только на стороне клиента.
как это? мы для разных клиентов каждый раз вызываем обращение к выборки объявлений?
В некоторых случаях я включаю логинирование запросов. Т.е. система подсчитывает к-во вызовов страницы, и кеширует ее только в том случае, если за определенный промежуток времени она вызывалась определенное к-во раз. Таким образом сильно экономится дисковое пространство.
нечто похожее я использовал
в принципе все ясно
все-таки используешь блочное кеширование и сборку из кешей.
 

Иван 76

Новичок
Alexandre
дополнительно нагружать и так нагруженный мускуль. хотя особенности у каждого проекта свои
Изначально все было на текстовых файлах с разнесением по директориям. Но практика показала, что MySQL все-таки эффективнее, особенно при больших объемах. Тем более, что MySQL стоит на отдельном сервере.

как это? мы для разных клиентов каждый раз вызываем обращение к выборки объявлений?
там простенькая страница, без наворотов. Просто делаем запрос по первичному ключу, достаем объявление, в зависимости от авторизованности и прав пользователя смотрим - проверять ли Last-Modified. Если это не админ, и не автор объявления, и не редактор с правом доступа, - проверяем Last-Modified и если он совпал с датой редактирования объявления - отдаем 304.
Какая разница, - лезть за кешем по первичному ключу, или в базу объявлений по первичному....

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