Memcached  — это служба (демон), предназначенная для кэширования различных объектов и структур в оперативной памяти. Хранение части информации в таком кеше позволяет значительно сократить нагрузку на базу данных и ускорить работу сайта. Лучше всего  memcached запускать на отдельном сервере.

Для установки этого демона и обеспечения обращения к его функциям из php вам необходимо установить следующие пакеты из репозиториев:
memcached - служба (демон)
php5-pecl-memcache - расширение для php

API memcached невелик: соединение (так же отключение) с сервером, добавление, удаление, обновление и получение объекта, инкримент и дикримент.

Для каждого объекта, который мы хотим кешировать устанвливается время жизни, от 1 секунды до бесконечности. При нехватке памяти наиболее старые записи удаляются. Но для PHP есть и библиотеки для работы с memcached которые добавляют возможностей. Например библиотека Dklab_Cache позволяет использовать тегирование для кешируемых объектов.

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

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

А если, например, в проекте время от времени запускается некторый SQL-запрос, который производит удаление выполненных заданий, если он завершены более месяца назад? Так как логика удаления находится внутри запроса, то мы не можем сбросить кеш для все пользователей которых коснулись изменения, сделанные запросом. В таком случае можно удалить все кешированнные данные, которые имеют определенный тег. Можно прикреплять каждому кешу для панели заданий тег tasks кроме ключа task_list_%id%. Тогда после выполнения SQL-запроса нужно сбросить все данные в кеше, которые имеют тег tasks . Тот же самый подход пригодится, если панель с заданиями, это  не единсвенная вещь связханная с таблицей заданий в БД, которую вы кешируете.

Если у вас есть разные панели на странице, которые строятся по одной таблице БД, но по разным запросам, то здесь и пригодится тегирование. Изменилась таблица - сбрасываем все кешированные данные, которые связаны с этой таблицей. Здесь уже возможно будут актуальны теги вида tasks_%id%.

Для последнего случая я и приведу пример работы с кешам при использовании Dklab_Cache - библиотеки.
Будет два файла. Один - отображает панели из кеша, второй - сбрасывает кеш. Скачать библиотеку можно здесь. После распаковки в корневую директорию сайта в подпапке t/Dklab_Cache/TagEmuWrapper создайте файл show_panels.php примерно такого содержания:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
require dirname(__FILE__) . '/init.php';
 
$id = 'HG768YY9892GH';
 
//Читаем из кеша данные для панелей
$panel1 = $backend->load('panel1_'.$id);
$panel2 = $backend->load('panel2_'.$id);
 
 
if($panel1===false) {
	// Если данных нет, то получаем их из БД и пишем в кеш
	$panel1 = $taskModel->getTasks(); 
	// panel1 содержит строку '<ul><li>Task 1</li><li>Task 2</li></ul>';
	$backend->save($panel1, 'panel1_'.$id, array('tasks_'.$id));
}
if($panel1===false) {
	// Если данных нет, то получаем их из БД и пишем в кеш
	$panel2 = $taskModel->getCompletedTasks();
	// panel2 содержит строку 'Completed tasks: Task2';
	$backend->save($panel2, 'panel2_'.$id, array('tasks_'.$id));
}
// Выводим панели
echo $panel1;
echo $panel2;

В этой же подпапке создайте файл update_tasks.php со следующими строками:

1
2
3
4
5
6
7
8
require dirname(__FILE__) . '/init.php';
 
$id = 'HG768YY9892GH';
//Меняем данные.
$taskModel->updateTasks();
//Когда данные изменились сбрасываем кеш по тегу
$backend->clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG,  
	array('tasks_'.$id));

Второй файл иллюстрирует код, который должен располагаться в месте, которое меняет таблицу заданий. Например, в обработчике формы редактирования статуса задания.
Объект $taskModel и его методы getTasks(), getCompletedTasks() и updateTasks() конечно же не существуют. Их создайте самостоятельно или замените запросы к БД простым html-кодом, как в комментариях.

Вот вкратце об использовании memcached. Успехов вам в оптимизации высоконагруженных проектов!

Tags:

Comments are closed.