Квест → Как хакнуть форму
Прошли: 77
В предыдущих статьях серии:
В MySQL 5.6 появилось memcache-совместимое хранилище ключ-значение на базе движка Innodb.
InnoDB Memcache Daemon предоставляет вам стабильность innodb для данных вида ключ-значение, доступ к которым может быть организован через более быстрый и оптимизированный протокол memcached. При использовании данного протокола будут пропущены: парсинг запроса, его оптимизация и остальные части обработки, которые не требуются.
С помощью mysqlnd_memcache, вы можете прозрачно направлять ваши запросы к такому memcache-совместимому интерфейсу.
Стандартные пакеты MySQL 5.6, которые поставляются Ubuntu (Trusty), не включают в себя плагин memcache. Для использования этого плагина вам потребуется установить его из официальных apt-репозиториев MySQL-я (для Debian 7.x Wheezy, Ubuntu 12.04 Precise и Ubuntu 14.04 Trusty).
После того как вы установили MySQL 5.6 (или выше), необходимо войти в MySQL под суперпользователем и выполнить следующее:
SOURCE /usr/share/mysql/innodb_memcached_config.sql; INSTALL PLUGIN daemon_memcached SONAME "libmemcached.so";
Скрипт innodb_memcached_config.sql
делает несколько вещей, и первое, что он делает - это создаёт базу данных innodb_memcache
, которая содержит три таблицы:
cache_policies
: в этой таблице хранятся правила, как выполняются команды GET
, SET
, DELETE
и FLUSH
.containers
: эта таблица содержит список ваших таблиц, к которым возможен доступ с помощью memcacheconfig_options
— в этой таблице хранятся настройки memcache, а именно — разделитель многоколоночных значений - separator
(по умолчанию вертикальная черта “|
”) и разделитель обращения к таблицам table_map_delimiter
(по умолчанию точка “.
”)Второе, что выполняет скрипт - загружает сам плагин и запускает memcache демона внутри MySQL.
Теперь всё готово, чтобы использовать этот плагин.
Так как движок memcache устанавливает некоторые требования к таблицам, то не каждая innodb таблица может быть автоматически использована в качестве такого хранилища. Для использования вы должны настроить так называемую коллекцию.
Каждая коллекция имеет название, которое используется для обращения к ней через memcache, а также содержит ряд столбцов:
name
: название для обращения к коллекции через memcachedb_schema
: название базы данныхdb_table
: название таблицыkey_columns
: название столбца, содержащего ключ (пусть вас не смущает множественное число, это один столбец)value_columns
: названия столбцов, указанные через запятую, которые содержат значение. В memcache-значении все значения этих столбцов будут разделены вертикальной чертой (как указано в таблице config_options
)flags
: какие флаги memcache установитьcas_column
: название столбца для CAS-значения, устанавливаемого memcache-емexpire_time_column
: название столбца, в котором хранится время "протухания" (в секундах) или 0 если не "протухает" никогдаunique_idx_name_on_key
: название индекса, который накладывает ограничение UNIQUE
на столбец ключа. Если столбец ключа является первичным ключом, укажите PRIMARY
Для того чтобы организовать наше хранилище, мы создадим новую базу данных kv_data
и таблицу kv_store
в ней:
CREATE DATABASE kv_data; USE kv_data; CREATE TABLE kv_store ( `key` VARCHAR(255), `value` VARCHAR(1024), `flags` INT, `cas` BIGINT UNSIGNED, `exp` INT, primary key(`key`) ) ENGINE = INNODB;
Далее, мы сообщим плагину о нашем хранилище, создав контейнер:
INSERT INTO innodb_memcache.containers( name, db_schema, db_table, key_columns, value_columns, flags, cas_column, expire_time_column, unique_idx_name_on_key ) VALUES ( 'kv_data', 'kv_data', 'kv_store', 'key', 'value', 'flags', 'cas', 'exp', 'PRIMARY' );
После того как вы это сделали, вам нужно немного подождать, чтобы это вступило в силу или перезапустить MySQL.
Теперь, когда у вас запущен и работает memcache интерфейс innodb, вы можете вставлять (insert) данные также как в обычную таблицу БД или, конечно же, посредством протокола memcache, — что можно осуществить с помощью telnet-а.
При использовании протокола memcache — по умолчанию и минимальное — количество операций перед тем, как данные будут сброшены в innodb, является 32, как указано в настройке daemon_memcached_w_batch_size
. Это означает, что данные становятся видны в MySQL каждые 32 операции. Такова плата за производительность. Исключением из правил является использование binlog-репликации, в том случае, если она постоянно установлена в 1.
Для того чтобы MySQL изменения были сразу доступны через memcache, вы должны выполнить:
SET TRANSACTION ISOLATION TO READ-UNCOMMITTED;
Для использования memcache интерфейса с помощью telnet, используйте его следующим образом:
$ telnet localhost 11211 telnet> set test.key 0 0 11 Hello World STORED telnet> get test.key VALUE test.key 0 11 Hello World END
По умолчанию данные сохраняются либо в коллекции под названием default
или, если она не существует, в первую коллекцию в таблице коллекций.
Для доступа к данным другой коллекции у вас есть два варианта:
Первый наиболее близок к MySQL-евскому оператору USE
. Вы просто обращаетесь к самой коллекции и далее любые запросы оперируют с этой коллекцией, пока она не будет изменена на другую.
Перед именем коллекции, для отличия от ключей, ставится префикс — два знака @:
telnet> get @@kv_data VALUE @@kv_data 0 16 kv_data/kv_store END
Второй — это использовать полное имя. В этом случае как раз вступает в игру table_map_delimeter
, посредством чего мы просто ставим перед коллекцией префикс @@collection
и после table_map_delimeter
. Таким образом, обращение к test.key
становится @@kv_data.test.key
telnet> get @@kv_data.test.key VALUE @@kv_data.test.key 0 11 Hello World END
Я рекомендую всегда использовать такой синтаксис, т. к. вы можете случайно сменить коллекцию в каком-нибудь вызванном участке кода без возврата к предыдущей коллекции.
Теперь вы можете просто обращаться к вашим данным через интерфейс memcache, используя PHP расширение memcached или memcache (memcached extension, memcache extension). В том числе, вы можете настроить ваш обработчик сессий использовать этот подход. А также вы можете использовать обычные SQL запросы. Однако, с плагином mysqlnd_memcache вы можете прозрачно перенаправлять SQL запросы на memcache интерфейс, когда это необходимо.
По умолчанию запросы сопоставляются с регулярным выражением, указанном в константе MYSQLND_MEMCACHE_DEFAULT_REGEXP
:
/^\s*SELECT\s*(.+?)\s*FROM\s*`?([a-z0-9_]+)`?\s*WHERE\s*`?([a-z0-9_]+)`?\s*=\s*(?(?=["'])["']([^"']*)["']|([0-9e\.]*))\s*$/is
Если запрос соответствует, далее плагин проверяет, что в настройках коллекции перечисленны только поля из таблицы и что в секции WHERE только одно условие с простым сравнением по ключу.
Для нашего примера этому условию будет соответствовать вот такой запрос:
SELECT `value` FROM kv_store WHERE `key` = 'test.key';
Однако ни один из таких не будет:
SELECT * FROM kv_store WHERE `key` = 'test.key'; SELECT `value` FROM kv_store WHERE `key` = `test.key` AND value LIKE '%foo%'; SELECT `key` FROM kv_store WHERE value LIKE '%foo%';
Такие запросы могут быть выполнены с помощью механизмов одного из расширений: mysql, mysqli или pdo, и будут перехвачены незаметно для вас.
Плагин mysqlnd_memcache не обрабатывает запросы на запись.
Несмотря на это ограничение, его использование может определённо улучшить ваш код (тем, что вам не требуется реализовывать обращение к memcache/memcached API) и получить большой выигрыш в производительности при незначительных изменениях.
Memcached известен своей простой настройкой пула memcached-ов для балансировки нагрузки и отказоустойчивости, но как обстоят дела с memcache-интерфейсом для InnoDB? В некотором роде похожий обработчик присутствует в MySQL репликации, тем, что каждый слейв может быть использован как сервер Memcache-а в режиме только-для-чтения, впрочем, те же правила для разделения чтения и записи применимы и при работе с Memcache-ем.
Вы должны убедиться, что вы используете только плагин mysqlnd_memcache для доступа к вашему пулу и связать его с плагином mysqlnd_ms для организации разделения чтения и записи. Однако это означает, что вы упустите возможность воспользоваться высоко производительным иинтерфейсом Memcache-а на запись.
Так как нет способа указать memcache(d) расширению, что сервера используются в режиме только-на-чтение, то невозможно использовать стандартную топологию репликации master+slaves в качестве пула memcached-ов.
Memcached интерфейс для InnoDB — это намного более быстрый способ использования MySQL для простых хранилищ ключ-значение, но при этом имеет все преимущества великолепного движка InnoDB.
Хотя он и не является настолько быстрым, как сам memcached, он позволяет вам устранить “ещё один шарнир” в вашей инфраструктуре, при этом являясь простой заменой для memcached.
Кроме того, были некоторые радикальные улучшения производительности memcached движка для innodb в предстоящем релизе MySQL 5.7 в особенности для больших мультиядерных систем.
В следующей статье этой серии мы рассмотрим кеширование запросов для дальнейшего повышения производительности.