В этой статье мы обсудим, как использовать ProxySQL для маршрутизации вставок в распределённый RT‑индекс при работе с Sphinx/Manticore Search.
Распределённый индекс в Manticore позволяет выполнять UPDATE над несколькими RealTime‑индексами, поскольку UPDATE отправляется ко всем индексам, но изменение происходит только в одном индексе (при условии, что у вас уникальные ID во всех индексах).
Для вставок распределённый индекс не знает, в какой индекс следует направить запрос, поэтому нам необходимо отправлять INSERT в один из RealTime‑подиндексов, что должно быть реализовано в коде приложения. Это имеет недостаток: при изменении распределённого индекса (например, добавлении нового RT‑подиндекса) требуется вносить изменения в код приложения.
ProxySQL
— это SQL‑ориентированный прокси для MySQL. Поскольку Sphinx и Manticore Search используют совместимый с MySQL протокол, ProxySQL можно использовать для простого балансирования серверов Manticore. Но у ProxySQL есть отличительная возможность: движок маршрутизации запросов на основе регулярных выражений, который позволяет не только маршрутизировать запросы, но и переписывать их.
Дальше мы отправим INSERT в распределённый индекс и с помощью ProxySQL перепишем запрос, изменив целевой индекс вставки в зависимости от выбранного критерия. Таким образом, нам не придётся вносить изменения в код приложения при добавлении новых шардов в распределённый индекс или при изменении способа распределения документов по шардам.
Рассмотрим распределённый индекс, состоящий из двух RT‑подиндексов. Мы хотим распределять вставку документов в зависимости от чётности их ID.
index myrt {
type = distrubuted
local = myrt1
local = myrt2
}
Добавление сервера Manticore Search в качестве бэкенда
В этом примере мы будем использовать группу хостов с id 2 для нашего сервера Manticore.
Admin> INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES(2,'192.168.1.224',9306);
Admin> LOAD MYSQL SERVERS TO RUNTIME;
Добавление правил переписывания в ProxySQL
Мы хотим вставлять документы с нечётными ID в myrt1 и документы с чётными ID в myrt2. Мы определяем 2 правила, которые захватывают ID и в зависимости от их чётности меняют имя индекса перед отправкой запроса в Manticore.
Admin> INSERT INTO mysql_query_rules(rule_id,match_pattern,replace_pattern,destination_hostgroup,active)
VALUES(32,
'^INSERT INTO (\w+)\(id,content,title,user_id,group_id\) VALUES\(([0-9]*)([02468])',
'INSERT INTO \12(id,content,title,user_id,group_id) VALUES(\2\3',2,1);
Admin> INSERT INTO mysql_query_rules(rule_id,match_pattern,replace_pattern,destination_hostgroup,active)
VALUES(33,
'INSERT INTO (\w+)\(id,content,title,user_id,group_id\) VALUES\(([0-9]*)([13579])',
'INSERT INTO \11(id,content,title,user_id,group_id) VALUES(\2\3',2,1);
Admin> LOAD MYSQL QUERY RULES TO RUNTIME;
Обратите особое внимание при создании шаблонов регулярных выражений и при формировании запросов в коде приложения, чтобы гарантировать, что запросы будут корректно захвачены.
Выполнение SphinxQL через ProxySQL
Прежде чем выполнить первые запросы, нам нужно создать пользователя в ProxySQL, который по умолчанию будет использовать группу хостов с id 2, чтобы его запросы маршрутизировались к нашему серверу Manticore.
Admin> INSERT INTO mysql_users(username,password,active,default_hostgroup) VALUES('test','pass',1,2);
Admin> LOAD MYSQL USERS TO RUNTIME;
А теперь выполним несколько вставок (используя соединение ProxySQL):
mysql> INSERT INTO myrt(id,content,title,user_id,group_id) VALUES(1,'test1','test1',1,1);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO myrt(id,content,title,user_id,group_id) VALUES(2,'test2','test2',1,1);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO myrt(id,content,title,user_id,group_id) VALUES(20,'test20','test20',1,1);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO myrt(id,content,title,user_id,group_id) VALUES(11,'test11','test11',1,1);
mysql> select * from myrt;
+------+---------+----------+--------+
| id | user_id | group_id | title |
+------+---------+----------+--------+
| 1 | 1 | 1 | test1 |
| 2 | 1 | 1 | test2 |
| 11 | 1 | 1 | test11 |
| 20 | 1 | 1 | test20 |
+------+---------+----------+--------+
4 rows in set (0.00 sec)
mysql> select * from myrt1;
+------+---------+----------+--------+
| id | user_id | group_id | title |
+------+---------+----------+--------+
| 1 | 1 | 1 | test1 |
| 11 | 1 | 1 | test11 |
+------+---------+----------+--------+
2 rows in set (0.00 sec)
mysql> select * from myrt2;
+------+---------+----------+--------+
| id | user_id | group_id | title |
+------+---------+----------+--------+
| 2 | 1 | 1 | test2 |
| 20 | 1 | 1 | test20 |
+------+---------+----------+--------+
2 rows in set (0.00 sec)
Наконец, не забудьте сохранить изменения, внесённые в ProxySQL, на диск для постоянства:
Admin> SAVE MYSQL QUERY RULES TO DISK; SAVE MYSQL SERVERS TO DISK; SAVE MYSQL USERS TO DISK;