Как стать автором
Обновить

Комментарии 60

Исправьте: «часть», а не «чась»
В практической части наверно нужно привести примеры реализации.
Простой пример кэша «ручками» для статики:
У нас есть какая-то директория, защищенная на чтение для пользователя (.htaccess).
Пользователь запрашивает какой-то урл (как известно он уникальный)
Хэшируем урл md5 получаем хэш
Проверяем, есть ли в директории файл с именем хэш или хэш.gz
Файл есть — выдаем с нужными заголовками
Если файла нет — при помощи ob_start() и его поддерживающих функций собираем весь код страницы.
Жмем если надо весь код gz со степенью сжатия 6 (наиболее оптимально) получаем ужатый весь код
Записываем ужатый весь код в директориия/хэш.gz или директориия/хэш
Выдаем пользоветелю ужатый весь код или весь код

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

К сожалению, в своих статьях о кэшировании ты рассуждаешь как теоретик — сразу видно отсутствие практического применения. Теперь по пунктам:

Что нужно кэшировать
кэшировать нужно абсолютно всё. В твоём примере данные извлекаются за 0.1 секунды, а из кэша отдаются за 0.2. Проблема в том что тест синтетический — на нагруженном проекте данные будут извлекаться за 0.9, а из кэша по прежнему отдаваться за 0.2, разумеется это зависит от того какие именно данные и куда производится кэширование, будем считать, что мы правильно определили куда кэшировать эти конкретные данные, и даже при этом тайминги будут различаться примерно так. Суть в том, что в твоей теории ты забываешь об окружении, а окружение — это уже практика.

Куда нужно кэшировать
Память — это очень правильно. Для кэширования объектов. Тут нет замечаний.

кэширование в файловую систему.
Во-первых, смотрим сюда en.wikipedia.org/wiki/Ext2 — ты говоришь о лимите файлов — теоретический лимит там указан как 1.3 умножить на 10 в 20 степени. число 32768 — это максимальное количество директорий внутри директории, но не файлов.
Так или иначе если в генерации страницы участвует 100-300 объектов (каждый из которых закэширован в файловую систему в виде отдельного файла) на нагруженном сервере эта генерация займет значительно больше времени чем вычитывание этих объектов из памяти — почему больше написано чуть ниже про файловые бд.

Файловые базы данных — TDB, SQLite, DB4
На действительно нагруженных проектах сервера выполняют невероятное количество операций с диском, особенно если часть статики крутится на одном сервере с пхп. И любое обращение к памяти «под нагрузкой» будет в «сто раз» быстрее чем обращение к диску, так как диск постоянно занят. Но попробуем пренебречь этими фактами и допустить что на самом деле данные меняются один раз в сутки, после изменения данных мы генерируем кэш и работаем только с ним оставшиеся 23 с копейками часа — это как раз теория. На практике нет — данные меняются очень часто. Поэтому кэширование в файлы будет работать лишь очень короткое время, затем вся польза такого кэширования будет сведена на нет.

О твоем развернутом примере.
Во-первых — 50 000 статей это мелочь, это такая мелочь что не стоит и думать о времени извлечения одной статьи из базы. Думать стоит о построении коллекций, но даже об этом при правильной реализации хранения в базе думать не приходится — ведь хранить сам контент по которому не строятся коллекции в одной таблице с временем публикации глупо. Во-вторых, приведенная схема, основанная на времени изменения таблицы в базе мне очень знакома, и ты сам знаешь почему. К сожалению она ущербна, как ты и написал, инвалидация кэша происходит при изменении одного итема. В-третьих поддержание зависимостей на уровне пхп кода достаточно сложная задача для программиста и не поддается автоматизации — пробовали, знаем. Итого: пример совершенно не разъясняет сути стратегии и является глубоко теоретическим.

О том «на что нужно обратить внимание»
Про кэширование в файловую систему уже выше написал. кэширование разных объектов нужно просто организовывать так, чтобы при формировании хеша использовался и айдишник объекта и его имя. Далее — твоё утверждение, что основная нагрузка приходится на главную страницу — абсолютно неверно. Главная страница, как правило, кэшируется и очень быстро отдаётся, настоящая нагрузка распределена по всем остальным страницам сайта, в этом и заключается основная проблема упреждающего кэширования и сильно распухших кэшей — мы никогда заранее не знаем на какую именно страницу сайта придет пользователь, или робот поисковой системы. В результате тратим время на генерацию этих страниц и кэшируем редко запрашиваемые страницы, получая распухший кэш и настоящую нагрузку на сервер. Твой вариант с периодическим удалением всего кэша в автоматическом режиме не реализуем. Сейчас ты можешь сказать, что кэш можно удалять в зависимости от того сколько места он занимает на диске, сколько времени прошло с последнего удаления и так далее, но все это не более чем костыль и к стабильности отношения не имеет.
а вот если бы были примеры практической реализации, то вышеприведенные проблемы автор бы сам заметил.
Спасибо за статьи, интересно.

По поводу того, что кэшировать постоянно изменяющиеся данные — не целесообразно — немного не соглашусь, тут есть нюансы.
Если получить данные рессурсоёмко, а запрашивают их очень часто, например 100 раз в секунду, то может смысл и их кэшировать, например, кэш на 1 секунду. При этом рессурсоёмкая операция будет выполняться 1 раз в секунду, а остальные 99 — быстро. А от того, что данные могут быть актуальны по состоянию на 1 секунду назад — не всегда важно.

Повторюсь, это не правило, а лишь частный случай, который показвает, что даже динамические данные может иметь смысл кэшировать.
Ещё добавлю

> можно положить полностью созданную главную страницу в память и отдавать её

Да, о таком способе когда-то писал Spectator. Предлагалось использовать в качестве ключа кэша URI страницы. Способ не для всех проектов, но по своему хороший.
Не забываем про GET/POST и динамические блоки страницы, которые зависят от серверных параметров и событий, иначе может получиться что пользователь не увидит, ну например, смены дня/ночи.
Я написал, «Способ не для всех проектов, но по своему хороший».
Да, было немного не правильно выражено. Я исправил.
Ну, или если вы все-таки каким-то чудом настроите у себя FastCGI

Автор, если у вас есть какие-то проблемы с настройкой FastCGI, то это не значит, что они есть у других.
Кстати, в MySQL существует Engine MEMORY, которая вроде тоже использует для таблицы память.

Подтверждаю, она действительно использует память :)
Вообще это чисто моя идея, но предполагаю что не я один её придумал, хотя реализаций я не видел.

Никто не спорит, что это чисто ваша идея.

Ну а вообще спасибо за статью, посмеялся :)
Спасибо, я внес соответствующие поправки. Рад, что вас развеселил.
Напишите свою статью про кэш, чтобы все прочитали и заапплодировали.
А то кричать о собственной осведомленности могут многие, а решиться что-то написать почему-то не могут.
Поэтому и приходится радоваться тому, что есть.
Удивительно. Давно не видел таких внятных комментов с таким количеством минусов :)
Мне одному кажется, что пост откровенно слабый, с кучей общих слов и совсем без конкретики?
просто это пост для тех, кто ещё не «занимался» кешированием. Для людей с начальным уровнем, вполне полезный пост.
Боюсь, что людям с начальным уровнем этот пост может добавить непонимания. Автор как-то очень лихо свалил в одну кучу кеш SQL, memcached и файловый кеш. Все эти три способа могут применяться одновременно и для разных (!) целей.

То что написано про memcached это, простите, откровенный бред. Читать про то что это такое и зачем нужно лучше из первый рук.
> могут применяться одновременно и для разных (!) целей
Не понял вас. Я где-то сказал, что должно применяться только в отдельности и для одной и той же цели? Довод неуместен.

> memcached это, простите, откровенный бред
Будте добры, аргументируйте свои слова. Я положительно настроен на конструктивную критику, если вы сможете объяснить, почему вы так считаете — и соглашусь и исправлю написанное.
По первому пункту. Просто нельзя так сваливать в кучу все типы кеша. А уж если свалилось, стоит написать для каких целей уместно использовать тот или иной способ.

Второй. www.danga.com/memcached/
НЛО прилетело и опубликовало эту надпись здесь
Та часть была откровенно безграмотной и провальной. Я до сих пор в недоумении, почему сообщество ее так высоко оценило. Думаю, это объясняется «крутым названием»: Теория кэша.
Если вчитаться — понимаешь, что автор плохо понимает то, о чем пишет (касается не только кэша и его теории(???), но и ЯП). В своих постах в прошлом топике я свое мнение аргументировал. Наше обсуждение статьи с автором вы можете прочитать, если захотите.

НЛО прилетело и опубликовало эту надпись здесь
Сообщество оценило актуальность темы и не более. То есть, оценками дали понять, что тема востребована.
Т.е. судило по названию топика, но никак по его содержанию (потому что не читало?).
Я как раз про это и говорю: за умным названием скрываются пространные рассуждения, порой, ошибочные и неграмотные.
Странная оценка.
Ну, во всяком случае, лучше ничего нет. А для размышлений на первое время пойдёт :)
Взяли бы и написали что-то грамотное, правильное. Это же теория. А их доказать ещё нужно. Вот слово «практическая» часть, конечно зря написано было изначально.
Я не признаю такой критики как «плохо», «слабо», «вяло» и так далее. Скажите, с чем конкретно вы не согласны. Кажется весь пост — слабым — флаг вам в руки — напишите такой, который бы не был таковым. Я только обеими руками за.
При кэшировании в файловую систему нельзя весь кэш пихать в одно место. То есть для каждых отдельных объектов лучше использовать свой директорий, например для страниц /cache/pages, для пользователей /cache/users и так далее.


В таком изложении это напоминает народную примету. Думаю, подобные вещи стоит описывать развёрнуто.
«Memcached нужен больше для обмена данными между приложениями»
Не только. Мемкэш хорошо подходит для распределенного кэша (по нескольким серверам).

«Файловая система. Наиболее надежный и быстрый способ.»
Быстрее памяти?
> Мемкэш хорошо подходит для распределенного кэша
Да, я это и имел ввиду. Опять плохое выражение. Спасибо, что обратили внимание.

> Быстрее памяти?
Знаете, говорите что хотите, но когда я проверял работоспособность memcached (речь только о memcached), оно показало, что обращение к нему чуть-чуть быстрее, чем к файловой системе. Тут ключевое слово «И». Да, я считаю, что файловая система — наиболее надежный И быстрый (в совокупности) способ.
Memcached отлично использовать для тяжёлых запросов, часто возникает необходимость выгрузить данные в кеш которые к примеру часто используются но которые можно обновлять с определённой периодичностью — почемуто только для множества серверов? Я боюсь с такой категоричностью как раз таки и новичков вы введёте в заблуждение.
С файлами — известно что include это очень тормозная операция, особенно когда их много, а в случае с кешем часто бывает что нужно раскидывать различные данные в кеш чтобы легче было с ними манипулировать.
Файловый кеш неплохой вариант для сайтов где нет возможности установить memcache — к примеру для массовых решений (например софт который обязан работать на всех серверах).
«Да, я считаю, что файловая система — наиболее надежный И быстрый (в совокупности) способ. „
А как вы измеряли надежность представленных способов?
Просто. После перезагрузки сервера Memcached данные насколько я знаю теряются. Поправте меня, если это не так. А с фалами такого не будет. Только исходя из этого.
Тогда я бы на другую чашу весов добавил то, что за файлами вам надо приглядывать самому, а мемкэш удаляет устаревшие ключи без вашего участия. Поэтому его надежность выше.
Хорошо, вы меня убедили.
Както я использовал файловый кеш для кэширования.
Это было давно, никаких APC и не было.
Время жизни кеша было от 20 секунд до 2х часов.
Есно дело файлы не стирались, просто при фетче filemtime проверялось.
Через три года работы в папке было 160гигов и стиралась она ПОЧТИ ТРИ ЧАСА(тоесть под миллион гдето файликов)!

Сейчас файловый кеш я использую только для подсистемы mirror
Снегерили страничку для человека(неавторизованного)- сохранили.
Снегерили страничку для пользователя(авторизованного) — удалили
Надо выдать страничку, но зашел робот или сайту кирдык(админ «мучиет» базу данных\мемкешед грухнулся\апача 502...) — выдали ее из кеша.

Сайт(мой) сам по себе может выдавать гдето 200-300 страниц в секунду(конект к базе, сборка страницы и тд)
Файловый кеш может выдавать тысячи и при этом ковыряться в носу.
Как не странно 70% посетителей сайтов — это роботы (я то знаю).
Выдавайте им страницы из файлового кеша до конекта к базе, а лучше прям нгинксом и нагрузка на сервер упадет на 70%…
70% это дохрена!
НЛО прилетело и опубликовало эту надпись здесь
Предвижу трилогию автора по кэшу. Жду =)
Танго и Кэш =) Вскоре следует ожидать статью под названием «Теория Танго»! Заранее извиняюсь за мой искрометный юмор!
А по существу, мне было бы намного интереснее узнать про организацию системы кэширования в распределенных средах и что делать с кэшированием при конкурентных запросах. Может быть в третьей части?
Самое интересное там, насколько я понимаю — « не сразу устаревающий» кэш.
Извиняюсь за нескромный вопрос… там это где?
В кэшировании распределенных сред
Уважаемый, enartemy, я прочитал вашу второю статью. Прочитал не один раз, как и первое ваше творение на эту тему.

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

То, что не надо кэшировать все подряд — согласен. Остальную часть я вам предлагаю удалить.
Главным аргументом в пользу кэширования должна служить не скорость изменения или вывода информации, за размер затрат на получение и вывод информации.
Как я уже писал вам в прошлой статье, многие системы предоставления отчетов, статистики работают долго. Чем долбить несчастный сервер чудовищными запросами пользователей, проще иметь под рукой кэш запросов, хоть в файле, хоть в памяти. Этот кэш будет переодически обновляться. С одной стороны, пользователям не надо ждать по 10-20 минут, пока сервер потеет и тужится выдать результат, выполняя десятки ресурсоемких однотипных операций. Есть и минус — данные в кэше будут всегда немного устаревшими.

Кроме этого к ресурсоемким процессам относятся обращения к внешним ресурсам, использующим установку соединения (сокеты, ...)

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

Память. Это memcached, APC, XCache
Если вы пишите для новичков, расскажите, что это. Потому что ваша статья для знающих людей — бесполезна.

База данных.
Я вообще ничего не понял. Вы предлагаете использовать БД для хранения экша, или говорите о кэшировании запросов и помещении таблиц в память? Какая-то манная каша повисла на абзаце.

Как нужно кэшироватьМного слов ни о чем. Опять теория и рассуждения.

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

А лучше представьте рабочие примеры, которые применяются в web-разработках с тестами внутри. Заодно и каша в вашей статье пропадёт.
Вот я тоже уже думаю, что без рабочих примеров статья выглядит кашей. Для меня это естественно не так, но что уж поделать.
Уважаемый, yaneblog.

> То, что не надо кэшировать все подряд — согласен. Остальную часть я вам предлагаю удалить.

Смотрите. Данные изменются 1 раз в секунду. Данные извлекаются 1 раз в 2 секунды. При получении данных всегда будет необходимо их обновление — никогда не получится так, что мы можем взять данные из кэша. Смысл? Процесс протекает за 0,01 секунды. Кеш срабатывает 0,02 секнуды. Нужно кешировать?

Если я удалю вторую часть — тогда будет действительно каша. «не надо кэшировать все подряд» — а что конкретно не надо-то.

> Этот кэш будет переодически обновляться.
Это называется кеширование по времени, я упоминал про него в прошлой статье.

> Сокеты быстро работают, очень быстро.
Для меня быстро — это тысячные доли секунды. Сокеты работают десятые доли секунды. Да быстро, если опреровать объемами 10-20 минут, но эти времена не применимы к генерации веб-страницы на-лету. Это же касается «применение кэша только из-за того, что устанавливается соединение нецелесообразно» — иногда и это бывает критичным.

Поймите, это Веб. Здесь нет 10-20 минут. Будете вы 20 минут ждать, пока страница хабра откроется? А вы представте только какая нужна база данных и сколько должно быть к ней запросов, что бы отобразить кждай кусочек страницы. И что же, она гененрируется 10-20 мин? Если она 10 сек генеритья, это уже будет раздражать.

> Если вы пишите для новичков, расскажите, что это.
Я не могу рассказывать вообще все, чтоб вообще все всем было понятно. Это невозможно. Что уж вы так плохо о людях думаете, они не могут найти сами информацию, если их это заинтересовало?

> База данных. Я вообще ничего не понял.
Я говорил о применении базы данных для хранения закешированных результатов.

Уважаемый yaneblog, вы тратите уйму времени, что бы прочитать это все, осмыслить и высказать все ваши многочисленные замечания. Используйте это более разумным способом — напишите об этом статью. Хорошую. Развернутую. И без каши. Назовите её, если хотите, разумным ответом на мои выдумки — я не обижусь. Тогда может у нас и получится диалог. А пока — это спор слепого с глухим.

А, вот и мой пропавший коментарий… Странно, он появлся спустя неготорое время. Глючит хабр, глючит…
это кэширование вывода =)
Блин… Вторй за уже така ситуация — пишу коммент, где все расписываю, а потом он пропадает, причем первый раз было в прошлой статье… Ладно, смысл такой.

Уважаемый yaneblog. Я посмотрел ваши статьи, мне они понравились. Ну так чем со мной спорить, — серьезно — напишите свою статью об этом. Хорошую. Развернутую. Без каши, как у меня. Заодно я увижу насколько вы хорошо разбираетесть в проблеме. Это совершенно без прикола. Тогда есть смысл продолжать полемику, а пока — это спор слепого с глухим, потому что вы считаете — что я не разбираюсь, а я считаю — что вы не разбираетесь.

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

Жду вашей статьи.
Пропадания комментов при их отправке, это ужасно. Сам пару раз так обламывался.
Хорошо, я напишу статью с примерами из производственной практики.
ноут за такую статью не получить =)
Я полагаю, автор старался не за ноутбук. Работа проделана, работа спорная, но как говорил один великий человек — «в споре рождается истина». Спор есть, будем рожать истину :)
кармадрочеры атакуют
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
>Использование БД для кэша мне представляется редким вариантом. >Это больше возможность, нежели практическое применение.
Тем не менее, столкнулся с ней как-то раз воочию. Часть логики была вынесена в PL/SQL хранимые процедуры, и кэшировались результаты этой части как раз в базу.
НЛО прилетело и опубликовало эту надпись здесь
посыл не тот

главное не инструкция, а мозги у имплементирующего. Кеш это как дикая рекурсия — проблемы никогда не видно невооруженным глазом, надо ясно представлять что делают железки по вашему заказу.
тут многие пишут, что «статья слабая» и «много воды». и они — правы.

1. совсем не понимаю, как кэшировать в файле всю сериализованную таблицу вообще могла прийти в голову?

2. нужно сразу определиться, какие у нас нагрузки, сколько у нас серверов и какие объёмы данных. например, если мы кэшируем данные в файлах, но в file system cache нашей операционной системы они все не помещаются, то производительность резко упадёт, а (на хоть сколько-нибудь загруженной системе) винчестер через несколько недель тупо выйдет из строя.
ещё нужно определить узкое место — веб-машина (которая генерирует страницу для клиента) или база. ведь кэш мы можем наращивать сколько угодно, а вот mysql при более чем 500 (ну, тысяче) запросах в секунду работает уже не всегда и не у всех. далее я буду предполагать, что процессора нам не жалко, а базу — жалко.

3. и почему цифры приведены такие странные? понятно, что они «демонстрационные» и «для наглядности», но нельзя наглядностью оправдывать взятые совершенно с потолка цифры.
запрос к мемкэшу выполняется порядка 0.001 — 0.01 сек. зависит от задержки в сети.
запрос к базе выполняется, конечно, дольше. не забываем про то, что к БД нужно подключиться, а БД должна ещё сделать выборку из своей системной таблицы с пользователями и проверить ваш пароль (а если это mysql, настроенная каким-нибудь жопоруким кретином, то ещё и сделает запрос на получение символического имени того хоста, к которому вы к ней обращаетесь) — это в том случае, если без persistent. И, вне зависимости от того, persistent ли соединение или нет, БД будет делать выборку по таблицам привелегий на базу данных, на таблицу, к которой вы обращаетесь, и на колонки этой таблицы — всё это занимает время.

4. вообще, стандартная стратегия кэширования довольно проста и работает в 99% случаев.
запросы вида «select * from table where id=123» — кэшировать с ключом table_123. при update/delete из кэша — удалять.
запросы вида «select * from table where some_field=r5283r78» — либо не кэшировать, либо поменять на «select id from table where ...» и далее выбирать уже эти id'ы с помощью мемкэшевского multiselect'а и (если там чего-то не оказалась) второго запроса к базе, складыя его результаты в кэш тоже.
сложные поисковые запросы либо не кэшируются вообще, либо (если это критично) кэшируются на небольшое время (с ключом типа «search_».md5(serialize($serachParams))), но кэш таких поисков никак не обновляется.
а, да.
APC, естественно, быстрее, чем Memcache. раза в 2, насколько я помню. мемкэш работает через сокеты, а APC — через shared memory. НО: у APC кэшированные объекты хранятся с помощью односвязаного списка, т.е. время операций с кэшем линейно зависит от количества объектов. и, если закэшировать 10000 объектов (которые могут быть мелкими и занимать даже меньше 128 мб), то мемкэш начнёт серьёзно обгонять APC. в мемкэше всё хранится с помощью хэш-таблицы и, вероятно, какого-то дерева в случае хэш-коллизий. время в худшем случае пропорционально логарифму от количества объектов, что в реальном мире означает константу.

у XCache такой проблемы, как у APC, нет.

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

ещё раз извините.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории