Это продолжение, начало этого материала смотрите здесь.
Итак, в конце 2010 года японский разработчик Ёсинори Мацунобу (Yoshinori Matsunobu) запустил свой, теперь уже чрезвычайно известный проект по созданию NoSQL-плагина для MySQL, который назвал HandlerSocket. Этот интерфейсный плагин позволяет клиентскому приложению подключаться напрямую к движку данных MySQL для устранения избыточной нагрузки, характерной для традиционных запросов через интерфейс SQL и неприемлемой для высоконагруженных БД.
Давайте поясним последнее ключевое утверждение. При традиционной работе через SQL-интерфейс, со стороны логики работы сервера часто наблюдается очень заметный оверхед (sql overhead).
Судите сами: каждый раз при поступлении любого запроса выполняется его лексический анализ, парсинг, обращение к схеме (чтобы узнать поля и индексы), блок работы с query cache, запускается оптимизатор, анализ связанных индексов, выборка стратегии запроса, открытие и блокировка таблиц, потом следует сам запрос к движку и его обслуживание, форматирование полученных данных, закрытие и разблокировка таблиц (на самом деле этот список слишком неполный, детали здесь я просто опускаю).
Особенно эти накладные расходы становятся заметны при интенсивной работе с однотипными запросами характерными для движков CMS на более-менее популярных сайтах, которые выполняются, условно говоря, «много сотен раз в секунду».
В связи с этим, возвращаясь к истории и причинам разработки HandlerSocket, его создатель с сожалением пишет, что даже после выхода версии MySQL 5.5, где быстродействие сервера было существенно улучшено (для чего решены многие хронические проблемы с мьютексами), необходимый ему уровень производительности так и не был достигнут.
Яшинори рассказывает, что работая в DeNA (крупнейшая японская социальная сеть с игровой составляющей), он имеет дело с частотой запросов к MySQL колеблющихся в диапазоне от 200 000 до 500 000 запросов в секунду, что, конечно же, классический MySQL выдержать даже теоретически неспособен.
Яшинори Мацунобу,
автор HandlerSocket NoSQL plugin for MySQL
Самостоятельный анализ узких мест работы MySQL привел к тому, что этот исследователь фактически «вычленил» SQL из работы БД, разработав свой собственный NoSQL-протокол доступа. Основная причина, по которой выбор сделан именно в пользу NoSQL — очень быстрый поиск по первичному ключу и возможность избавиться от наиболее «тормознутого участка» во всем MySQL — его SQL-подсистемы.
Теперь давайте перейдем к более конкретному рассмотрению HandlerSocket.
SHOW GLOBAL STATUS, SHOW ENGINE INNODB STATUS, SHOW PROCESSLIST
и так далее. fsync()
;Begin; multiple DMLs(row format);
») Приведу короткий, принципиальный алгоритм установки HandlerSocket, за подробностями отсылаю к официальной документации:
1. Загружаем исходный код HandlerSocket и собираем его:
./configure —with-mysql-source=... —with-mysql-bindir=... ; make; make install
2. Заходим в командную строку как root
и активируем плагин HandlerSocket в MySQL:
mysql> INSTALL PLUGIN ’HandlerSocket’ soname ’HandlerSocket.so’;
3. После этого будут собраны и установлены как серверный (handlersocket plugin), так и клиентский (libhsclient) код. Теперь желательно убедиться в том, что установка прошла успешно и плагин запущен, сделать это можно через ’show processlist
’:
mysql> SHOW PROCESSLIST; +----+---------+------+-------------------------------------------+ | Id | Command | Time | State | +----+---------+------+-------------------------------------------+ | 1 | Connect | NULL | handlersocket: mode=rd, 0 conns, 0 active | | 2 | Connect | NULL | handlersocket: mode=rd, 0 conns, 0 active | ... | 16 | Connect | NULL | handlersocket: mode=rd, 0 conns, 0 active | | 17 | Connect | NULL | handlersocket: mode=wr, 0 conns, 0 active |
Протокол HandlerSocket является плагином с интерфейсом демона, который поддерживается в MySQL начиная с версии 5.1, соответственно, нужен сервер БД как минимум этой версии или выше. При самостоятельной сборке HandlerSocket не придется изменять исходные коды сервера, но должны быть доступны как исходные (путь к ним указывается в ключе —with-mysql-source
), так и бинарные коды MySQL (ключ —with-mysql-bindir
). Частый источник таинственных проблем — несовпадения версий дистрибутива и исходных кодов при этой процедуре. Дополнительно нужно проверить доступность портов 9998 и 9999 из внешнего мира (или измените их дефолтные значения в файле конфигурации my.cnf
). Как вариант, можно использовать Percona Server (форк MySQL), где этот протокол изначально интегрирован в дистрибутив.
Текущая версия HandlerSocket реализована только под Linux, версия под Windows не планируется. На данный момент имеются готовые классы для следующих ведущих языков программирования: C++, PHP, Python, Ruby, Java, JavaScript/Node.js. Доступны модули для веб-серверов, например для Nginx, который обращается к данным MySQL через протокол HandlerSocket и отдает данные клиенту в формате JSON.
Будем считать, что установка успешно завершена. Но перед тем как мы начнем экскурс в устройство команд HandlerSocket, следует сразу уяснить его некоторые архитектурные особенности этого хранилища/протокола типа ключ-значение, а именно — наличие двух разных типов потоков: для доступа клиентов по чтению и по записи.
Как можно увидеть в файле /etc/mysql/my.cnf
, по-умолчанию стартует 16 читающих тредов (которые будут доступны клиентам на 9998 порту) и только 1 пишущий (доступный на 9999 порту).
Вот как выглядят все эти параметры по-умолчанию в конфигурационном файле:
loose_handlersocket_port = 9998 # номер порта, на котором ожидаются запросы на чтение loose_handlersocket_port_wr = 9999 # номер порта, на котором ожидаются запросы на запись loose_handlersocket_threads = 16 # количество рабочих потоков (для запросов по чтению) loose_handlersocket_threads_wr = 1 # количество рабочих потоков (для запросов по записи) open_files_limit = 65535 # максимальное количество разрешенных конкурентных соединений
Если взглянуть выше ещё раз на вывод команды ’show processlist
’, то отчетливо видны как читающие треды (атрибут handlersocket: mode=rd), так и один пишущий (handlersocket: mode=wr). Естественно, в зависимости от специфики и интенсивности конкретной задачи вам предлагается самостоятельно сконфигурировать разумный баланс между количественными отношениям между этими потоками.
Поэтому, как бы там ни было, просто описываю здесь эту недокументированную опцию, которая, несмотря на её малоизвестность, прекрасно работает на практике. Итак, следующие переменные (вносимые в конфигурационный файл my.cnf
самостоятельно) ответственны за авторизацию в HandlerSocket:
handlersocket_plain_secret = YOUR_PASS handlersocket_plain_secret_wr = YOUR_PASS
Соответственно, первая строчка отвечает за доступ читающих потоков, а вторая — за пишущие (здесь вместо параметра YOUR_PASS
нужно вписать свой пароль, естественно, у разных типов потоков они могут не совпадать).
Аутенфикация в HandlerSocket реализована и действует в пределах текущей сессии, а не для каждой команды. И, наконец, вы можете разрешить отдельную авторизацию, например, только потокам ответственным за запись, — тогда просто удалите строчку handlersocket_plain_secret
из конфигурационного файла, оставив заполненной handlersocket_plain_secret_wr
. Подробное описание всех остальных параметров настройки HandlerSocket можно найти в официальной документации.
Посмотреть множество других фактов и дополнительные сведения об Handlersocket можно в этой презентации от компании Percona
~
Читать этот материал дальше. Оглавление этой серии статей — здесь.