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]
Готово.