В интернете достаточно много информации на данную тему, но, несмотря на это, многие обходят её стороной. Цель данного поста, разъяснить на пальцах основы взаимодействия с Memcached.
Memcache разработан для кэширования данных, генерация которых требует большого количества ресурсов. Такого рода данные могут содержать что угодно, начиная с результатов запроса к базе данных и заканчивая тяжеловесным куском шаблона. Memcached не входит в базовый набор модулей, поставляемых с PHP, однако он доступен в репозитории pecl.
В качестве рассматриваемого дистрибутива я решил использовать Debian, потому как он наиболее часто используется при создании web-серверов. Модуль Memcached для PHP доступен в репозитории уже скомпилированным (php5-memcached), но я опишу процесс установки из исходного кода, так как не все репозитории настолько богаты, как дебиановский.
#apt-get install memcached
Для начала, Вам хватит следующего конфига:
#/etc/init.d/memcached restart
Вот и всё! Совсем не сложно.
В результате выполнения этого кода каждый раз будет выводиться время с точностью до секунд. Однако обновляться оно будет раз в 5 секунд, пока не очистится кэш. В данном примере проиллюстрированы самые простые операции, но в производительности мы скорее потеряем, чем выиграем. Ведь нам каждый раз придётся подключаться к серверу…
В данном примере приведена функция, которая создаёт изображение размером 800x600 и расставляет на нём 10 000 точек. Один раз, сгенерировав такое изображение, в дальнейшем мы лишь выводим его на экран, не генерируя заново.
Тут всё гораздо проще и привычней: генерируем изображение каждый раз заново.
Я протестировал оба скрипта на производительность. Одна и та же машина в первом случае выдала 460 ответов в секунду, а во втором лишь 10. Чего и следовало ожидать.
addServer — в случае, если у вас в распоряжении несколько кэширующих серверов, вы можете создать некий кластер, добавляя сервера в пул. Следует обратить внимание на параметр weight. Он указывает на то, сколько памяти вам будет доступно на конкретном сервере.
delete — из названия понятно, что данный метод удаляет из кэша объект с заданным ключом.
replace — заменяет значение объекта с заданным ключом. Используйте в случае, если Вам понадобится изменить содержимое объекта, раньше чем истечёт время его жизни.
С моей точки зрения, применять кэширование стоит только на высоконагруженных ресурсах. Ведь каждый раз, подключаясь к серверу Memcached, вы тратите драгоценное время, что скорее всего не будет оправданным. Что касается больших проектов, лучше сразу написать больше строк кода, чем потом делать это в попыхах, с мыслью о том, что ваш сервис лежит. Также не стоит забывать о расходовании памяти! Учтите, что положив 300 мегабайт в кэш, вы отняли у себя 300 мегабайт ОЗУ...
В завершение хочу сказать, что данная статья не раскрывает все прелести технологии, однако я надеюсь, что она стимулирует Вас к самосовершенствованию. Спасибо за прочтение, многоуважаемый %username%!
UPD: Ещё один интересный момент. Memcached, есть PHP API к libmemcached. А Memcache, библиотека для php, не использующая libmemcached.
Что такое Memcache и какое отношение он имеет к PHP?
Memcache разработан для кэширования данных, генерация которых требует большого количества ресурсов. Такого рода данные могут содержать что угодно, начиная с результатов запроса к базе данных и заканчивая тяжеловесным куском шаблона. Memcached не входит в базовый набор модулей, поставляемых с PHP, однако он доступен в репозитории pecl.
Установка и настройка
В качестве рассматриваемого дистрибутива я решил использовать Debian, потому как он наиболее часто используется при создании web-серверов. Модуль Memcached для PHP доступен в репозитории уже скомпилированным (php5-memcached), но я опишу процесс установки из исходного кода, так как не все репозитории настолько богаты, как дебиановский.
Устанавливаем сервер Memcached
#apt-get install memcached
Для начала, Вам хватит следующего конфига:
#/etc/memcached.conf
#Memcached будет работать, как демон
-d
#Лог будет складывать туда
logfile /var/log/memcached.log
#Отведём 256 мегабайт ОЗУ под хранилище
-m 256
#Слушать будет этот порт
-p 11211
#В последствии желательно поменять
-u nobody
#Слушаем localhost
-l 127.0.0.1
#/etc/init.d/memcached restart
Проверяем
# netstat -tap | grep memcached
tcp 0 0 localhost:11211 *:* LISTEN 13036/memcached
Компилируем и устанавливаем модуль для PHP
apt-get install php5-dev libmemcache-dev
pecl download memcache
tar xzvf memcache-2.2.6.tgz
cd memcache-2.2.6/
phpize && ./configure --enable-memcache && make
cp modules/memcache.so /usr/lib/php5/20060613/
echo 'extension=memcache.so' >> /etc/php5/apache2/php.ini
/etc/init.d/apache2 restart
Вот и всё! Совсем не сложно.
Примеры использования
1. Базовые операции
- <?php
- //Создаём новый объект. Также можно писать и в процедурном стиле
- $memcache_obj = new Memcache;
- //Соединяемся с нашим сервером
- $memcache_obj->connect('127.0.0.1', 11211) or die(«Could not connect»);
- //Попытаемся получить объект с ключом our_var
- $var_key = @$memcache_obj->get('our_var');
- if(!empty($var_key))
- {
- //Если объект закэширован, выводим его значение
- echo $var_key;
- }
- else
- {
- //Если в кэше нет объекта с ключом our_var, создадим его
- //Объект our_var будет храниться 5 секунд и не будет сжат
- $memcache_obj->set('our_var', date('G:i:s'), false, 5);
- //Выведем закэшированные данные
- echo $memcache_obj->get('our_var');
- }
- //Закрываем соединение с сервером Memcached
- $memcache_obj->close();
- ?>
В результате выполнения этого кода каждый раз будет выводиться время с точностью до секунд. Однако обновляться оно будет раз в 5 секунд, пока не очистится кэш. В данном примере проиллюстрированы самые простые операции, но в производительности мы скорее потеряем, чем выиграем. Ведь нам каждый раз придётся подключаться к серверу…
2. Повышаем производительность
2.1 С кэшированием
- <?php
- function LoadCPU()
- {
- //Функция, которая должна зугрузить процессор
- //Создадим изображение 800x600
- $image = imagecreate(800, 600);
- //Белый фоновый цвет
- $color = imagecolorallocate($image, 255, 255, 255);
- //Чёрный
- $color2 = imagecolorallocate($image, 0, 0, 0);
- for ($i = 0; $i < 10000; $i++) {
- //Расставим 10 000 точек в случайном порядке
- imagesetpixel($image, rand(0, 800), rand(0,600), $color2);
- }
- //Выбрасываем указатель
- return $image;
- }
- //Создаём новый объект Memcache
- $memcache_obj = new Memcache;
- //Соединяемся с нашим сервером
- $memcache_obj->connect('127.0.0.1', 11211) or die("Could not connect");
- //Попытаемся получить объект с ключом image
- $image_bin = @$memcache_obj->get('image');
- if(empty($image_bin)) {
- //Если в кэше нет картинки, сгенерируем её и закэшируем
- imagepng(LoadCPU(),getcwd().'/tmp.png',9);
- $image_bin = file_get_contents(getcwd().'/tmp.png');
- unlink(getcwd().'/tmp.png');
- $memcache_obj->set('image', $image_bin, false, 30);
- }
- //Выведем картинку из кэша
- header('Content-type: image/png');
- echo $image_bin;
- //Закрываем соединение с сервером Memcached
- $memcache_obj->close();
- ?>
В данном примере приведена функция, которая создаёт изображение размером 800x600 и расставляет на нём 10 000 точек. Один раз, сгенерировав такое изображение, в дальнейшем мы лишь выводим его на экран, не генерируя заново.
2.2 Без кэширования
- <?php
- function LoadCPU()
- {
- //Функция, которая должна загрузить процессор
- //Создадим изображение 800x600
- $image = imagecreate(800, 600);
- //Белый фоновый цвет
- $color = imagecolorallocate($image, 255, 255, 255);
- //Чёрный
- $color2 = imagecolorallocate($image, 0, 0, 0);
- for ($i = 0; $i < 10000; $i++) {
- //Расставим 10 000 точек в случайном порядке
- imagesetpixel($image, rand(0, 800), rand(0,600), $color2);
- }
- //Выбрасываем указатель
- return $image;
- }
- //Выводим изображение, не кэшируя
- header('Content-type: image/png');
- imagepng(LoadCPU(),'',9);
- ?>
Тут всё гораздо проще и привычней: генерируем изображение каждый раз заново.
Результаты
Я протестировал оба скрипта на производительность. Одна и та же машина в первом случае выдала 460 ответов в секунду, а во втором лишь 10. Чего и следовало ожидать.
Ещё несколько полезных функций
addServer — в случае, если у вас в распоряжении несколько кэширующих серверов, вы можете создать некий кластер, добавляя сервера в пул. Следует обратить внимание на параметр weight. Он указывает на то, сколько памяти вам будет доступно на конкретном сервере.
delete — из названия понятно, что данный метод удаляет из кэша объект с заданным ключом.
replace — заменяет значение объекта с заданным ключом. Используйте в случае, если Вам понадобится изменить содержимое объекта, раньше чем истечёт время его жизни.
Итог
С моей точки зрения, применять кэширование стоит только на высоконагруженных ресурсах. Ведь каждый раз, подключаясь к серверу Memcached, вы тратите драгоценное время, что скорее всего не будет оправданным. Что касается больших проектов, лучше сразу написать больше строк кода, чем потом делать это в попыхах, с мыслью о том, что ваш сервис лежит. Также не стоит забывать о расходовании памяти! Учтите, что положив 300 мегабайт в кэш, вы отняли у себя 300 мегабайт ОЗУ...
В завершение хочу сказать, что данная статья не раскрывает все прелести технологии, однако я надеюсь, что она стимулирует Вас к самосовершенствованию. Спасибо за прочтение, многоуважаемый %username%!
UPD: Ещё один интересный момент. Memcached, есть PHP API к libmemcached. А Memcache, библиотека для php, не использующая libmemcached.