通过Amoeba对数据进行简单的分片

在前一小节的基础上,本小节进一步尝试Amoeba的分片功能,尝试将一个数据库表水平切分至两个数据库节点上。

Amoeba的分区相关配置

配置dbServers.xml

首先根据前一小节的配置,在dbServers.xml中增加一个dbServer元素(即是我们新增用于水平切分的数据库)如下:

<?xml version="1.0" encoding="gbk"?>

<!DOCTYPE amoeba:dbServers SYSTEM "dbserver.dtd">
<amoeba:dbServers xmlns:amoeba="http://amoeba.meidusa.com/">
...
 <dbServer name="server2"  parent="abstractServer">
  <factoryConfig>
   <!-- mysql ip -->
   <property name="ipAddress">192.168.0.1</property>1
  </factoryConfig>
 </dbServer>
 ...
</amoeba:dbServers>

1

这里仅仅在之前的dbServers.xml文件中增加了一段新的节点配置,server2同样继承了abstractServer的配置,唯一不同的是其主机地址不一样,因此它有自己的主机地址属性,你需要按自己的实际需求配置这个主机地址。

配置rule.xml

Example 3.4. 一个基本的rule.xml配置示例

<?xml version="1.0" encoding="gbk"?>
<!DOCTYPE amoeba:rule SYSTEM "rule.dtd">

<amoeba:rule xmlns:amoeba="http://amoeba.meidusa.com/">
  <tableRule name="staff" schema="test" defaultPools="server1,server2">1
            <rule name="rule1" ruleResult="POOLNAME">2
                   <parameters>ID</parameters>3
                   <expression><![CDATA[4
                 var division = ID % 2; 
                 case division when 0 then 'server1';
                               when 1 then 'server2';
                 end case;
                    ]]></expression>
            </rule>
   </tableRule>
</amoeba:rule>

1

tableRule的name属性定义了表名、schema为数据库名、defaultPools定义了该表的默认库。

2

在tableRule中定义了名为rule1的规则,规则的返回结果为POOLNAME,在这里ruleResult还有其他配置项,将在后面的章节中介绍。

3

parameters元素定义了切分的参数,比如在例子的场景中就是按照员工号来进行切分。通常parameters的配置为该表的某列列名或几列列名。

4

expression元素定义了类似VB Script的切分表达式。在本例中,Amoeba对ID(员工号)取余,如果员工号是单数则存储在server2中,员工号是双数则存储在server1中。


运行及验证

首先重复上小节的建表操作在新的数据库节点上创建test.staff表,方法如上

接着启动Amoeba实例,如上

根据以下步骤用MySQL客户端操作Amoeba:

$ mysql -uroot -ppassword -h127.0.0.1 -P8066
...
mysql> use test;
Database changed
mysql> DELETE FROM test.staff;1
Query OK, 4 rows affected (0.03 sec)
mysql> INSERT INTO test.staff (ID, NAME)2
    -> VALUES (1, 'Struct Chen.');
Query OK, 1 row affected (0.02 sec)
mysql> INSERT INTO test.staff (ID, NAME)3
    -> VALUES (2, 'Ning Sun.');
Query OK, 1 row affected (0.03 sec)
mysql> INSERT INTO test.staff (ID, NAME)4
    -> VALUES (2, 'Daisy Li.');
Query OK, 1 row affected (0.03 sec)

mysql> SELECT * FROM test.staff LIMIT 0, 50;5
+----+------------+
| ID | NAME       |
+----+------------+
|  3 | Daisy Li.  |
|  1 | Struct Che |
|  2 | Ning Sun.  |
+----+------------+
3 rows in set (0.00 sec)
...

1

由于之前的章节已经在staff表中插入过数据,为了避免结果混淆,先清空staff表。

2 3 4

向staff表插入三条数据。

5

查询staff表,事实上之前插入的三条数据被分片到了不同的数据库节点,但Amoeba的合并工作使得它们看起来像在一个库里,也因此可见Amoeba对客户端的透明。

分别查看server1和server2的数据情况,server1的数据情况:

$ mysql -uroot -ppassword -h127.0.0.1 -P3306
...
mysql> SELECT * FROM test.staff LIMIT 0, 50;
+----+-----------+
| ID | NAME      |
+----+-----------+
|  2 | Ning Sun. |
+----+-----------+
1 row in set (0.00 sec)
...

可以看见,ID为偶数的数据分片到了server1上,再看下server2的情况:

$ mysql -uroot -ppassword -h192.168.0.1 -P3306
...
mysql> SELECT * FROM test.staff LIMIT 0, 50;
+----+------------+
| ID | NAME       |
+----+------------+
|  3 | Daisy Li.  |
|  1 | Struct Che |
+----+------------+
2 rows in set (0.00 sec)
...

正如配置的那样,ID为奇数的数据被分片到了server2上。