Объектный кэш в WordPress

Click here to view original web page at wp-kama.ru

Object cache или Кэш объектов в WordPress — это механизм ядра, который позволяет сохранять любые данные в кэш. Такой кэш используется для сохранения данных, которые получаются много раз в процессе кода или для сохранения данных полученных после сложных операций.

Рассмотрим пример кэширования SQL запроса.

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

function myfunc() {
	return $wpdb->get_results( "SELECT ..." );
}

myfunc(); // SQL запрос
myfunc(); // SQL запрос
myfunc(); // SQL запрос

Сделаем, чтобы функция работала с объектным кэшем. И теперь только первый вызов функции выполнит SQL запрос, а остальные будут брать данные из кэша.

function myfunc() {
	// пробуем получить кэш и вернем его если он есть
	$cache_key = 'my_cache_key';
	if( $cache = wp_cache_get( $cache_key ) )
		return $cache;

	$value = $wpdb->get_results( "SELECT ..." );

	wp_cache_set( $cache_key, $value ); // добавим данные в кэш

	return $value;
}

myfunc(); // SQL запрос
myfunc(); // Кэш
myfunc(); // Кэш

меню меню

В WP такое кэширование используется практически везде: в опциях, записях, терминах, у пользователей, метаданных и т.д.

Кэширование объектов в опциях WordPress

Для примера, рассмотрим как работает кэширование объектов в опциях WordPress. Функция get_option() не создает дополнительных запросов в базу данных при множественном вызове, как раз благодаря такому кэшу.

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

Так например, этот код вызванный в файле темы не сделает ни одно запроса к БД:

if( ! get_option( 'comments_open' ) ){
	echo '<p>Комментирование на сайте '. get_option('blogname') .' закрыто.</p>';
	echo '<p>Свяжитесь с администрацией: '. get_option('admin_email') .'</p>';
}
Кэширование метаданных

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

// допустим в этом запросе были получены посты: 1 2 3 4 5
$posts = get_posts();
foreach( $posts as $post ){
	echo $post->post_title . '<br>';
}

// дальше в коде нам нужны метаданные поста 3

echo get_post_meta( 3, 'my_meta', 1 ); // эти данные будут взяты из кэша...

меню

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

В WordPress есть возможность включить внешнее хранилище для кэша объектов и сделать кэширование постоянным. Так данные из кэша будут доступны между запросами.

Для включения постоянного объектного кэша (persistent object cache) нужно установить плагин. Таких плагинов много, потому что вариантов где и как хранить такой кэш также много, вот некоторые из них:

Данные плагины позволяют использовать серверы Redis, Memcached, APC соответственно.

Для того, чтобы определить используется ли внешний плагин объектного кэширования, в WordPress есть специальная функция wp_using_ext_object_cache().

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

Например, сохраним значение в кэш объектов, только если кэш является постоянным, в противном случае сохраним значение в опцию:

if( wp_using_ext_object_cache() ) 
	wp_cache_set( 'key', 'value' );
else 
	update_option( 'key', 'value' );

меню

Параметр $group у функций кэширования позволяет использовать одинаковые ключи кэша.

Группа — это префикс к ключу. Такой префикс используется:

  • при работе с WordPress мультисайт («глобальные» и «не глобальные» группы).
  • при использовании плагинов объектного кэширования («постоянные» и «непостоянные» группы).

В ядре WordPress существуют следующие названия групп:

  • default — группа кэша по умолчанию.
  • posts — группа кэша для хранения записей (постов, страниц, произвольных типов).
  • options — группа кэша для хранения опций.
  • comment — группа кэша для комментариев.
  • themes — группы кэша для хранения тем.
  • plugins — группы кэша для хранения плагинов.
  • users — группа кэша для хранения информации о юзерах.

меню

Работают только когда WordPress установлен как сеть мультисайт.

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

Для каждого сайта сети к ключу кэша добавляется префикс сайта, чтобы отличать, например, кэш записи с ID 5 одного сайта от кэша записи с таким же ID 5 другого сайта. Но также в мультисайте есть объекты, которые работают для всей сети, например «Пользователи» — они и относятся к глобальным группам, к кэшам таких объектов никакой префикс не добавляется...

По умолчанию глобальными группами являются:

users
userlogins
usermeta
user_meta
useremail
userslugs
site-transient
site-options
blog-lookup
blog-details
site-details
rss
global-posts
blog-id-cache
networks
sites

В список глобальных групп можно добавить свою группу, см. функцию wp_cache_add_global_groups('my-global-group').

меню

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

Иногда надо, чтобы кэш не сохранялся на постоянной основе, а работал как и прежде (только во время генерации страницы). Чтобы добиться этого, можно указать группу для создаваемого кэша объектов и пометить эту группу как «Непостоянная». Делается это с помощью функции wp_cache_add_non_persistent_groups( 'my-group' ).

Так при сохранении кэша в группе «my-group», значение будет сохранено только в локальный кэш (в оперативную память) и не будет сохраняться в хранилище кэширующего плагина, например на сервер Memcached.

Обычно к непостоянным группам относятся группы: «themes», «plugins», «comment», «counts».

меню

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

С помощью функции wp_suspend_cache_addition() можно временно отключить работу объектного кэша.

wp_suspend_cache_addition( true ); // отключаем работу кэша объектов

// наш код...

wp_suspend_cache_addition( false ); // включаем обратно

меню

Чтобы посмотреть как используется кэш можно установить плагин «Debug Bar». В нём можно посмотреть статистику обращений в кэш объектов и потребляемую память (сколько весит элемент кэша).

Если установлен плагин кэширования объектов, Debug Bar покажет данные по внешнему серверу.

При написании использовал статью с сайта wpmag.ru.