利用一个数据库中间件扩展MySQL集群
发布日期:2016-4-25 16:4:36
上回我写了一篇有关kingshard架构设计的文章,得到很多热心网友的关注,我很开心。但其中有网友提到:希望再写一篇关于如何利用kingshard搭建一个可扩展的MySQL集群的文章。所以在这里利用假期时间,写了一篇kingshard使用指南,在这篇文章中,将结合自己对MySQL Proxy的理解,为大家讲述如何正确使用kingshard数据库中间件。 一、kingshard的应用场景
面对上面这些问题,我们可以在客户端代码中逐一实现。但是这样也会使得客户端越来越重,不那么灵活。作者一直从事数据库相关工作的开发,正是基于数据库开发的痛点,设计和实现了kingshard数据库中间件。kingshard对上述5类问题都有比较合适的解决方案。下面对kingshard的主要功能做一些介绍。 二、安装与启动说明 1. 设置配置文件 下面我给出了一个配置文件范例,用户可以自行按照自己的需求逐项配置,如图1所示的代码: 图1 这里我着重说一下分表的配置规则: kingshard支持两种类型的分表规则:hash与range。 kingshard分表涉及到的子表,需要用户在各个db手动创建好,并且格式是:table_name_%4d,也就是说子表下标由4位数组成。比如:table_name_0000,table_name_0102。 所有操作未分表的SQL语句都将发送到默认节点。 2.安装与启动kingshard 按照以下的步骤来安装与启动kingshard:
请注意:kingshard会响应SIGINT,SIGTERM,SIGQUIT这三个信号,平滑退出。在部署kingshard机器上应避免产生这三个信号,以免造成kingshard非正常退出!后台运行kingshard建议使用supervisor工具 三、跨节点分表 因为我只有两台MySQL,所以搭建了两个节点,这两个节点都只有一台Master 角色的MySQL数据库,具体的拓扑图,如图2所示: 图2 1.分表操作演示 分表操作有hash与range两种类型,在这里只演示hash类型的分表操作,range类型的分表与之类似,就不赘述。 1.1 手动创建子表 在node1与node2上各创建4张子表,下面只给出在node1上test_shard_hash_0000的建表SQL语句,其他子表的建表SQL语句与之类似。 node1包含:
node2包含:
如下所示: CREATE TABLE `test_shard_hash_0000` ( `id` bigint(64) unsigned NOT NULL, `str` varchar(256) DEFAULT NULL, `f` double DEFAULT NULL, `e` enum('test1','test2') DEFAULT NULL, `u` tinyint(3) unsigned DEFAULT NULL, `i` tinyint(4) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1.2.分表的插入与查询 执行下面所说的SQL语句,根据查询的结果可以看出SQL语句根据分表规则落到不同的子表。查询操作(select)可以跨多个node,当更新操作涉及到多个node时,kingshard会以非事务的方式执行跨node的更新。为保证数据一致性,请根据实际需求使用非事务方式的跨node更新操作。 mysql> insert into test_shard_hash(id,str,f,e,u,i) values(15,"flike",3.14,'test2',2,3); Query OK, 1 row affected (0.01 sec) mysql> mysql> insert into test_shard_hash(id,str,f,e,u,i) values(7,"chen",2.1,'test1',32,3); Query OK, 1 row affected (0.01 sec) mysql> insert into test_shard_hash(id,str,f,e,u,i) values(17,"github",2.5,'test1',32,3); Query OK, 1 row affected (0.00 sec) mysql> insert into test_shard_hash(id,str,f,e,u,i) values(18,"kingshard",7.3,'test1',32,3); Query OK, 1 row affected (0.01 sec) 如下所示的是对应的SQL日志: 2015/09/02 18:48:24 - INFO - 127.0.0.1:55003->192.168.59.103:3307:insert into test_shard_hash_0007(id, str, f, e, u, i) values (15, 'flike', 3.14, 'test2', 2, 3) 2015/09/02 18:49:05 - INFO - 127.0.0.1:55003->192.168.59.103:3307:insert into test_shard_hash_0007(id, str, f, e, u, i) values (7, 'chen', 2.1, 'test1', 32, 3) 2015/09/02 18:49:51 - INFO - 127.0.0.1:55003->127.0.0.1:3306:insert into test_shard_hash_0001(id, str, f, e, u, i) values (17, 'github', 2.5, 'test1', 32, 3) 2015/09/02 18:50:21 - INFO - 127.0.0.1:55003->127.0.0.1:3306:insert into test_shard_hash_0002(id, str, f, e, u, i) values (18, 'kingshard', 7.3, 'test1', 32, 3) 我们可以看到前两条SQL发送到了node2的master上了,后两条SQL发送到node1上的master了。 然后我们可以用select语句查看数据,且select支持跨node查询。如图3所示: 图3 由于是hash类型的分表,所以对于select范围类型的查询,必须查询每一个子表。对应的SQL日志如下所示: 2015/09/02 18:55:01 - INFO - 127.0.0.1:55003->127.0.0.1:3306:select * from test_shard_hash_0000 where id < 18 2015/09/02 18:55:01 - INFO - 127.0.0.1:55003->127.0.0.1:3306:select * from test_shard_hash_0001 where id < 18 2015/09/02 18:55:01 - INFO - 127.0.0.1:55003->127.0.0.1:3306:select * from test_shard_hash_0002 where id < 18 2015/09/02 18:55:01 - INFO - 127.0.0.1:55003->127.0.0.1:3306:select * from test_shard_hash_0003 where id < 18 2015/09/02 18:55:01 - INFO - 127.0.0.1:55003->192.168.59.103:3307:select * from test_shard_hash_0004 where id < 18 2015/09/02 18:55:01 - INFO - 127.0.0.1:55003->192.168.59.103:3307:select * from test_shard_hash_0005 where id < 18 2015/09/02 18:55:01 - INFO - 127.0.0.1:55003->192.168.59.103:3307:select * from test_shard_hash_0006 where id < 18 2015/09/02 18:55:01 - INFO - 127.0.0.1:55003->192.168.59.103:3307:select * from test_shard_hash_0007 where id < 18 对应等值的select查询,kingshard会计算出具体命中的子表,然后只会在相应的子表中查询。对应的SQL如图4所示: 图4 如下所示的是对应的SQL日志: 2015/09/02 18:59:37 - INFO - 127.0.0.1:55003->127.0.0.1:3306:select * from test_shard_hash_0002 where id = 18 1.3. 分表的更新 当更新的记录落在同一个子表时,kingshard支持这类操作。在上面插入的记录中,id为7和15的记录都落在test_shard_hash_0007中,所以可以成功地执行下面的SQL: mysql> update test_shard_hash set u=123 where id = 15 or id = 7; Query OK, 2 rows affected (0.01 sec) 对应的SQL日志如下所示: 2015/09/02 19:17:27 - INFO - 127.0.0.1:55003->192.168.59.103:3307:update test_shard_hash_0007 set u = 123 where id = 15 or id = 7 当更新的记录落在不同的子表,kingshard会以非事务的方式将更新操作发送到多个node上。例如执行如下SQL: mysql> update test_shard_hash set str="myworld_test4" where id in(128,1,231); Query OK, 3 rows affected (0.02 sec) 对应的SQL日志如下所示: 2016/03/15 15:18:27 - OK - 1.2ms - 127.0.0.1:60730->127.0.0.1:3306:update test_shard_hash_0000 set str = 'myworld_test4' where id in (128, 1, 231) 2016/03/15 15:18:27 - OK - 0.5ms - 127.0.0.1:60730->127.0.0.1:3306:update test_shard_hash_0001 set str = 'myworld_test4' where id in (128, 1, 231) 2016/03/15 15:18:27 - OK - 6.8ms - 127.0.0.1:60730->192.168.59.103:3307:update test_shard_hash_0007 set str = 'myworld_test4' where id in (128, 1, 231) 2.指定发送的node 在有的时候我们需要操作的表,不在default node中。在kingshard中允许用户将特定的sql路由到指定的node上。只需要在sql语句前面加上包含node名称的注释(连接MySQL时需要加上-c选项,避免客户端过滤掉注释)。如图5所示 图5 3. 强制读主库 有时候在主库中插入数据后,希望立即从主库读出来。在kingshard中由于读写分离的原因,select默认会发送到相应node的从库上。但是只需要在select语句中加入相应的注释项(/*master*/),就可以将select语句发送到主库。如图6所示 图6 4. 跨node的sum与count函数 在kingshard中,支持sum和count函数,kingshard会将相应的SQL发送到正确的DB,并将结果合并起来再返回给客户的。例如图7所示的: 图7 如下所示的相应的SQL日志: 2015/09/03 14:49:01 - INFO - 127.0.0.1:55768->127.0.0.1:3306:select count(id) from test_shard_hash_0000 where id > 1 2015/09/03 14:49:01 - INFO - 127.0.0.1:55768->127.0.0.1:3306:select count(id) from test_shard_hash_0001 where id > 1 2015/09/03 14:49:01 - INFO - 127.0.0.1:55768->127.0.0.1:3306:select count(id) from test_shard_hash_0002 where id > 1 2015/09/03 14:49:01 - INFO - 127.0.0.1:55768->127.0.0.1:3306:select count(id) from test_shard_hash_0003 where id > 1 2015/09/03 14:49:01 - INFO - 127.0.0.1:55768->192.168.59.103:3307:select count(id) from test_shard_hash_0004 where id > 1 2015/09/03 14:49:01 - INFO - 127.0.0.1:55768->192.168.59.103:3307:select count(id) from test_shard_hash_0005 where id > 1 2015/09/03 14:49:01 - INFO - 127.0.0.1:55768->192.168.59.103:3307:select count(id) from test_shard_hash_0006 where id > 1 2015/09/03 14:49:01 - INFO - 127.0.0.1:55768->192.168.59.103:3307:select count(id) from test_shard_hash_0007 where id > 1 2015/09/03 14:49:14 - INFO - 127.0.0.1:55768->127.0.0.1:3306:select sum(id) from test_shard_hash_0000 where id > 1 2015/09/03 14:49:14 - INFO - 127.0.0.1:55768->127.0.0.1:3306:select sum(id) from test_shard_hash_0001 where id > 1 2015/09/03 14:49:14 - INFO - 127.0.0.1:55768->127.0.0.1:3306:select sum(id) from test_shard_hash_0002 where id > 1 2015/09/03 14:49:14 - INFO - 127.0.0.1:55768->127.0.0.1:3306:select sum(id) from test_shard_hash_0003 where id > 1 2015/09/03 14:49:14 - INFO - 127.0.0.1:55768->192.168.59.103:3307:select sum(id) from test_shard_hash_0004 where id > 1 2015/09/03 14:49:14 - INFO - 127.0.0.1:55768->192.168.59.103:3307:select sum(id) from test_shard_hash_0005 where id > 1 2015/09/03 14:49:14 - INFO - 127.0.0.1:55768->192.168.59.103:3307:select sum(id) from test_shard_hash_0006 where id > 1 2015/09/03 14:49:14 - INFO - 127.0.0.1:55768->192.168.59.103:3307:select sum(id) from test_shard_hash_0007 where id > 1 5. 跨node的order by kingshard支持跨node的select操作使用order by,kingshard先将合适的SQL发生到对应的node,然后将结果集在内存中排序,从而实现select的order by操作。示例如图8所示: 图8 对应的SQL日志如下所示: 2015/09/03 14:54:11 - INFO - 127.0.0.1:55768->127.0.0.1:3306:select * from test_shard_hash_0000 where id > 1 order by id asc 2015/09/03 14:54:11 - INFO - 127.0.0.1:55768->127.0.0.1:3306:select * from test_shard_hash_0001 where id > 1 order by id asc 2015/09/03 14:54:11 - INFO - 127.0.0.1:55768->127.0.0.1:3306:select * from test_shard_hash_0002 where id > 1 order by id asc 2015/09/03 14:54:11 - INFO - 127.0.0.1:55768->127.0.0.1:3306:select * from test_shard_hash_0003 where id > 1 order by id asc 2015/09/03 14:54:11 - INFO - 127.0.0.1:55768->192.168.59.103:3307:select * from test_shard_hash_0004 where id > 1 order by id asc 2015/09/03 14:54:11 - INFO - 127.0.0.1:55768->192.168.59.103:3307:select * from test_shard_hash_0005 where id > 1 order by id asc 2015/09/03 14:54:11 - INFO - 127.0.0.1:55768->192.168.59.103:3307:select * from test_shard_hash_0006 where id > 1 order by id asc 2015/09/03 14:54:11 - INFO - 127.0.0.1:55768->192.168.59.103:3307:select * from test_shard_hash_0007 where id > 1 order by id asc 四、单node的事务 kingshard支持在单个node上执行事务,也就是说同一个事务不能跨多个node,当出现跨node的情况时,kingshard会返回错误给客户端。可以跨同node上的不同子表。例子如下所示: mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> insert into test_shard_hash(id,str,f,e,u,i) values(23,'proxy',9.2,'test1',12,3); Query OK, 1 row affected (0.00 sec) mysql> commit; Query OK, 0 rows affected (0.01 sec) 当在一个事务中,出现跨node的SQL语句时,kingshard会返回如下所示的错误: #SQL语句在node2中执行 mysql> insert into test_shard_hash(id,str,f,e,u,i) values(31,'proxy',9.2,'test1',12,3); Query OK, 1 row affected (0.01 sec) #SQL语句在需要在node1执行,跨node了。 mysql> insert into test_shard_hash(id,str,f,e,u,i) values(40,'proxy',9.2,'test1',12,3); ERROR 1105 (HY000): transaction in multi node 六、kingshard的管理端操作 kingshard的管理接口,目前还是命令行的方式。后续有时间打算将其改成web方式。管理端具体的命令可以参考文档。管理端的命令格式,可以分为以下两类:
七、总结 kingshard开源两个月以来,得到了很多开发者的关注。这足以证明,大家对数据库中间件是有需求的,希望出现一款简单好用的MySQL Proxy。kingshard经过这两个月的迭代开发,也比较稳定了。据了解,有几个公司正在对其进行尝试。后续作者的主要精力会放在优化kingshard的性能上,同时完善kingshard已有的功能。如果大家对kingshard有什么想法或建议,可以发邮件联系我(flikecn#126.com),非常乐意和大家交流。 上一条: 时间序列数据库--索引 下一条: MYSQL主备复制结构的搭建和切换
|