在本文中,我们将讨论如何使用ProxySQL在使用Sphinx/Manticore Search时路由插入到分布式实时索引。
Manticore的分布式索引允许在多个实时索引上进行UPDATE操作,UPDATE会发送到所有索引,但只在一个索引上发生更改(假设跨索引的ID是唯一的)。
对于插入操作,分布式索引不知道应该选择哪个索引,这意味着我们需要在应用程序代码中将插入发送到某个实时子索引。这的缺点是,对分布式索引进行更改(例如添加新的实时子索引)需要更改应用程序代码。
ProxySQL
是一个针对MySQL的SQL感知代理。由于Sphinx和Manticore Search具有MySQL兼容的协议,ProxySQL可用于简单的Manticore服务器负载均衡。但ProxySQL还有一个很棒的功能:正则查询路由引擎,它不仅可以路由查询,还可以重写查询。
我们接下来要做的是向分布式索引发送插入,并借助ProxySQL根据选定的标准重写查询,通过更改插入的目标索引。这样,如果我们添加新的分片到分布式索引或更改文档在分片间的分布方式,就不需要修改应用程序代码。
让我们考虑一个由两个实时子索引组成的分布式索引。我们希望根据文档ID的奇偶性来分发插入。
index myrt {
type = distrubuted
local = myrt1
local = myrt2
}
将Manticore Search服务器添加为后端
在这个示例中,我们将为Manticore服务器使用主机组ID 2。
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并根据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;
创建正则表达式模式时要非常注意,同时要注意如何在应用程序代码中构建查询,以确保查询能被捕获。
通过ProxySQL运行SphinxQL
在运行第一个查询之前,我们需要在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;