mycat读写分离

mycat读写分离+垂直切分+水平切分+er分片+全局表 测试  

2016-09-30 15:16:39|  分类: mysql |举报 |字号 订阅


读写分离:利用最基础的mysql主从复制,事务性的查询无法分离出去(因为 会导致数据不一致 ),这样就无法做到真正的读写分离,因为有些场景可能大部分都是事物性的读。解决方法: galera for mysql 强一致性。

http://blog.csdn.net/benluobobo/article/details/51099607

安装使用过程遇到的问题:
1、mycat启动后报错,进程直接退出: Error: Exception thrown by the agent : java.net.MalformedURLException: Local host name unknown: java.net.UnknownHostException: ys-fs: ys-fs: Name or service not known

原因:本机要配置/etc/hosts  127.0.0.1 主机名

一、垂直切分测试:
1、schema.xml里面加入:
<schema name="weixin" checkSQLschema="false" sqlMaxLimit="100" dataNode="weixin" />
<schema name="yixin" checkSQLschema="false" sqlMaxLimit="100" dataNode="yixin" />
<schema name="sms" checkSQLschema="false" sqlMaxLimit="100" dataNode="sms" />

<dataNode name="weixin" dataHost="host0" database="weixin" />
<dataNode name="yixin" dataHost="host1" database="yixin" />
<dataNode name="sms" dataHost="host2" database="sms" />

<dataHost name="host0" maxCon="1000" minCon="10" balance="0"
   writeType="0" dbType="mysql" dbDriver="native">
   <heartbeat>select user()</heartbeat>
   <!-- can have multi write hosts -->
   <writeHost host="namenode" url="192.168.168.230:3306" user="root" password="youngsun" />
</dataHost>

<dataHost name="host1" maxCon="1000" minCon="10" balance="0"
   writeType="0" dbType="mysql" dbDriver="native">
   <heartbeat>select user()</heartbeat>
   <!-- can have multi write hosts -->
   <writeHost host="hadoop1" url="192.168.168.231:3306" user="root" password="youngsun" />
</dataHost>

<dataHost name="host2" maxCon="1000" minCon="10" balance="0"
   writeType="0" dbType="mysql" dbDriver="native">
   <heartbeat>select user()</heartbeat>
   <!-- can have multi write hosts -->
   <writeHost host="hadoop2" url="192.168.168.232:3306" user="root" password="youngsun" />
</dataHost>

2、server.xml加入:
<user name="test_wyh">
       <property name="password">test</property>
       <property name="schemas">weixin,yixin,sms</property>
</user>
3、遇到问题:
1)、Caused by: org.xml.sax.SAXParseException; lineNumber: 106; columnNumber: 16; The content of element type "mycat:schema" must match "(schema*,dataNode*,dataHost*)".
原因:要按照schema、datanode 、datahost的顺序放,不能打乱。也就是所有 schema要放一起,然后接着才能放datanode。。。。

2)、报1184错误,是因为没有 把datahost主机的权限授予mycat所在主机。
<writeHost host="hadoop2" url="192.168.168.232:3306" user="root" password="youngsun" />
这里的 用户要授予mycat所在主机远程访问权限:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'youngsun'

二、水平切分测试:
1、分别建立4个库:user0、user1、user2、user3。我这里4个库建在4个独立的主机上。
 CREATE DATABASE  user0 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

2、 创建表结构

         user0user2创建同样的表结构,t_usert_user_class_rel的建表语句参考如下:

DROP   TABLE   IF   EXISTS  `t_user_ext`;
CREATE   TABLE  `t_user_ext` (
 `
user_id int ( 11 NOT   NULL  COMMENT  ' 用户ID ' ,
 `receive_address` 
varchar ( 256 ) COLLATE utf8_unicode_ci  DEFAULT   NULL  COMMENT  ' 收货地址 ' ,
 `create_time` 
datetime   NOT   NULL ,
 `province_code` 
varchar ( 10 ) COLLATE utf8_unicode_ci  DEFAULT   NULL ,
 
PRIMARY   KEY  (` user_id `)
) ENGINE
= InnoDB  DEFAULT  CHARSET = utf8 COLLATE = utf8_unicode_ci COMMENT = ' 用户信息表 ' ;

DROP   TABLE   IF   EXISTS  `t_user_class_rel`;
CREATE   TABLE  `t_user_class_rel` (
 `id` 
int ( 11 NOT   NULL  AUTO_INCREMENT COMMENT  ' id ' ,
 `caller` 
varchar ( 16 CHARACTER   SET  utf8  NOT   NULL  COMMENT  ' 调用方系统表示 ' ,
 `province_code` 
varchar ( 10 CHARACTER   SET  utf8  DEFAULT   NULL  COMMENT  ' 省份编码 ' ,
 `
user_id int ( 11 NOT   NULL  COMMENT  ' 用户ID ' ,
 `class_id` 
int ( 11 NOT   NULL  COMMENT  ' 班级ID ' ,
 `role_type` 
int ( 11 DEFAULT   NULL  COMMENT  ' 用户在该班的角色(1学生2家长3教师) ' ,
 `create_time` 
datetime   NOT   NULL  COMMENT  ' 创建时间 ' ,
 `modify_time` 
datetime   DEFAULT   NULL  COMMENT  ' 修改时间 ' ,
 
PRIMARY   KEY  (`id`),
 
UNIQUE   KEY  `idx_rel_user_class_id` (` user_id `,`class_id`,`role_type`),
 
KEY  `idx_rel_user_id` (` user_id `) USING BTREE,
 
KEY  `idx_rel_class_id` (`class_id`)
) ENGINE
= InnoDB  DEFAULT  CHARSET = utf8 COLLATE = utf8_unicode_ci;

3、添加schema:加了一点内容:不分表的情况测试(只对部分表进行切分。其实这种时候,没有切分的表,应该是不需要跟已经切分过的表进行关联,否则就会垮库join。既然是这样,那业务就比较独立了,为什么不把这部分表垂直切分出去呢?) 总结心得:1、如果某张表进行水平切分了,那么跟他有事物关联的表,要么搞全局表,要么进行er分片,不然就会导致垮库join。而没有关联关系的表或者非事物关联的表,实际上可以垂直切分出去(如果有必要)。2、 dataHost可以理解成一个主机组,可以是单机,可以是主从,可以是 galera  等搭建起来的集群。读写分离就是在这里处理的。ha、读写分离等都在这里进行配置,都是针对datahost。
  < schema  name ="test_sharding"  checkSQLschema ="false"  sqlMaxLimit ="100" >
        <!--  auto sharding by id (long)  -->
       
< table  name ="t_user"  dataNode ="user0,user1,user2,user3"  rule =" rule_wyh " >
           
< childTable  name ="t_user_class_rel"  primaryKey ="id"  joinKey ="user_id"  parentKey ="user_id"   />
       
</ table >
            <!--   此处测试不分表的情况。要先在这里配置,然后可以在mycat创建t_user_1表,也可以在user3对应的local创建表。如果这里没事先配置,无法在mycat建表,会报错。这个还可以通过制定默认datanode实现,更简单,配置方法:在shcema标签上加上datanode   -->
            < table  name ="t_user_1"  dataNode ="user3"   >
       
</ table >
 </ schema >
  < dataNode  name ="user0"  dataHost =" host0 "  database ="user0"   />
 < dataNode  name ="user1"  dataHost =" host1 "  database ="user1"   />
 
< dataNode  name ="user2"  dataHost =" host2 "  database ="user2"   />
 < dataNode  name ="user3"  dataHost =" host3 "  database ="user3"   />
4、添加datahost:host3
<dataHost name="host3" maxCon="1000" minCon="10" balance="0"
   writeType="0" dbType="mysql" dbDriver="native">
   <heartbeat>select user()</heartbeat>
   <!-- can have multi write hosts -->
   <writeHost host="ys-fs" url="192.168.168.238:3306" user="root" password="youngsun" />
</dataHost>
在238上授权授权:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'youngsun';
flush privileges;

5、 配置 rule.xml 文件

schema.xml的文件内容中可看到t_user表指定的分片规则是rule1,需要在conf/rule.xml文件中设置rule1的规则为根据user_id进行分片,并按照类“org.opencloudb.route.function.PartitionByLong”的规则进行分片,即将user_id模除1024后每256内分到一个数据库中,即模除后0255user0数据库库,256511user1数据库,512767user2数据库,7681023user3数据库。

总结心得:普通取模算法,连续的id会路由到不同的分片。大了批量插入的事务控制难度,而固定分片hash算法根据二进制则可能会分到连续的分片,减少插入事务事务控制难度。

         该文件的参考内容如下所示:

<? xml version="1.0" encoding="UTF-8" ?>
<! DOCTYPE mycat:rule SYSTEM "rule.dtd" >
< mycat:rule  xmlns:mycat ="http://org.opencloudb/" >  
 
< tableRule  name ="rule_wyh" >
    
< rule >
      
< columns > user_id </ columns >
      
< algorithm > func_4p </ algorithm >
    
</ rule >
 
</ tableRule >

 
< function  name =" func_4p "  class ="org.opencloudb.route.function.PartitionByLong" >
    
< property  name ="partitionCount" > 4 </ property >
    
< property  name ="partitionLength" > 256 </ property >
 
</ function >
</ mycat:rule >

6、 配置 server.xml 文件

         server.xml文件中的schemas属性中添加test_shardingschema。修改后的文件如下所示:

<! DOCTYPE mycat:server SYSTEM "server.dtd" >
< mycat:server  xmlns:mycat ="http://org.opencloudb/" >
    
< system >
        
< property  name ="sequnceHandlerType" > 0 </ property >  
    
</ system >
    
< user  name ="test" >
       
< property  name ="password" > test </ property >
       
< property  name ="schemas" > weixin,yixin,photo, test_sharding </ property >
    
</ user >
</ mycat:server >

7、 水平切分测试

         重启MyCAT,使用MySQL客户端连接后,连接后可在test_sharding数据库下看到t_usert_user_class_rel表,

         MySQL客户端连接的MyCattest_sharding数据库的t_user表运行如下插入语句,插入user_id=1、255、256、511、512、1023、1024、50、300、1000的数据:注意insert into 必须带上字段名列表,不然报错插不进去。

INSERT INTO  t_user( user_id  , receive_address  , create_time  , province_code  ) VALUES('1', '广州市越秀区广州大道中599号', '2014-07-17 10:53:15', 'GD');
INSERT INTO  t_user( user_id  , receive_address  , create_time  , province_code  ) VALUES('255', '广州市越秀区广州大道中599号', '2014-07-17 10:53:15', 'GD');
INSERT INTO  t_user( user_id  , receive_address  , create_time  , province_code  ) VALUES('256', '广州市越秀区广州大道中599号', '2014-07-17 10:53:15', 'GD');
INSERT INTO  t_user( user_id  , receive_address  , create_time  , province_code  ) VALUES('511', '广州市越秀区广州大道中599号', '2014-07-17 10:53:15', 'GD');
INSERT INTO  t_user( user_id  , receive_address  , create_time  , province_code  ) VALUES('512', '广州市越秀区广州大道中599号', '2014-07-17 10:53:15', 'GD');
INSERT INTO  t_user( user_id  , receive_address  , create_time  , province_code  ) VALUES('1023', '广州市越秀区广州大道中599号', '2014-07-17 10:53:15', 'GD');
INSERT INTO  t_user( user_id  , receive_address  , create_time  , province_code  ) VALUES('1024', '广州市越秀区广州大道中599号', '2014-07-17 10:53:15', 'GD');
INSERT INTO  t_user( user_id  , receive_address  , create_time  , province_code  ) VALUES('50', '广州市越秀区广州大道中599号', '2014-07-17 10:53:15', 'GD');
INSERT INTO  t_user( user_id  , receive_address  , create_time  , province_code  ) VALUES('300', '广州市越秀区广州大道中599号', '2014-07-17 10:53:15', 'GD');
INSERT INTO  t_user( user_id  , receive_address  , create_time  , province_code  ) VALUES('1000', '广州市越秀区广州大道中599号', '2014-07-17 10:53:15', 'GD');

       而后在MyCATtest_sharding数据库的t_user表运行select查看记录执行情况。进入localhostuser0user3数据库,查看数据是否按照之前确定的rule1的规则写入不同的数据库。

         读者可在test_sharding数据库的t_user表执行updatedelete等语句,并去分库查看执行结果,可得知MyCATMySQL客户端基本透明,对程序也几乎透明,在select语句运行时,MyCAT会自行去各个分库按照规则获取合并结果。

         接着测试按照ER关系策略分片的t_user_class_rel表是否按照user_id的分片策略,同样user_id的数据分布在同一个user库的t_user表和t_user_class_rel表。

  在MyCATtest_mycat数据库的t_user_class_rel表运行如下语句:

INSERT INTO `t_user_class_rel`( `id`  , `caller` , `province_code` , `user_id` , `class_id` , `role_type` , `create_time` , `modify_time`) VALUES ('257', 'eip', 'GD', '2', '35', '3', '2012-08-05 17:32:13', '2013-12-27 16:07:32');
INSERT INTO `t_user_class_rel`( `id`  , `caller` , `province_code` , `user_id` , `class_id` , `role_type` , `create_time` , `modify_time`) VALUES ('1', 'eip', 'GD', '257', '35', '3', '2012-08-05 17:32:13', '2013-12-27 16:07:32');
INSERT INTO `t_user_class_rel`( `id`  , `caller` , `province_code` , `user_id` , `class_id` , `role_type` , `create_time` , `modify_time`) VALUES ('2', 'eip', 'GD', '513', '35', '3', '2012-08-05 17:32:13', '2013-12-27 16:07:32');
INSERT INTO `t_user_class_rel`( `id`  , `caller` , `province_code` , `user_id` , `class_id` , `role_type` , `create_time` , `modify_time`) VALUES ('3', 'eip', 'GD', '769', '35', '3', '2012-08-05 17:32:13', '2013-12-27 16:07:32');

而后在MyCATtest_mycat数据库的t_user_class_rel表运行select查看记录执行情况。进入localhostuser0user3数据库,查看数据是否按照之前确定的rule1的规则和ER分片策略写入不同的数据库。

分片join解决方案心得小结:如果一张表做分片了,其他有一张表要跟这张表做关联,方案如下:

1、全局表(适合做的才做):非跨分片join

2、另一张表也搞分片:非跨分片join

3、share join(只能2个表join):跨分片join

4、另一张表里join用到的字段冗余到 已经做了分片的那张表上去:不用join    (该方案可用性不错)

5、另一张表里join用到的字段 搞成一张全局表:非跨分片join

三、读写分离

MyCAT的读写分离机制如下:

  • 事务内的SQL,全部走写节点,除非某个select语句以注释/*balance*/开头
  • 自动提交select语句会走读节点,并在所有可用读节点中间随机负载均衡
  • 当某个主节点宕机,则其全部读节点都不再被使用,因为此时,同步失败,数据已经不是最新的,MyCAT会采用另外一个主节点所对应的全部读节点来实现select负载均衡。
  • 当所有主节点都失败,则为了系统高可用性,自动提交的所有select语句仍将提交到全部存活的读节点上执行,此时系统的很多页面还是能出来数据,只是用户修改或提交会失败。
231和233主从配置,233配置成读库。

<dataHost name="host1" maxCon="1000" minCon="10" balance="1"
   writeType="0" dbType="mysql" dbDriver="native">
   <heartbeat>select user()</heartbeat>
   <!-- can have multi write hosts -->
   <writeHost host="hadoop1" url="192.168.168.231:3306" user="root" password="youngsun" >
        <readHost host="hadoop3" url="192.168.168.233:3306" user="root" password="youngsun" weight="1" />
   </writeHost>
</dataHost>
阅读(3076) | 评论(0)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值