Блочное кеширование и MVC

korchasa

LIMB infected
Автор оригинала: MiksIr
Э, ну, если задача - приделать костыль быстрого кеширования в архитектуру, где об этом кешировании и не думали, и при этом данные с коротким но известным временем жизни - то почему бы и нет.
Костыль - это по определению сложноподдерживаемое, нелогичное решение. Если требования отдавать "честные" данные в бизнесе отсутствуют, то ttl никак не костыль. Он не отрицает "всегда валидных" кэшей. Просто это разные требования к актуальности, которая, ктстати, достигается дополнительным кодом.

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

MiksIr

miksir@home:~$
Ну вообще-то приладка к шаблонизатору кеширования - это сложноподдерживамое решение, если сравнивать десятки мини-кешей-блоков в шаблоне с централизованным кешированием в одной точке.

Никто не говорит, что TTL - это плохо, часто это даже нужно. Но вот когда у нас есть нестабильная новостная лента, которая может выдать 10 новостей за час, а может и без обновлений несколько часов простоять - тут TTL уже совсем не то, что нужно. Думаю, с этим у нас разногласий нет.

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

Именно на основе этих размышлений напрашивается вывод, что такое кеширование - это костыль. Ибо быстро реализуемое но сложноподдерживаемое (не расширяемое, децентрализованное - поди потом разберись где в каких шаблонах кто понаставил кешей с каким TTL). Кстати, почему это костыль - нелогичное? Как раз самое логичное исходя из бизнес задачи "как можно быстрее реализовать, а потом уже думать, как сделать правильнее" ;)

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

korchasa

LIMB infected
Автор оригинала: MiksIr
Теперь, если в проекте разные типы данных, одни из которых допускают запаздывание, а другие - нет, то мы что - создадим разные кеши? Нет.
Нет? Почему?
Автор оригинала: MiksIr А вот блочное кеширование в шаблонизаторе гораздо сложнее доработать будет.
Ну во-первых подобная бизнес логика вряд ли поменяется. Через полгода прибежит заказчик и скажет, что он решил честно показывать количество онлайн пользователей, ибо "написано 503, а на самом деле 490"?
Во-вторых оно легко дорабатывается. Для работы кэша нужно 3 вещи: id соединения, ключ кэша, ttl. Их легко защить в каком-нибудь OnlineUsersCacheService.
Именно на основе этих размышлений напрашивается вывод, что такое кеширование - это костыль. Ибо быстро реализуемое но сложноподдерживаемое (не расширяемое, децентрализованное - поди потом разберись где в каких шаблонах кто понаставил кешей с каким TTL).
Ну так include шаблонов в руки - пусть шаблон будет один ;)
Автор оригинала: MiksIr И, к слову, если говорить о мало-мальско серьезном сайте, типа социалок с кучей пользователей, то это по определению уже своя серверная база, а значит кеширование просто нужно уносить на фронт-энд.
В более-менее серьезных сайтах кэширование происходит на нескольких уровнях, т.к. условия разные. Один multiget к memcache сделать дешевле, чем 10 подзапросов, через nginx+SSI.
 

MiksIr

miksir@home:~$
Действительно. Давайте создадим разные реализации кеширования. Один в шаблонах с TTL, другой в мапере с обновлением на апдейте... еще осталось парочку придумать, что бы потом сказать - во, смотрите тут сколько кешей, огого.

Ну во-первых подобная бизнес логика вряд ли поменяется.
Поменяться - может и не поменяется, а вот новая добавиться - запросто может. А далее - см п.1

Во-вторых оно легко дорабатывается. Для работы кэша нужно 3 вещи: id соединения, ключ кэша, ttl.
Ну-ка тут поподробнее. Мы говорим о кеше с актуализацией на апдейте данных. Для этого нам нужно знать - какие данные были использованы при генерации этого вот куска хтмл-я. Не, конечно можно в шаблоне это еще одним вызовом куда-то приписать, получить, и т.д.... т.е. я знаю, что лимбовцы любят активные шаблоны, но не до такой же степени ;)

Ну так include шаблонов в руки - пусть шаблон будет один
Ага, и не дай бог потребуются данные в разном виде. Ничо, еще какой-нибудь костыль в шаблонизатор прикрутим ;))

В более-менее серьезных сайтах кэширование происходит на нескольких уровнях, т.к. условия разные.
На самом деле этих уровней не так уж и много, если мы говорим о MVC по крайней мере. Сырые данные кешировать... можно, но база обычно сама это неплохо делает. Полученные объекты - да, можно кешировать. Резултаты сложных рассчетов в контроллере... можно, конечно, напрмую класть в кеш, а можно обернуть в те же объекты - там уже все есть. Ну и готовый HTML. Несомненно, может быть специфика - как и в применении любого паттерна, но в большинстве случаев все укладывается в кеширование выхода и кеширование внутренних объектов.

Один multiget к memcache сделать дешевле, чем 10 подзапросов, через nginx+SSI.
В случае полного кеша - один мультигет - это запрос в PHP, а далее проходим роутер, контроллер, шаблонизатор... 10 SSI - это 10 запросов по файловой системе не уходя с уровня nginx. Файлы можно и в память положить, если так хочется, и в мемкеш - это уже вторично. Так что дешевле - один тяжелый запрос в PHP или 10 легких запросов по файлам?
 

korchasa

LIMB infected
Автор оригинала: MiksIr
Поменяться - может и не поменяется, а вот новая добавиться - запросто может. А далее - см п.1
Что значит добавится новая логика? Добавиться к чему? На пальцах: У нас есть блок, например, новые статьи, и заказчика устраивает отставание на минуту. Мы добавляем 2 строчки и он кэшируется. Если, вдруг, заказчик почему-то меняет свое решение, то мы удаляем 2 строчки и делаем либо кэширование данных, либо оборачиваем это в какую-то абстракцию, которая содержит и удаление и html. Т.е. то, что предлагаешь делать сразу, мы делаем только когда это ДЕСТВИТЕЛЬНО необходимо.
Автор оригинала: MiksIr Ну-ка тут поподробнее. Мы говорим о кеше с актуализацией на апдейте данных. Для этого нам нужно знать - какие данные были использованы при генерации этого вот куска хтмл-я.
Лимбовцы обычно УДАЛЯЮТ кэш, в тот момент, когда он перестает быть валидным. Заранее генерировать кэш не обязательно, можно dog-pile по разному обходить.
Сырые данные кешировать... можно, но база обычно сама это неплохо делает.
Ага, главное таблички не обновлять :D
Так что дешевле - один тяжелый запрос в PHP или 10 легких запросов по файлам?
У меня два фронта - мне застрелиться?
 

MiksIr

miksir@home:~$
У меня два фронта - мне застрелиться?
Зачем же, FC с корзиной. Для тех кто попроще - придумали и другие варианты шаренных ФС. Да и из мемкеша nginx давно умеет брать. Суть одна - запрос на бекенд очень дорогой.

Лимбовцы обычно УДАЛЯЮТ кэш, в тот момент, когда он перестает быть валидным.
Дело в том, что кеш перестает быть валидным в момет изменения данных. А TTL - это некое допущение, сколько времени мы разрешаем себе показывать пользователям старый невалидный кеш. А апдейт или удаление - это уже второй вопрос вообще к текущему отношения не имеющий. Удаление, соглашусь, гораздо более удобно в плане _универсальности_.

Мы добавляем 2 строчки и он кэшируется. Если, вдруг, заказчик почему-то меняет свое решение, то мы удаляем 2 строчки и делаем либо кэширование данных, либо оборачиваем это в какую-то абстракцию, которая содержит и удаление и html.
На пальцах - допустим, у вас не говнокод. У вас данные мапятся через одну дырку, которую можно эти данные легко научить кешировать. Вопрос - зачем вот все вышеописанное, если можно изначально было кешировать данные там? Давайте по плюсам-минусам.

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

Кеширование данных в шаблонизаторе позволяет получить выигрыш за счет пропуска логики работы контролера и самого шаблонизатора. Наглядность проставления TTL для блоков. Минусы: сложно реализовать иную логику ревалидации кеша кроме как TTL, только для активных шаблонов, зависимость от шаблонизатора(?), нужно описывать отдельные кеши для различающихся представлений одних данных (хотя бы Top10 и Top20 одних и тех же новостей на разных страницах)

Ну я набросал особо не напрягаясь. Давайте дополним и посмотрим.
 

Lightning

Трудоголик
Еще вариант.
Сделать двунаправленную связь представления с контроллером.
В шаблоне прописываются блоки, которые могут быть кэшированы (могут быть, а могут и не быть. При этом шаблону это неизвестно, это решает контроллер, как и тип кеша (по событиям или по времени)).
PHP:
<? if( block( 'block_name' ) ) { ?>
    <!-- содержимое блока -->
<? } endBlock( 'block_name' ); ?>
Когда вызывается block(), представление обращается к контроллеру. Контроллер проверяет, существует ли кэш данного блока. Если существует, то отдает его в представление, если нет - то создает объекты модели и т.д.
Плюсы:
- не дублируется логика.
- кэшируется готовый html-код блока
Минусы:
- контроллер усложняется

Когда кэширования данных будет не достаточно, можно будет применить.
 

korchasa

LIMB infected
Lightning
Можно назвать помесь контроллера с html компонентом и кэшировать его :)

-~{}~ 19.11.09 23:11:

Или сделать composit layout и кэшировать его подзапросы. Тот же SSI, только в РНР.
 

MiksIr

miksir@home:~$
На сколько дороже, чем 10 запросов к memcache по сети? Ну примерно.
Берем один сервер. Смотрим, сколько он может обслужить PHP запросов как выделенный бекенд и мемкеш запросов как выделенный мемкеш сервер. Получаем нужный результат.
А потом можно еще с этим вот http://www.lexa.ru/nginx-ru/msg19911.html ;)
Я мемкеш для таких целей не использую, да и результат для меня очевиден - так что бенчмарк за вами ;)

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

Lightning

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

john.brown

просто кулибин
Lightning
Имхо, вот этим
PHP:
<? if( block( 'block_name' ) ) { ?> 
    <!-- содержимое блока --> 
<? } endBlock( 'block_name' ); ?>
ты это уже начал делать... ;)
 

Lightning

Трудоголик
john.brown
Имхо, если контроллер может использовать разные шаблоны, а шаблон может использоваться разными контроллерами, значит шаблон отделен от контроллера.
 

john.brown

просто кулибин
Может быть, может быть... В моем понимании, в шаблоне не должно быть всяких условий, циклов, вызовов функций...Но это вопрос философский, и найдется не мало людей на форуме, которые пойдут священной войной на меня за это... :D
 

Beavis

Banned
john.brown
правильно, шаблон должен быть не сложнее чем
<html>
{content}
</html>

:D
 

john.brown

просто кулибин
Beavis
Шутки, шутками, но, имхо, в шаблоне должна быть только разметка блоков отображения, и переменные. А логика вся удел вюшки.
 

Lightning

Трудоголик
john.brown
Вот это
PHP:
<? if( block( 'block_name' ) ) { ?> 
    <!-- содержимое блока --> 
<? } endBlock( 'block_name' ); ?>
не что иное, как разметка блоков.

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