Memcached — ещё одна key:value система кеширования, аналогичная Redis.
Основное ограничение и отличие — memcached не хранит данные постоянно, т.е. при рестарте сервера данные из памяти будут утеряны.
Кратко её установка и примеры использования.
Содержание
Установка
pacman
На Arch Linux можно установить из репозитория с помощью pacman:
[simterm]
$ sudo pacman -S memcached
[/simterm]
Debian/Ubuntu — с помощью apt, заодно PHP и NGINX для примеров:
[simterm]
# apt install -y memcached php nginx mariadb-server php-mysql php-memcached
[/simterm]
Docker
Либо запустить из Docker образа:
[simterm]
$ docker run --name memcached -p 11211:12111 memcached
[/simterm]
Файл настроек — /etc/memcached.conf.
Подключение, команды
memcached сервер принимает подключения на порт 11211, и подключиться к нему можно даже просто telnet (или передавать команды через netcat — см. примеры ниже)
[simterm]
root@ip-172-31-12-178:~# telnet localhost 11211 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'.
[/simterm]
После чего можно добавлять/получать данные.
Аттрибуты
Основные аттрибуты, которые задаются данным в кеше:
| Аттрибут | Описание |
|---|---|
| key | имя ключа, максимальная длина 250 байт |
| flag | 32-х битная целочисленное, обычно можн оустановить в 0 |
| exptime | время жизни объекта в кеше в секундах — 0 хранить всегда= |
| bytes | кол-во байт, которые необходимо выделить для хранения значения |
| noreply | опциональный параметр, что бы сервер не оптравлял ответа после выполнения запроса |
| value | значение, которое необюходимо доабвить в кеш |
set
Добавить значение можно с помощью set.
Синтаксис:
[simterm]
set key flags exptime bytes [noreply] (ENTER)
value
[/simterm]
Добавляем ключ с имнем key_name, без флага, таймаут хранения 100 секунд, резервируем 5 байт:
[simterm]
set key_name 0 100 5 value STORED
[/simterm]
get
Получаем его с помощью get:
[simterm]
get key_name VALUE key_name 0 5 value END
[/simterm]
add
Добавит ключ:значение, только если для ключа ещё нет значения в кеше.
Добавляем ключ:
[simterm]
set key_name 0 1000 6 qwerty STORED
[/simterm]
Пробуем добавить значение:
[simterm]
add key_name 0 1000 6 ytrewq NOT_STORED
[/simterm]
И в новый ключ:
[simterm]
add key_name2 0 1000 6 ytrewq STORED
[/simterm]
delete
Что бы удалить ключ:значение — вызываем delete:
[simterm]
delete key_name2 DELETED
[/simterm]
Теперь get вернёт пустой объект:
[simterm]
get key_name2 END
[/simterm]
Больше примеров тут>>> и тут>>>.
Memcached и PHP
Настраиваем NGINX — редиректим запросы к PHP на PHP-FPM, в файле /etc/nginx/sites-enabled/default задаём:
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.php;
server_name _;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}
}
FPM уже принимает подключения через сокет:
[simterm]
root@ip-172-31-12-178:~# cat /etc/php/7.0/fpm/pool.d/www.conf | grep ^listen listen = /run/php/php7.0-fpm.sock
[/simterm]
Перезагружаем конфиги NGINX:
[simterm]
root@ip-172-31-12-178:~# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful root@ip-172-31-12-178:~# service nginx reload
[/simterm]
Создаём страницу с phpinfo():
[simterm]
root@ip-172-31-12-178:~# cat /var/www/html/index.php <?php phpinfo(); ?>
[/simterm]
Проверяем:
Создадим страницу, файл /var/www/html/cache_tests.php, с которой будем запрашивать и добавлять данные из кеша:
<?php
$mem = new Memcached();
$mem->addServer("127.0.0.1", 11211);
?>
Тут создаётся PHP Memcached объект, который сохраняется в переменной $mem, и подключается к локальному серверу на порт 11211.
Далее — пробуем получить ключ с именем key_name из кеша:
...
$result = $mem->get("key_name");
...
И добавляем проверку: если значение получено — то выводим его в браузер, если ключа в кеше нет — добавляем его туда:
<?php
$mem = new Memcached();
$mem->addServer("127.0.0.1", 11211);
$result = $mem->get("key_name");
if ($result) {
echo $result;
} else {
echo "No key found. Adding key to cache.";
$mem->set("key_name", "Key_name's value from memcached!") or die ("Couldn't save anything to memcached...");
}
?>
Проверяем:
[simterm]
root@ip-172-31-12-178:~# curl localhost/cache_tests.php No key found. Adding key to cache.
[/simterm]
Повторяем запрос:
[simterm]
root@ip-172-31-12-178:~# curl localhost/cache_tests.php Key_name's value from memcached!
[/simterm]
И напрямую из memcached:
[simterm]
root@ip-172-31-12-178:~# echo "get key_name" | nc localhost 11211 VALUE key_name 0 32 Key_name's value from memcached! END
[/simterm]
Кеширование запросов из MySQL
В следующем примере — сохраним в memcached результат запроса из MariaDB базы.
MySQL база
Подключаемся к серверу БД:
[simterm]
root@ip-172-31-12-178:~# mysql -u root -p Enter password: Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 50 ... MariaDB [(none)]>
[/simterm]
Создаём базу:
[simterm]
MariaDB [(none)]> CREATE DATABASE memcached_test;
[/simterm]
Переключаемся на неё:
[simterm]
MariaDB [(none)]> use memcached_test; Database changed
[/simterm]
Создаём пользователя с правами на эту базу:
[simterm]
MariaDB [memcached_test]> GRANT ALL ON memcached_test.* TO memcached_test@localhost IDENTIFIED BY 'password';
[/simterm]
Создаём таблицу:
[simterm]
MariaDB [memcached_test]> CREATE TABLE db_data (id int, name varchar(30));
[/simterm]
Добавляем в неё запись:
[simterm]
MariaDB [memcached_test]> INSERT INTO db_data VALUES (1, "some_data");
[/simterm]
Проверяем:
[simterm]
MariaDB [memcached_test]> select * from db_data; +------+-----------+ | id | name | +------+-----------+ | 1 | some_data | +------+-----------+
[/simterm]
PHP скрипт
Скрипт /var/www/html/db_test.php будет пробовать получить данные из memcahed, если их нет — то выполнит запрос напряую к БД, и добавит данные в memcached.
Обновляем /etc/php/7.0/fpm/php.ini, убираем комментарий ; перед php_mysqli.dll:
... extension=php_mysqli.dll ...
Добавляем подключение к memcached, аналогично первому примеру, и второе подключение — к MySQL:
<?php
$mem = new Memcached();
$mem->addServer("127.0.0.1", 11211);
$connection = mysqli_connect("localhost", "memcached_test", "password");
mysqli_select_db($connection, "memcached_test");
?>
Добавляем переменную $query, в которой будет сам запрос к БД, и переменную $querykey, в которой сгенерируем ключ, который будет использоваться в memchached для получения данных:
... $query = "SELECT ID FROM db_data WHERE name = 'some_data'" or die(mysqli_error($connection)); $querykey = "KEY" . md5($query) or die(mysqli_error($connection)); ...
Добавляем переменную $result, в которой будет результат, который мы получаем из memcached:
... $result = $mem->get($querykey); ...
Далее добавляем логику: если $result пустой — то обращаемся напрямую к MySQL, получаем данные, и записываем их в memchaced с помощью set($querykey, $result, 10), если данные найдены — то выводим их в браузер:
<?php
$mem = new Memcached();
$mem->addServer("127.0.0.1", 11211);
$connection = mysqli_connect("localhost", "memcached_test", "password");
mysqli_select_db($connection, "memcached_test");
$query = "SELECT ID FROM db_data WHERE name = 'some_data'" or die(mysqli_error($connection));
$querykey = "KEY" . md5($query) or die(mysqli_error($connection));
$result = $mem->get($querykey);
if ($result) {
print "<p>Data retrieved from memcached: " . $result[0] . "</p>";
} else {
$result = mysqli_fetch_array(mysqli_query($connection, $query)) or die(mysqli_error($connection));
$mem->set($querykey, $result, 10);
print "<p>Data retrieved from MySQL: " . $result[0] . "</p>";
print "<p>Data not found in memcached.</p><p>Stored in memcached for next time.</p>";
}
?>
Проверяем:
Обновляем страницу:
Теперь данные в memcached.
Проверяем напрямую из него — добавим вывод ключа:
...
} else {
$result = mysqli_fetch_array(mysqli_query($connection, $query)) or die(mysqli_error($connection));
$mem->set($querykey, $result, 10);
print "<p>Data retrieved from MySQL: " . $result[0] . "</p>";
print "<p>Data not found in memcached.</p><p>Stored in memcached for next time.</p>";
print "<p>Memcached key: $querykey.</p>";
}
...
Обновляем страницу, копируем ключ:
Запрашиваем его из memcached (помним, что данные хранятся только 10 секунд):
[simterm]
root@ip-172-31-12-178:~# echo "get KEY18c26b3d9c726e12f7257b600ec91b20" | nc localhost 11211
VALUE KEY18c26b3d9c726e12f7257b600ec91b20 4 53
a:2:{i:0;s:9:"some_data";s:4:"name";s:9:"some_data";}
END
[/simterm]
Готово.



