# Using ProxySQL to route INSERTs in a distributed RealTime index

在本文中，我们将讨论如何使用 ProxySQL 在使用 Sphinx/Manticore Search 时将插入操作路由到分布式 RT 索引。

Manticore 的分布式索引允许在多个 RealTime 索引上执行 UPDATE 操作，因为 UPDATE 会被发送到所有索引，但更改仅发生在其中一个索引（假设索引之间具有唯一 ID）。

对于插入操作，分布式索引不知道应该选择哪个索引，这意味着需要将插入操作发送到其中一个 RealTime 子索引，这必须在应用程序代码中实现。这有一个缺点：如果对分布式索引进行更改（例如添加新的 RT 子索引），则需要在应用程序代码中进行更改。
[ProxySQL](http://www.proxysql.com/) 是一个用于 MySQL 的 SQL 意识代理。由于 Sphinx 和 Manticore Search 使用与 MySQL 兼容的协议，因此可以使用 ProxySQL 对 Manticore 服务器进行简单的负载均衡。但 ProxySQL 提供了一个强大的功能：一个正则表达式查询路由引擎，它不仅可以路由查询，还可以重写查询。

接下来我们要做的是将插入操作发送到分布式索引，并借助 ProxySQL 根据选定的标准通过更改插入的目标索引来重写查询。这样，即使我们在分布式索引中添加新的分片或更改文档在分片之间的分布方式，也不需要在应用程序代码中进行更改。

让我们考虑一个由两个 RT 子索引组成的分布式索引。我们希望根据文档 ID 的奇偶性来分配文档的插入操作。

```ini
index myrt {
     type  = distrubuted
     local = myrt1
     local = myrt2
}
```


### 将 Manticore Search 服务器添加为后端

在此示例中，我们将主机组 ID 2 用于我们的 Manticore 服务器。


```sql
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 之前更改索引名称。

```sql
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 服务器。

```sql
Admin> INSERT INTO mysql_users(username,password,active,default_hostgroup) VALUES('test','pass',1,2);

Admin> LOAD MYSQL USERS TO RUNTIME;
```

现在让我们运行一些插入操作（使用 ProxySQL 连接）：


```sql
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);


```

```sql
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 中所做的更改保存到磁盘以实现持久化：


```sql
Admin> SAVE MYSQL QUERY RULES TO DISK; SAVE MYSQL SERVERS TO DISK; SAVE MYSQL USERS TO DISK;

```
