Ускоряем mysql в десятки раз с использованием handlersocket
DESCRIPTION
TRANSCRIPT
HANDLERSOCKETИЛИ
УСКОРЯЕМ MYSQL
В ДЕСЯТКИ РАЗ
Александр Календарев
ПЛАНКратко об HandlerSoket
HandlerSoket изнутри
Инсталляция
HandlerSoket Протокол
Использование HandlerSoket
ЧТО МОЖЕТ ДАТЬ УСКОРЕНИЕ
Отсутствие разбора SQL запроса
Выполнение несколько операций в одном запросе
Снижение сетевого трафика за счет протокола
ИНТЕРФЕЙС HANDLER
HANDLER tbl_name OPEN [ [AS] alias]
HANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,...)
[ WHERE where_condition ] [LIMIT ... ]
HANDLER tbl_name CLOSE
HANDLERSOKET
Плагин к MySQL
Предоставляет NoSQL интерфейс
к таблицам данных MySQL
Автор: Akira Higuchi
ВОЗМОЖНОСТИ
Представляет доступ к данным по индексу
Операции с данными: = < и >
Top и Limit
ГДЕ
Плагин к MySQL 5.2.5 https://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL
PerconaServer 5.1http://www.percona.com/downloads/Percona-Server-5.1/LATEST/
СТРУКТУРА HANDLERSOCKET
Handler Interface
InnoDb MyISAM Other storage engines …
SQL Layer Handlersocket Plugin
Listener for libmysql
Libmysqllibhsclient
Applications
mysqld
client app
СЕТЕВОЕ ВЗАИМОДЕЙСТВИЕ
Read Thread
Read Thread
Read Thread
Read Thread
Write Thread
HS
APIDB
Engine
Client
Client
Client
Client
port 9998
port 9999
ПОТОКОВАЯ МОДЕЛЬ
Небольшое кол-во потоков
Несколько коннекций на один поток epoll модель
Небольшое потребление памяти на один поток
СТРУКТУРА ЧИТАЮЩЕГО ПОТОКА
reads requests from many clients
locks the DB, gets a read view
executes many requests
unlocks the DB
returns responses to clients
locks/unlocks (1/#conns)
СТРУКТУРА ПИШУЩЕГО ПОТОКА
reads requests from many clients
Locks DB, begins a transaction
executes many requests
commits, and unlocks the DB
returns responses to clients
locks/unlocks (1/#conns)
ИНСТАЛЛЯЦИЯ
./configure
--with-mysql-source=...
--with-mysql-bindir=...
--with-mysql-plugindir=...
ИНСТАЛЛЯЦИЯ
./mysql_config --variable=pkglibdir
/usr/local/mysql/lib
mysql_config --plugindir
/usr/local/mysql/lib/plugin
--with-mysql-bindir
--with-mysql-plugindir
ИНСТАЛЛЯЦИЯ
$ make
$ sudo make install
$ vi my.conf
ИНСТАЛЛЯЦИЯ
[mysqld] # the port number to bind to (and for write)loose_handlersocket_port = 9998loose_handlersocket_port_wr = 9999
# the number of worker threads loose_handlersocket_threads = 16loose_handlersocket_threads_wr = 1
#to allow handlersocket accept connectionsopen_files_limit = 65535
ИНСТАЛЛЯЦИЯ
mysql> install plugin handlersocket soname 'handlersocket.so';
ПРОВЕРКА: SHOW PROCESSLIST
mode=rd mode=wr
ПРОВЕРКА: SHOW PROCESSLIST
5 conns, 0 active
ПРОТОКОЛTeкстовый
telnet localhost 9998
Соединение persisten
ПОЧЕМУ СЛЕДУЕТ ЗНАТЬ ПРОТОКОЛ?Если что-то на получается –то
проверяем используя telnet
Зная Протокол – лучше оптимизиация
Написание тестов и патчей
ПОСЛЕДОВАТЕЛЬНОСТЬ ВЫПОЛНЕНИЯ
Создать Индекс
Выполнить операцию
ОПЕРАЦИИ
=>, >=<, <=
+ INSERT
= UPDATE
SELECT
ПРИМЕРCREATE TABLE `test`.`test` (
`keyid` VARCHAR(45),
`value` VARCHAR(45),
`code` INT NULL ,
`code2` varchar(32) ,
PRIMARY KEY (`keyid`) ,
INDEX `code` (`code` ASC)
INDEX `code2` (`code`, `code2`)
)
СОЗДАНИЕ ИНДЕКСАP <indexid> <dbname> <tablename>
<indexname> <columns>Разделитель \tab
P 0 test test PRIMARY keyid,value
P 1 test test code keyid,code
P 3 test test code2 keyid,code,code2
ПРОСТАЯ ВЫБОРКА<indexid> <op> <vlen> <v1> ... <vn>
<limit> <offset>
>P 1 test test code keyid,codeSELECT keyid,value FROM test.testWHERE code = ‘000123’
>1 = 1 000123
ПРОСТАЯ ВЫБОРКА<indexid> <op> <vlen> <v1> ... <vn>
<limit> <offset>
>P 1 test test code keyid,code
SELECT keyid,code FROM test.testWHERE code = 10 LIMIT 10
>1 = 1 10 10
ПРОСТАЯ ВЫБОРКА<indexid> <op> <vlen> <v1> ... <vn>
<limit> <offset>
>P 2 test test code keyid,code,code2
SELECT keyid,code,code2 FROM test.testWHERE code = 10 AND code2=‘a’ LIMIT
10
>2 = 2 10 a 10
ФОРМАТ ОТВЕТА <errorcode> <numcols> <r1> ...<rn>0 - успехРазделитель \tab
P0 test test PRIMARYcode,code2,keyid
0 1
0 = 1 100012
0 3 67 c 100012
ФОРМАТ ОТВЕТА <errorcode> <numcols> <r1> ...<rn>
P1 test test code code,code2,keyid
0 1
1 > 1 90 10
1 3 100200 91 a 100258 91 a 10027…
10 групп по 3
ВСТАВКА <indexid> '+' <vlen> <v1> ... <vn>Пишем в пишущий порт telnet localhost 99990 1 - успехРазделитель \tab
P0 test test PRIMARY code,code2,keyid
0 10 + 3 1 f 102113 0 1
УДАЛЕНИЕ / ОБНОВЛЕНИЕ <indexid> <op> <vlen> <v1> ... <vn>
<limit> <offset> <mop> <m1> ... <mk>0 1 - успехМодификатор U – update, D – delete
P0 test test PRIMARY code,code2,keyid
0 10 = 1 1000011 0 D
0 1 1
ОБНОВЛЕНИЕ / УДАЛЕНИЕ <indexid> <op> <vlen> <v1> ... <vn>
<limit> <offset> <mop> <m1> ... <mk>0 1 <numcols>Модификатор U – update, D – delete
P0 test test PRIMARY code,keyid
0 10 = 1 100003 1 0 U zzzzzzz 1000030 1 10 = 1 1000030 2 zzzzzzz 100003
КЛИЕНТСКИЕ БИБЛИОТЕКИ
libhsclient
Net::HandlerSocket
http://openpear.org/package/Net_HandlerSocket
http://github.com/tz-lom/HSPHP http://code.google.com/p/php-handlersocket/
КЛИЕНТСКИЕ БИБЛИОТЕКИ
https://github.com/kryton/java-handlersocket-client
http://pypi.python.org/pypi/python-handler-socket
http://packages.python.org/python-handler-socket/
https://github.com/winebarrel/ruby-handlersocket https://github.com/miyucy/handlersocket https://github.com/igrigorik/em-handlersocket https://github.com/quake/active_record_handlersocket
https://github.com/koichik/node-handlersocket
ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ
Формирование фронтэнда (список товаров) PHP + HS
Поиск товаров по характеристикам PHP + Sphinx + HS
Автокомплит (список товаров) JS + nginx + HS
ФОРМИРОВАНИЕ ФРОНТЭНДАСписок товаров:
$hs->openIndex(0, $dbname, 'good', 'PRIMARY', 'id,title,price,count');
$hs->openIndex(1, $dbname, 'description', 'PRIMARY', 'good_id,description');
$priceItems = $hs->executeSingle(0, '=', array('1'),20);
foreach ( $priceItems as &$item ) {
$item[’6'] = $hs->executeSingle(1, '=', array($item['0'], $lang_id));
}
ПОИСК ТОВАРА Поиск по индексу модели (Sphinx)
Поиск индексу характеристики (Sphinx)
Выборка товара по id HandlerSocket (см. формирование фронтэнда)
$pricItems = $sphinx->Query( $q );
foreach ( $pricItemsId as $id ) {
$item[] = $hs->executeSingle(1, '=', array($id));
}
АВТОКОМПЛИТ ( NGX_HSJSON )JS формирует HTTP запрос
GET /autocomplete/sie[mens]
Модуль nginx формирует запрос P 0 shop brands name,id 0 >= 1 1 sie 10
HS возвращает результат 0 2 siemens 32
Модуль nginx формирует ответJSON {“name”: “Siemens”, “id”: 32}
МОДУЛЬ NGX_HANDLERSOCKET_JSONhttps://github.com/akalend/ngx_http_handlersocket_json_module
location ~ /cities/(.+)/$ {hs_json; # enable modulehs_json_host 127.0.0.1; # IP хоста
hs_json_port 9998; # портhs_json_db test; # БДhs_json_table city; # имя таблицыhs_json_index name; # имя индекса hs_json_fields name,id; # список полей
hs_json_op "=”; # операция hs_json_limit 10; # аналог limit MySQL hs_request $1; # запрос
}
АНАЛОГ INNODB-MEMCACHED
MySQL 5.6.2 – экспериментальная (12.04)
Используется InnoDb-API
Memcached Протокол
Настройка через таблицыconteyners, config_options, cache_policies
СТРУКТУРА INNODB-MEMCACHED
СРАВНЕНИЕ С АНАЛОГАМИ NOSQL
Hs
Mc
McDb
Tokyo Tyrant
Redis
0 5 10 15 20 25 30
Write 100K по 32 Byte
Read 100K по 32 Byte
СРАВНЕНИЕ С NOSQL
1 16 64 512 1024 40960
20
40
60
80
100
120
140
McHsredis
ЧТЕНИЕ 9998/9999 PORT 100K ПО 32B
24.6 24.8 25 25.2 25.4 25.6 25.8 26
port 9999port 9998
ССЫЛКИ http://yoshinorimatsunobu.blogspot.com/search/label
/handlersocket
http://www.slideshare.net/akirahiguchi/handlersocket-plugin-for-mysql-4664154
http://www.percona.com/docs/wiki/percona-server%3Afeatures%3Aspecial%3Ahandlersocket
http://habrahabr.ru/blogs/nosql/113040/
http://l-o-n-g.livejournal.com/153756.html
HANDLERSOCKET
Эффективная технология
Ускоряет обращение к MySQL более чем в десятки раз
Есть клиенты на многих языках
АЛЕКСАНДР КАЛЕНДАРЕВ
@akalendhttp://githab.com/akalend
http://akalend.habrahabr.ru/blog