Кэш объектов в WordPress: способы реализации на PHP

Раздел: Администрирование и оптимизация -> Оптимизация производительности

Объектное кэширование в WordPress: настройка и варианты

Объектный кэш (object cache) в WordPress хранит результаты часто выполняемых запросов к базе данных, чтобы снизить нагрузку на сервер и ускорить загрузку страниц. По умолчанию WordPress использует встроенный кэш в оперативной памяти PHP, который теряется после каждого запроса. Для постоянного кэширования требуется внешнее хранилище, такое как Redis, Memcached или APCu. В этой статье рассмотрено несколько подходов с подробными примерами кода.

Как организовать постоянный объектный кэш с помощью Redis?

Основное и наиболее производительное решение для большинства проектов – использование Redis через drop-in файл object-cache.php. Для этого потребуется сервер с установленным Redis и PHP-расширение PhpRedis (или Predis).

  1. Установка Redis на сервер (например, Ubuntu):
    sudo apt update && sudo apt install redis-server

    Cache php id (кэширование по id в php)

  2. Установка расширения PhpRedis:
    sudo apt install php-redis

    Php http cache (http-кэширование в php)

    После установки перезапустите веб-сервер.
  3. Скачайте файл object-cache.php из репозитория WP Redis (https://github.com/WordPress/wp-redis) или используйте плагин WP Redis. Поместите файл в wp-content/object-cache.php.
  4. Настройте подключение, добавив в wp-config.php:
    define('WP_REDIS_HOST', '127.0.0.1');
    define('WP_REDIS_PORT', 6379);
    define('WP_REDIS_DATABASE', 0);

    Cache index php (кэширование индекса в php)

  5. Проверьте работу:
    $value = wp_cache_get('key', 'group');
    if (false === $value) {
    $value = 'cached data';
    wp_cache_set('key', $value, 'group');
    }
    echo $value;

    Wp content object cache php (кэш объектов в wp-content (wordpress))

Типичные ошибки:

  • Файл object-cache.php не распознаётся из-за неправильных прав доступа (должен быть 644).
  • Redis не запущен – проверьте командой
    redis-cli ping

    Cache html php (кэширование html в php)

    .
  • Ошибка подключения из-за неверных параметров WP_REDIS_HOST или порта.
  • Конфликт с другими плагинами кэширования – отключайте их при использовании объектного кэша.

Как использовать Memcached для объектного кэша?

Memcached – альтернатива Redis. Требует установки расширения memcached в PHP и демона memcached. Drop-in файл object-cache.php для Memcached доступен в плагине Memcached Object Cache. Настройка похожа на Redis:

define('WP_CACHE_KEY_SALT', 'mysite_');
define('WP_MEMCACHED_SERVERS', array(
array('127.0.0.1', 11211)
));

Bitrix php cache (кэширование в bitrix (php))

Важно: Memcached не поддерживает персистентность данных (данные теряются при перезапуске), поэтому не подходит для длительного хранения. Частая проблема – неверное указание серверов в многосерверной конфигурации.

Когда достаточно APCu (оперативного кэша в памяти PHP)?

APCu подходит для односерверных сайтов с низкой нагрузкой. Кэш хранится в общей памяти PHP, но не распространяется между разными серверами. Для включения достаточно установить расширение APCu и активировать плагин APCu Object Cache или написать свой object-cache.php на основе apcu_store() и apcu_fetch().

function apcu_cache_store($key, $data, $group, $expire) {
return apcu_store($group . ':' . $key, $data, $expire);
}

APCu не синхронизируется между серверами, поэтому на балансировщиках нагрузки возникнет различие в данных. Также APCu имеет ограничение по размеру памяти (обычно 32–128 МБ).

Как организовать файловый кэш без внешних сервисов?

Файловый кэш сохраняет данные в файлы внутри wp-content/cache/. Он медленнее Redis, но не требует дополнительных служб. Можно использовать плагин File-Based Object Cache или написать собственный:

$file = WP_CONTENT_DIR . '/cache/obj_cache_' . md5($key . $group) . '.txt';
if (file_exists($file) && (time() - filemtime($file) < 3600)) {
return unserialize(file_get_contents($file));
} else {
$value = compute_data();
file_put_contents($file, serialize($value));
return $value;
}

Проблемы: рост числа файлов, медленная работа на больших объёмах, конфликты блокировок при одновременной записи. Не подходит для высоконагруженных проектов.

Зачем использовать транзиенты (transients) для временного кэширования?

Транзиенты – встроенный механизм WordPress для хранения данных с TTL. Они реализованы через опции, но объектный кэш может ускорить их получение. Пример:

$data = get_transient('my_featured_posts');
if (false === $data) {
$data = new WP_Query(array('posts_per_page' => 5));
set_transient('my_featured_posts', $data, 12 * HOUR_IN_SECONDS);
}
// $data содержит объект WP_Query

Транзиенты не используют собственный TTL при использовании внешнего объектного кэша – срок действия управляется через ключ. Ошибка: путаница между set_transient и set_site_transient для мультисайтов.

Как создать собственный object-cache.php с гибкой инвалидацией?

Можно написать свой drop-in файл, который, например, группирует данные и сбрасывает всю группу по команде. Пример использования wp_cache_* функций с групповой поддержкой:

// object-cache.php (фрагмент)
function wp_cache_add($key, $data, $group = '', $expire = 0) {
global $custom_cache;
if (isset($custom_cache[$group][$key])) return false;
$custom_cache[$group][$key] = $data;
// дополнительно сохраняем в Redis
return true;
}

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

Расширенные примеры кода для объектного кэша WordPress

Пример 1: Пакетное чтение и запись с wp_cache_get_multiple и wp_cache_set_multiple

Начиная с WordPress 6.0 доступны функции для работы с несколькими ключами. Пример:

Пример
$keys = array('post_1', 'post_2', 'post_3');
$group = 'posts';
$cached = wp_cache_get_multiple($keys, $group);
// $cached = array('post_1' => false, 'post_2' => 'data2', 'post_3' => false);
foreach ($cached as $key => $value) {
if ($value === false) {
$value = get_post($key);
wp_cache_set($key, $value, $group);
}
}
Если Redis не поддерживает пакетные операции, функция decomposes в цикл – это медленнее.

Пример 2: Использование wp_cache_flush_group для сброса одной группы (только Redis)

Redis позволяет сбрасывать ключи по шаблону. Пример с group flushing:

Пример
// При сохранении поста сбрасываем кэш группы 'post_meta' для этого поста
add_action('updated_post_meta', function($meta_id, $post_id) {
wp_cache_delete($post_id, 'post_meta');
// или если нужен сброс всей группы
wp_cache_flush_group('post_meta'); // только если объектный кэш поддерживает
}, 10, 2);
Не все реализации поддерживают wp_cache_flush_group – проверяйте документацию вашего object-cache.php.

Пример 3: Мониторинг кэша через Redis CLI

Подключитесь к Redis и выполните:

Пример
redis-cli
KEYS *wordpress* # список всех ключей, содержащих 'wordpress'
MEMORY USAGE wp:options:alloptions # размер конкретного ключа
INFO keyspace # статистика по базам
Вывод: множество ключей, например: "wp:posts:1", "wp:options:alloptions", размер в байтах.

Пример 4: Настройка кластера Redis для WordPress Multisite

Для мультисайтовой сети нужно указывать префикс для каждого сайта. В wp-config.php:

Пример
define('WP_REDIS_CLIENT', 'phpredis');
define('WP_REDIS_SERVERS', serialize(array('
'tcp://192.168.1.1:6379',
'tcp://192.168.1.2:6379'
)));
define('WP_CACHE_KEY_SALT', 'network_'); // префикс для всей сети
// Для индивидуальных префиксов используйте фильтр 'wp_cache_key_prefix'
Важно: кластер Redis не поддерживает транзакции и сброс всех ключей через FLUSHDB – используйте ключи с шаблонами.

Пример 5: Собственный object-cache.php с поддержкой истечения по группам

Код:

Пример
function wp_cache_set($key, $data, $group = '', $expire = 0) {
$redis = get_redis_connection();
$redis_key = $group . ':' . $key;
$result = $redis->set($redis_key, serialize($data));
if ($expire > 0) {
$redis->expire($redis_key, $expire);
}
// храним список ключей группы для быстрой очистки
$redis->sAdd('group:' . $group, $redis_key);
return $result;
}
function wp_cache_flush_group($group) {
$redis = get_redis_connection();
$keys = $redis->sMembers('group:' . $group);
foreach ($keys as $key) {
$redis->del($key);
}
$redis->del('group:' . $group);
}
При сбросе группы все ключи этой группы будут удалены, но если в процессе создаются новые – может потребоваться блокировка.

Пример 6: Использование транзиентов с объектным кэшем для сложных запросов

Пример
$transient_key = 'category_posts_' . $cat_id;
$cached = get_transient($transient_key);
if (false === $cached) {
$query = new WP_Query(array('cat' => $cat_id, 'posts_per_page' => 10));
$cached = array('posts' => $query->posts, 'total' => $query->found_posts);
set_transient($transient_key, $cached, HOUR_IN_SECONDS);
}
foreach ($cached['posts'] as $post) {
setup_postdata($post);
// вывод поста
}
wp_reset_postdata();
Транзиенты автоматически синхронизируются с объектным кэшем, если включён drop-in, иначе сохраняются в таблице wp_options.

Пример 7: Настройка времени жизни разных групп кэша

В object-cache.php можно задавать разное TTL для разных групп:

Пример
$ttl_config = array(
'posts' => 3600, // 1 час
'comments' => 600, // 10 минут
'options' => 86400, // сутки
);
function get_group_ttl($group) {
global $ttl_config;
return isset($ttl_config[$group]) ? $ttl_config[$group] : 0;
}
После добавления проверьте, что значения TTL корректно передаются в Redis (через EXPIRE).

Кэш объектов в wp-content (WordPress) - comments

En
Wp content object cache php (php)