// codeart.ru / Статьи / Кэширование в WordPress (1/3) Форум

Кэширование в WordPress (1/3) rss подписка

Автор: Evgeny Sergeev

До сегодняшнего дня я особо не задумывался над тем как в WordPress организовано кэширование данных. Нет, я конечно знал о замечательных плагинах wp-cache и wp-super-cache, но до конца механизм их действия не представлял. Кроме этого я к своему стыду не знал о существовании встроенного WordPress Object Cache. А так же чем встроенный кэш отличается от плагинов. Думаю, что пришла пора разобраться с этим вопросом.

Я планирую написать серию из трех статей на тему WordPress кэширования, в первой статье коротко опишу какие возможности существуют в WordPress для организации так называемого расширенного (advanced) кэширования, а так же объясню в чем разница между кэширующим плагином, и WP-object-cache. Во второй статье более подробно разберу устройства плагина wp-cache, а в третьей затрону вопрос кэширования статических ресурсов, таких как css-файлы, картинки и JavaScript-ы.

Но давайте обо всем по порядку.

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

Первая часть отвечает за проверку наличия данных в кэше и их загрузку. Важно понимать, что если данные в кэше присутствуют, то вторая часть алгоритма не выполняется. Я наиболее часто работаю с кэшированием на уровне шаблонов страниц, когда в кэш попадает либо вся страница полностью, либо какая-то ее часть. При таком способе кэширования, скрипт по загрузке данных располагается в самом начале основной программы. Если страница сохранена в кэше полностью, то возможно оптимизировать загрузку страницы на уровне http протокола (например, используя заголовки expire и etag ). Кроме этого, кэшировать данные можно на уровне объектов или запросов в БД, тогда обе части алгоритма реализуются в месте использования объекта.

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

Разработчики WordPress не стали отходить от описанной выше схемы и предусмотрели возможность кэширования как на уровне объектов (WP Object Cache) так и на уровне страниц (расширенный механизм кэширования).

Для того, чтобы запустить механизм расширенного кэширования, нужно определить константу ‘WP_CACHE’ – “define(‘WP_CACHE’, true);“. Чтобы понять как она влияет на работу WP, давайте посмотрим на код непосредственно относящийся к этой константе:


// For an advanced caching plugin to use, static because you would only want one
if ( defined('WP_CACHE') )
@include ABSPATH . 'wp-content/advanced-cache.php';

Это код располагается почти в самом начале файла wp-settings.php, и выполняется до установки соединения с БД и инициализации основных параметров WP. Когда я первый раз увидел его, ко мне в голову пришла мысль, что файл advanced-cache.php уже существует. Но данное предположение оказалось ошибочным – файл необходимо либо создать самостоятельно, либо установить плагин который сделает это за вас.

Другой кусок кода, относящийся к кэшированию данных так же оказался в wp-settings.php, но уже ближе к концу, и выглядит он примерно так:


if ( defined('WP_CACHE') && function_exists('wp_cache_postload') )
wp_cache_postload();

Функция wp_cache_postload выполняется после того как будут загружены все данные и выполнены все плагины. Это делается потому, что плагины могут изменить содержание загруженной информации. Логичнее всего эту функцию определить в файле advanced_cahce.php. Хотя, опять же, никто не заставляет делать именно так.

Из всего вышесказанного делаем вывод, что первая часть алгоритма кэширования должна быть определена в файле advanced-cache.php, а вторая в функции wp_cache_postload(). Забегая вперед, скажу, что плагин wp-cache так и поступает, у него есть файл wp-cache-pahase1.php, на который создается символическая ссылка с файла advanced_cache.php, а также файл wp-cache-phase2.php, который подключается в функции wp_cache_postload(). Более подробно о том как устроены эти файлы расскажу во второй статье про WordPress кэширование.

Теперь давайте подумаем, зачем нужен расширенный алгоритм кэширования, если в WordPress уже существует Object Cache? Исходя из названия нетрудно предположить, что встроенный в WP механизм кэширования служит для сохранения состояния объектов, а не готовых HTML-страниц. А если быть еще более точным, то данный механизм сохраняет только результаты выполнения SQL запросов.

Чтобы запустить WordPress Object Cache, необходимо определить константу “ENABLE_CACHE” – define(‘ENABLE_CACHE’, true);. После чего в директории wp-content следует создать папку cache, при этом для данной директории важно выставить права на запись пользователю от имени которого работает Веб-сервер. При работе с данным механизмом используются функции: wp_cache_set(), wp_cache_get(). Так как я не планирую более подробно писать об Object Cache, рекомендую ознакомиться со статьей Using the WordPress Object Cache.

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

  1. Интересные и полезные ссылки v.4
  1. А я вот до сих пор не ставил плагины кеширования: не совсем понятно, что будет происходитьс php кодом в шаблонах, имею в виду мой личный код

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

    Бывают разные типы кеша: файловый кеш, кеш в базе, кеш в memcached. Тоесть все завесит от того, что мы выбираем как хранилище кеша. Этот выбор будет разным, в зависимости от задачи.

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

    Ну и естественно, какие-то части страницы могли изменится пока страница лежала в кеше.

    На самом деле в проектах чаще всего используют кеш разнообразных блоков, кеш страниц полностью – это плохое решение.

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

    К чему я это вел – не в обиду – но понимание об общей теории кеширования у тебя не правильные. То, что подходит для WP не подходит в общем случае для большинства проектов.

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

    Во-первых кэш страницы полностью – это идеальный случай, так как только в этом случае можно полноценно использовать механизмы заложенные в http протокол!

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

    Задача проекта не влияет на алгоритм кэширования, на алгоритм кэширования может влиять только скорость обновления данных (динамика) на странице. Например, форум с одним новым сообщением в месяц замечательно поддается кэшированию (как на уровне страницы так и на уровне запросов в БД), а тот же форум с 1 сообщением в секунду нет!

    Говоря, что алгоритм кэширования делиться более чем на две основные части (или фазы) не плохо было бы привести примеры этих фаз. В противном случае – это голословное утверждение!

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

    Опять же пугающая бессмысленность фразы “Обновления данных в кеше – это вопрос либо времени, либо программной реализации”. Что ты имел в виду под этой фразой остается для меня загадкой!

    В заключение, Станислав, у тебя очень много фраз смысл которых теряется из-за твоего желания выразиться красиво. Например “общее понимаени теории кэширования у тебя неправильное” – это что за зверь такой “общая теория кэширования”? Надеюсь, ты понимаешь, что общий случай и общая теория – две разные вещи?

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

  4. Во-первых кэш страницы полностью – это идеальный случай, так как только в этом случае можно полноценно использовать механизмы заложенные в http протокол!

    Как много действительно полезных для пользователя проектов, где можно применить кеширование страниц полностью? И что это за “в этом случае можно полноценно использовать механизмы заложенные в http протокол”. Что это за магические механизмы?

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

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

    Задача проекта не влияет на алгоритм кэширования, на алгоритм кэширования может влиять только скорость обновления данных (динамика) на странице. Например, форум с одним новым сообщением в месяц замечательно поддается кэшированию (как на уровне страницы так и на уровне запросов в БД), а тот же форум с 1 сообщением в секунду нет!

    Тут ты прав – я не правильно выразился – вопрос не в задачах проекта, а в частоте обновления данных (мой косяк, надо четче писать мысль, хотя я это и подразумевал, что важно обновление данных).

    Говоря, что алгоритм кэширования делиться более чем на две основные части (или фазы) не плохо было бы привести примеры этих фаз. В противном случае – это голословное утверждение!

    http://framework.zend.com/manual/en/zend.cache.html
    http://framework.zend.com/manual/en/zend.cache.theory.html
    http://ru.wikipedia.org/wiki/%D0%9A%D0%B5%D1%88%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5#.D0.9A.D1.8D.D1.88.D0.B8.D1.80.D0.BE.D0.B2.D0.B0.D0.BD.D0.B8.D0.B5_.D0.B8.D0.BD.D1.82.D0.B5.D1.80.D0.BD.D0.B5.D1.82-.D1.81.D1.82.D1.80.D0.B0.D0.BD.D0.B8.D1.86

    Никаких двух фаз тут никто не описывает. Фаза одна – есть ли данная информация в кеше? Если есть – загрузить и отобразить. В чем состоит вторая фаза в общем случае – не понятно.

    Для WP я так понял из сорца они хранят полностью страницу с возможностью изменения ключевых записей (данные с записью, с комментариями – обновления в общем). Но это же не значит, что везде и все так делают.

    Опять же пугающая бессмысленность фразы “Обновления данных в кеше – это вопрос либо времени, либо программной реализации”. Что ты имел в виду под этой фразой остается для меня загадкой!

    Это не бессмысленность. Цитата из того же линка из википедии:

    “При модификации элементов данных в кэше выполняется их обновление в основной памяти. Задержка во времени между модификацией данных в кэше и обновлением основной памяти управляется так называемой политикой записи.

    В кэше с немедленной записью каждое изменение вызывает синхронное обновление данных в основной памяти.

    В кэше с отложенной записью (или обратной записью) обновление происходит в случае вытеснения элемента данных, периодически или по запросу клиента. Для отслеживания модифицированных элементов данных записи кэша хранят признак модификации (изменённый или «грязный»). Промах в кэше с отложенной записью может потребовать два обращения к основной памяти: первое для записи заменяемых данных из кэша, второе для чтения необходимого элемента данных.”

    1. Мы можем задавать время жизни кеша – после истечения этого времени – запись в кеше удаляется и делается новый запрос на получение обновленных данных – и они снова кладутся в кеш.

    2. Либо обновлять кеш после появления новых записей сразу, без задания времени жизни кеша. Таким образом он будет жить до тех пор, пока не появится новая запись.

    В заключение, Станислав, у тебя очень много фраз смысл которых теряется из-за твоего желания выразиться красиво. Например “общее понимаени теории кэширования у тебя неправильное” – это что за зверь такой “общая теория кэширования”? Надеюсь, ты понимаешь, что общий случай и общая теория – две разные вещи?

    Я не старался выразиться красиво – но старался выразиться понятно.

    Под общей теорией кеширования я понимаю то, что написано тут – http://ru.wikipedia.org/wiki/%D0%9A%D0%B5%D1%88%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5#.D0.9A.D1.8D.D1.88.D0.B8.D1.80.D0.BE.D0.B2.D0.B0.D0.BD.D0.B8.D0.B5_.D0.B8.D0.BD.D1.82.D0.B5.D1.80.D0.BD.D0.B5.D1.82-.D1.81.D1.82.D1.80.D0.B0.D0.BD.D0.B8.D1.86

    А ты что подразумеваешь под “общим случаем”? Если учесть, что ты предложил отвлечься от WP.

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

    У меня сложилось впечатление, что мы говорим о разных вещах – я про серверное кеширование, а ты про клиентское.

    Я и не думал обижаться, кроме того не знаю, как ты – но я себя в профессионалы никогда не записывал и не записываю. Если я в чем-то не прав – проясни, я же не утверждаю, что я на 100% прав, я выразил свое мнение по этому поводу и свое понимание данного вопроса.

  5. PS. Не приходят уведомления о новых ответах в почту.

  6. Я и не думал обижаться, кроме того не знаю, как ты – но я себя в профессионалы никогда не записывал и не записываю. Если я в чем-то не прав – проясни, я же не утверждаю, что я на 100% прав, я выразил свое мнение по этому поводу и свое понимание данного вопроса.

    Ок. Сейчас поясню в чем, на мой взгляд, ты неправ.

    Никаких двух фаз тут никто не описывает. Фаза одна – есть ли данная информация в кеше? Если есть – загрузить и отобразить. В чем состоит вторая фаза в общем случае – не понятно.

    Как же это не описывает то? А что по твоему Zend_Cache_Core::get() и Zend_Cache_Core::save()?
    1-ая фаза – получение данных из кэша. Прежде всего в эту фазу выполняется проверка условий на основании которых принимается решение об актуальности данных в кэше (Zend_Cache_Core::get()).

    2-ая фаза – сохранение данных. Здесь определяется данные для кэширования, срок их жизни, идентификатор и т.д. (Zend_Cache_Core::save()

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

    Это не бессмысленность. Цитата из того же линка из википедии:
    ….

    Вопрос времени, так же как и другие вопросы связанные с принятием решения об актуальности данных хранящихся в кэше – это вопросы программной реализации. Получается, что ты в одну строку ставишь “часть” с “целым”.

    1. Мы можем задавать время жизни кеша – после истечения этого времени – запись в кеше удаляется и делается новый запрос на получение обновленных данных – и они снова кладутся в кеш.

    2. Либо обновлять кеш после появления новых записей сразу, без задания времени жизни кеша. Таким образом он будет жить до тех пор, пока не появится новая запись.

    Приводишь два основания (условия) для обновления кэша. Если я правильно, понял, то второй ты считаешь – программной реализацией, а первый – вопросом времени? На мой взгляд они оба реализуются программно. Разве нет?

    А ты что подразумеваешь под “общим случаем”? Если учесть, что ты предложил отвлечься от WP.

    Если взять набор реализованных на практике алгоритмов кэширования, каждый из которых разбить на логические участки, и дать им имена. Затем полученные имена представить как множество. То общим случаем будет считаться – пересечение всех этих множеств.

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

    В своих рассуждениях я остановился на самом верхнем уровне абстракции, т.е. когда новое разбиение всех алгоритмов на части не дает нового общего случая.

    У меня сложилось впечатление, что мы говорим о разных вещах – я про серверное кеширование, а ты про клиентское.

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

    Как много действительно полезных для пользователя проектов, где можно применить кеширование страниц полностью? И что это за “в этом случае можно полноценно использовать механизмы заложенные в http протокол”. Что это за магические механизмы?

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

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

    Я согласен с тобой, что есть много факторов мешающих кэшированию страниц полностью(например, открытие сессии в PHP автоматически добавляет заголовок no-cache). Но это не означает, что во всем проекте нет ни одной страницы, которая не могла бы быть сохранена полностью. Всегда есть статичные, редкообновляемые ресурсы – внешне javascript-ы, css-файлы, картинки. Которые могут кэшируются просто на ура! Очень часто, бывает что объем этих файлов превышает объем html страницы. Я прирваниваю эти файлы к страницам, потому что у каждого из них есть свой урл. Но даже если не рассматривать эти ресурсы, а брать в расчет обычные html/php страницы, то все равно вопрос применимости полного кэширования, в части случаев в рамках одного и того же проекта, можно решить положительно.

    Поэтому, как мне кажется, в любом проекте нужно совмещать как кэширование на уровне страниц, так и кэширование на уровне объектов. В WP сделано именно так, о чем я писал в статье.

  7. Женя, про Зенд – ты правильно написал, только это же совсем не стадии.

    Как же это не описывает то? А что по твоему Zend_Cache_Core::get() и Zend_Cache_Core::save()?
    1-ая фаза – получение данных из кэша. Прежде всего в эту фазу выполняется проверка условий на основании которых принимается решение об актуальности данных в кэше (Zend_Cache_Core::get()).

    2-ая фаза – сохранение данных. Здесь определяется данные для кэширования, срок их жизни, идентификатор и т.д. (Zend_Cache_Core::save()

    Эти две фазы, как ты их определяешь – одновременно не работают. Если не выполнено 1-ое, тогда делается 2-ое, но никак по-другому.

    Самый простой пример, чтобы ты мог убедиться в этом тут – http://framework.zend.com/manual/en/zend.cache.frontends.html#zend.cache.frontends.core

    Если данные есть в кеше – то save вообще не вызывается и значит нет никакой второй фазы.

    На примере того же Зенда я так и не могу понять твоей фразы:

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

    Где там создание копии ? Где там расположении после задачи по получению и обработке данных, когда страница уже построена?

    Моя вся претензия к статье – привязана к этому предложению. И я до сих пор так и не понимаю, что за смысл ты во вторую “фазу” вкладываешь..

  8. Ну и не Zend_Cache_Core::get(), а Zend_Cache_Core::load(), но это не принципиально совсем.

  9. Станислав, вот теперь я понял суть твоей претензии. Действительно, в статье я не сказал, что это взаимоисключающие части алгоритма. Я даже не мог предположить, что кто-то решит иначе. Т.е. сначало идет создание кэша, потом его использование.

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

    Где там создание копии ? Где там расположении после задачи по получению и обработке данных, когда страница уже построена?

    Здесь под созданием копии данных имеется в виду создание кэша.

    В кэше наиболее удобно сохранять уже обработанные данные ( в случае если обработка не требуется, то конечно данные в кэш можно класть сразу после получения).

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

    Что касается zend cache, то это практически тоже самое, что WP Object Cache. При этом алгоритм не меняется, меняется только места его использования в основной программе.

  10. Станислав, те абзацы которые вызвали у тебя недопонимание я исправил. Надеюсь, теперь все встало на свои места?

  11. Да я в принципе применяю все, что объективно выгодно в данном проекте. Куски хтмл кода-то или же объекты в памяти – если это выгодно – я это применяю. :)

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

  12. Весьма познавательная перепсика. Мнения разные и очень понятно.

  13. так ведь начиная с версии 2.5 вордпресс больше не имеет дискового кеширования. обходными путями (подсунуть новой версии вордпресса cache.php от версии 2.3.3) можно заставить работать кеш, но боюсь это чревато чем-нибудь не слишком хорошим.

  14. Жень, спасибо! Санислав и остальные – и за комментарии тоже. Очень поучительная статья вышла. Как раз вот нужно с кешем разбираться в ВП, а тут вот)

  15. К сожалению не совсем понял статью.
    Я вообще в пшп не разбираюсь.
    Просто у меня проблема – я статью корректирую, корректирую, а она все по старому отображается.
    Я вот и подумал – может это кеширование виновато ?
    Прав я или нет ?

  16. Подскажите, пожалуйста!
    Создаю сайт на wp, для кеширования собираюсь использовать hyper cache или wp-cache. Как можно запретить кеширование участков кода (например: информеров и т.д.), при сохранении в кеше всего остального.
    Заранее спасибо!

  17. По факту почти все плагины одинаковые – но какому отдать предпочтение чтобы и работал сайт нормально и хостер не ругался…

Leave a Reply

« »