Неожиданно для себя обнаружил, что метод Kohana::cache($name, $data = NULL, $lifetime = 60)
работает немного не так, как я ожидал. Предполагая, что параметр $lifetime
(время жизни кэша, в секундах) надо указывать при сохранении данных, использовал Kohana::cache($name, $data, $lifetime)
для кэширования и Kohana::cache($name)
для извлечения из кэша. Вроде бы все логично, но…
Обратил внимание, что кэш практически не используется, т.е. течении дефолтных 60 секунд. Залез в исходники и увидел, что параметр $lifetime
никак не сохраняется в файловом кэше. На основании вышеописанных рассуждений опубликовал патч, который позволяет хранить в кэше как сами данные, так и lifetime. Однако в комментариях Shadowhand высказал мнение, что время жизни должен указывать клиент (т.е. тот, кто запрашивает данные из кэша), в связи с чем патч был отклонен.
Тем не менее, вопросы остались. Почему просто не указать ОДИН раз время жизни при сохранении, а потом просто пытаться его считать? В частности, раньше библиотека Cache так и делала. Теперь же любой клиент должен использовать вызов Kohana::cache($name, NULL, $lifetime)
, а откуда он может знать оптимальный lifetime? В общем, ИМХО, неудобно и нелогично…
я в своих поделках при кешировании в файлы делаю touch так, как будто файлы записаны в будущем. При чтении — сверяю время создания файла и текущее. Если файл не из будущего — кеш просрочен.
Фигли тут сложного для разработчиков Коханы?
>Однако в комментариях Shadowhand высказал мнение, что время жизни должен указывать клиент (т.е. тот, кто запрашивает данные из кэша), в связи с чем патч был отклонен.
Т.е., если никто не запрашивает данные их кеша — он хранится вечно? Бред…
Согласен.. Довольно странное нестандартное поведение для кеша…
А такой механизм только для файлового кеша?
Ъ
Этот вариант еще лучше. Так можно автоматизировать очистку кэша по крону, т.к. не придется даже считывать содержимое файлов.
aktuba
С файловым кэшем в принципе так и будет. Файл удалится только если при обращении обнаружится его «просроченность». В общем-то, надо делать чистку вручную.
Сергей
Ну, в трешке я портированный кэш так пока и не посмотрел, но в 2.3.4 все было стандартно.
Думаю, нормальное решение — для случаев, когда одни и те же данные могут отображаться либо на отдельных страницах либо в виде набора.
Грубо: при выводе заметки в блоге, нужно показывать достоверное количество комментариев. На главной же странице точное значение количества комментариев не так важно, можно его обновить в кэше лишь при просмотре отдельной страницы.
По-моему логичней как раз, чтобы клиент указывал время. Ведь если делать так как Вы говорите, то у клиента нету никакой возможности сказать «дай ка мне обнавлённые данные». А это зачастую очень нужно.
Мне нравится такой подход!
Хотя сначала тоже наткнулся на эту «особенность» и был немного в замешательстве )))
@BaRoN!
Как по мне, в таком случае лучше кэшировать отдельно блок с коротким анонсом статьи (в том числе и количество комментариев), нет?
@Vegnus
Клиент вообще не должен знать, из кэша данные или нет. Так же как и не может знать, к какому моменту времени кэш можно будет считать «просроченным». Этим должен заниматься объект, обладающий всей необходимой информацией, т.е. кэширующий объект.
@Славик
Честно говоря, не вижу в нем ничего полезного. К примеру, мы кэшируем данные о пользователе. Далее из десяти различным мест пытаемся загрузить их. Какой lifetime использовать? А если позже мы переделаем что-то в алгоритме кэширования и понадобится изменить lifetime?
Думаю, клиент и правда не должен знать из кеша ли берутся его данные или нет.
Но, вопрос что понимать под клиентом в данном случае.
Допустим, у меня есть блок информации, который часто дергается разными модулями. Пусть это будут модули A и B.
Модулю А считает, что кеш должен храниться 1 день, а модуль В считает, что 5 минут. В итоге при очередном обращении соответствующий модуль сам решает истекло ли время жизни кеша или нет — и если надо — обновляет его. Но модуль — это и есть в данном случае кеширующий объект, обладающий всей информацией. А функция Kohana::cache(…) — это просто функция ядра.
То есть по сути модули А и В можно считать и клиентами, и кеширующими объектами одновременно.
В любом случае все легко можно заточить под себя, если кто-то считает это неудобным =) Меня лично этот подход устраивает.
2Бубнов Славик: что значит «Модулю А считает, что кеш должен храниться 1 день, а модуль В считает, что 5 минут.»? Модуль вообще не должен знать, в кеше данные, в базе или вообще на другом сайте. Модуль запрашивает — ядро отдает. Поэтому ядро и должно решать, какой фрагмент сколько хранить
Почему не должен-то?! =)
На самом деле используя в контроллере методы модулей (пусть это будут те же А и В) А->get_data() и B->get_data() — я не думаю о том, насколько актуален кеш и откуда вообще берутся данные. Я эту логику прописал в модуле, который и решает эти вопросы )))
Или я что-то не так понял? Поправьте плиз если что.
>На самом деле используя в контроллере методы модулей (пусть это будут те же А и В) А->get_data() и B->get_data() — я не думаю о том, насколько актуален кеш и откуда вообще берутся данные.
Я про это и говорю. Клиент должен просто получать данные, а время хранения (валидности) сохраненных данных — это забота того, кто сохраняет, а не того, кто читает эти данные.
Ну, так и я о том же =) Может просто недопоняли друг-друга
Подолью еще немного огоньку в обсуждение
Так все-таки модули A и B определяют время жизни кэша? Из приведенной выше фразы следует так. Как по мне, если мы храним в кэше собственно данные (не сгенерированный output в виде готового HTML или чего-то подобного, а чистые данные), то они должны быть постоянно актуальными (исключение разве что если там есть часто меняющаяся статистика, которую имеет смысл обновлять с некоторыми интервалами). Например, хранится в кэше последние 10 комментариев блога. При написании комментария автоматически производится перезапись в кэш новых значений.
Модули А и В действительно определяют время жизни кеша, но каждый в своем контексте.
Что значит актуальность данных? Думаю, в данном случае критерий актуальности данных — это лайфтайм кеша, который опять же может быть разным в зависимости от контектса модуля. Что для одного актуально, для другого устарело и он это обновляет. А следующему дергающему данный кеш модулю все равно, изменилось там что-то или нет, т.к. у него свой критерий актуальности и он сам решит что делать. В случае, если модули могут как-то по-особенному работать с кешем (может как-то модифицировать его и т.п.) — то я бы кешировал данные для модулей отдельно.
Если честно не вижу никаких проблем здесь или противоречий.
2Бубнов Славик:
>Модули А и В действительно определяют время жизни кеша, но каждый в своем контексте.
Бред. Теряется весь смысл кеша, если каждый клиент будет обновлять его тогда, когда ему захочется. Кеш для того и предназначен, чтобы хранить данные какое-то время, а не запрашивать их постоянно из базы, например.
>Что для одного актуально, для другого устарело и он это обновляет.
Да не должен он решать устарели данные или нет. Модуль должен получить данные, которые ему дали, и обработать их. А откуда они полученны (кеш или баз), модуль даже знать не должен.
Хотел прийти к какому-то пониманию, но выходит какой-то холивар )))
Что одному «бред», другому вполне понятно и подходит )))
Я, лично, нормально смотрю на эту логику, пусть она и отличается от стандартных мехнизмов кеширования, к которым все привыкли, как к любимой кружке для чая/кофе
Считаю необходимым в таком случае вернуться к написанному мною ранее:
> В любом случае все легко можно заточить под себя, если кто-то считает это неудобным =)
Может хватит уже бороться с этим странным изобретением, носящим такое липкое название — кэш?
Уверен — оно не заслуживает того…
Ведь на самом деле — что такое кэш? — Некоторый блок данных в текстовом формате…
Так положите вместо него файл данных SQLite и сбрасывайте туда то, что называете кэшем, и обновляйте его напрямую — затраты на все это гораздо меньше, чем на кеширование плюс масса других положительных моментов
А еще лучше — использовать разделение всех данных ресурса на оперативные и постоянные, ну и соответственно разделить при этом нагрузку между MySQL и SQLite.
@Zares
Можете кинуть в меня камнем, но ведь по сути использование SQLite — то же кеширование, только с использованием другого средства для хранения…
(но ведь по сути использование SQLite — то же кеширование, только с использованием другого средства для хранения…)
…но с прямым доступом для оперативного обновления и при этом — значительно меньшим потреблением ресурсов системы…
Ну во-первых: кто сказал, что кеш — это текстовые данные?
Это может быть и объект, и класс, и изображение и т.д.
Во-вторых, SQLite будет очень проигрывать тому-же мемкешу, а при нагрузках вообще может положить систему.
В третьих — использовать SQL-базу для кеша бессмыслено. С таким же успехом можно использовать MySQL с типом таблиц MEMORY.
Кеш нужен, в первую очередь, для ускорения работы системы. И тут любая база, включая SQLite, будет очень сильно проигрывать обычным файлам или, тем более, мемкешу.
Да, многие нагруженные веб-приложения на некоторых серверах испытывают трудности с производительностью, и это связано не только с доступом к данным в MySQL.
Кстати, не мне объяснять то, что «положить» сервер не составит труда и без БД
Главная причина этой проблемы состоит в неразумном построении логики приложения.
Мало того, что PHP-интерпретатор трудится изо всех сил, собирая (по сотни, тысячи раз в секунду) в кучу все, что нужно для того, чтобы склеить и выдать «нагора» элементарный HTML, в том числе и, винимая это из базы данных… видители, потому, что однажды программисту таким путем было на пару часов быстрее завершить работу над скриптом а затем это стало стандартным подходом!
Во-вторых — в большинстве случаев отсутствует оптимальное структурирование данных, хранящихся в БД.
Ведь не проблема выдать одни и те-же наборы данных сотням, тысячам клиентов…
Проблема в том, что, когда один запрашивает данные — десятки-сотни других в этот момент обновляют их!
Попробуйте в таблицу с записями добавить поле счетчика количества просмотров плюс поле даты последнего просмотра статьи, например…
Да, ну зачем вам об этом думать, ломать себе голову над какими-то…, когда есть простая палочка-выручалочка — кэширование.
Вот только, со временем, оказывается, что это, та-же система в системе, с теми-же вопросами, что и в структуре-родителе…
Но вот когда дело доходит до использования МЕМКЕША, особенно, например в работе со скриптом на CodeIgniter — тут я спокойно, молча, тихо удаляюсь…
2Zares: как-то много воды и ничего по сути . Вы писали сайты с большими нагрузками? Подскажете, как сделать многопользовательский блог с комментированием (древовидным) и т.д. Чтобы без кеширования держало 150000-200000 уникальных пользователей в сутки и около 2 000 000 просмотров. Если скажете — буду рад научится подобному.
@aktuba
О таких вещах не говорят — их просто делают.
Нет, ошибаюсь — говорят …когда не получается сделать
2Zares: ну это вы зря… Покажите, расскажите — мне действительно интересно (только не предлагайте переводить все на html/ssi). Просто я занимаюсь подобным сайтом и было бы полезно разгрузить его.
Вот только у меня кое-какие сомнения… Фраза «Но вот когда дело доходит до использования МЕМКЕША, особенно, например в работе со скриптом на CodeIgniter — тут я спокойно, молча, тихо удаляюсь…» говорит о том, что вы не работали с подобными нагрузками. Надеюсь я ошибаюсь .
@aktuba
Да нет, по-видимому Вы меня не правильно поняли!
Я не разработчик — я из тех, кто эксплуатирует, и я скорее ищу того, кто сделает то, что мне нужно и при этом — так как мне нужно, а не так как удобно, собственно, разработчику…
Скажите, кто Вас учил писать веб-приложения? Кто Вас обычно консультирует в процессе разработки и дает необходимые рекомендации? Вы используете свой индивидуальный подход в решении стандартных задач?
>Я не разработчик — я из тех, кто эксплуатирует, и я скорее ищу того, кто сделает то, что мне нужно и при этом — так как мне нужно, а не так как удобно, собственно, разработчику…
Чаще всего это неверный подход. Лучше давать концепцию разработчику, а реализацию пусть делает он. Конечно бывают исключения, но…
По поводу меня — тут все сложно =). Я начинал как разработчик десктоп-приложений, а на веб-разработку перешел по необходимости =). Консультации… Пара форумов и несколько друзей — отличных разработчиков. Например, Александр Макаров (rmcreative.ru).
У меня за долгие годы работы в WEB сложилось такое впечатление, что те программисты, которые пришли в веб-программирование из С++ или JAVA имеют несколько предвзятые представления о реализации тех или иных концепций построения веб-приложений.
Почему-то в большинстве случаев ограничиваются использованием MVC паттерна, возможно потому, что подобное ранее использовали в построении GUI десктопных приложений…
Ну и, возможно, не совсем корректно говорить об этом в данной теме, на этом блоге, но все-же, как Вы относитесь к не MVC системам, flourishlib вчастности?
Скорее всего вы правы, в большинстве случаев. Но, как ни странно, я, в данном случае, исключение =), хотя именно MVC мне близко, т.к. мне очень нравится Delphi.
Все просто — взгляды на какую-то технологию/реализацию очень зависят от опыта работы. Если человек писал простенькие утилиты — вряд ли ему вообще известно понятие MVC. И наоборот — если человек занимался проектированием довольно серьезных приложений, то MVC (или что-то подобное) само появляется .
Если же взять за основу именно мой опыт, то использовать Model-View-Controller я начал очень поздно в вебе. Да и сейчас я использую немного иначе данную концепцию, не так, как этому учат в многочисленных статьях =).
А по поводу flourishlib — даже не знаю, что это такое.
А как использовать например memcached в kohana 3?
На github’е есть модуль Cache.
2KotDev: а в чем сложность-то? Что-то я вопрос не понял…
Сложность в том что нет официального модуля для кэша. А установив тот модуль с github’a получил такую ошибень
ErrorException [ Warning ]: Invalid argument supplied for foreach()
SYSPATH/classes\kohana\arr.php [ 213 ]
208 public static function merge(array $a1)
209 {
210 $result = array();
211 for ($i = 0, $total = func_num_args(); $i $val)
214 {
215 if (isset($result[$key]))
216 {
217 if (is_array($val))
218 {
Пардоньте парни, ставил модуль от некого Nergal’a он и выдал ошибку. Этот же работает. Спасибо
Писец, я думал только политики срутся как сабаки
Хотел бы высказаться «в защиту» Бубнов Славик и девелопера Kohana.
Я уверен что это очень хорошо, что время жизни хеша оставлено «на откуп» клиенту-модулю. Бывают ситуации когда этот хещ нужно обновлять 1 раз в неделю а то и в месяц, а бывают ситуации когда его нужно обновлять 1 раз в час. При описанном Бубнов Славик подходе к делу в нужном модуле (класе, методе) меняеш циферю и вуаля.) Интересно как выкручиватся если у тебя лайтайм забит жестко где то в ядре и ты с модуля не имееш даже понятия откуда данные берутся? Думаю что скорее всего этим минималистическим выиграшем народ.ру пренебрегает …
И еще раз, «Программеры всех стран, классов, методов и фреймворков — ОБЪЕДИНЯЙТЕСЬ». Хорош мерятся … сами знаете чем. Работы всем хватит, бери да делай.
@Юрец
1. Все же обычно одни и те же данные имеют постоянный lifetime. Ну как может быть, что в одном модуле кэш последних десяти комментов считается актуальным в течении 1 минуты, в другом и 10 минут не предел? Данные они и есть данные, они одни и те же.
2. А модуль и не должен знать, откуда данные берутся (из кэша или нет, стоит ли им доверять и т.д.) — он их просто запрашивает. А источник данных уже сам анализирует, есть что-то стоящее в кэше, надо ли запросить БД и т.д.