在本文中,我们将讨论如何使用 ProxySQL 将插入路由到分布式 RT 索引,同时使用 Sphinx/Manticore Search。
Manticore 中的分布式索引允许在多个实时索引上进行 UPDATE,因为 UPDATE 会发送到所有索引,但更改仅发生在一个索引上(假设您在索引中具有唯一 ID)。
对于插入,分布式索引不知道应该选择哪个索引,这意味着我们需要将插入发送到一个实时子索引,这必须在应用程序代码中实现。这有一个缺点,即对分布式索引进行更改(例如,添加新的 RT 子索引)需要在应用程序代码中进行更改。
ProxySQL
是一个针对 MySQL 的 SQL 代理。由于 Sphinx 和 Manticore Search 具有与 mysql 兼容的协议,因此可以使用 ProxySQL 对 Manticore 服务器进行简单的负载均衡。但是 ProxySQL 具有一个很棒的功能:正则表达式查询路由引擎,它不仅允许路由查询,还可以重写查询。
我们接下来要做的是将插入发送到分布式索引,并在 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,并根据 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;