来源:https://segmentfault.com/a/1190000009495748
参考文档:Mycat安装与使用
环境
环境 | 版本 |
---|---|
windows | 10 |
java | 1.8.0 |
mysql | 5.7.17 |
navicat for mysql | 10 |
安装
PS:MyCAT使用Java开发,用到了JDK 7的部分功能,所以在使用前请确保安装了JDK 7.0,并设置了正确的Java环境变量(可在命令行窗口输入:“java –version”获知是否安装成功,以及获取JDK的版本)。
下载1.6版本
F盘新建mycat-server文件夹,解压Mycat-server-1.6-RELEASE-20161028204710-win.tar.gz,得到mycat文件夹
水平切分
定义
将数据水平分布到不同的DB或table中,在通过相应的DB路由][1] 或者table路由规则找到需要查询的具体的DB或者table以进行Query操作,比如根据用户ID将用户表切分到多台数据库上。
将某个访问极其频繁的表再按照某个字段的某种规则来分散到多个表之中,每个表中包含一部分数据。
例如,所有数据都是和用户关联的,那么我们就可以根据用户来进行水平拆分,将不同用户的数据切分到不同的数据库中。
现在互联网非常火爆的web 2.0类型的网站,基本上大部分数据都能够通过会员用户信息关联上,可能很多核心表都非常适合通过会员ID来进行数据的水平切分。而像论坛社区讨论系统,就更容易切分了,非常容易按照论坛编号来进行数据的水平切分。切分之后基本上不会出现各个库之间的交互。
优缺点
优点:
表关联基本能够在数据库端全部完成;
不会存在某些超大型数据量和高负载的表遇到瓶颈的问题;
应用程序端整体架构改动相对较少;
事务处理相对简单;
只要切分规则能够定义好,基本上较难遇到扩展性限制。
缺点:
切分规则相对复杂,很难抽象出一个能够满足整个数据库的切分规则;
后期数据的维护难度有所增加,人为手工定位数据更困难;
应用系统各模块耦合度较高,可能会对后面数据的迁移拆分造成一定的困难。
实现
MyCAT使用MySQL的通讯协议模拟成一个MySQL服务器,并建立了完整的Schema(数据库)、Table (数据表)、User(用户)的逻辑模型。
schema 是实际逻辑库的配置,多个schema代表多个逻辑库。
DataNode是MyCAT的逻辑数据节点,映射到后端的某一个物理数据库的一个Database,为了做到系统高可用,每个DataNode可以配置多个引用地址(DataSource),当主DataSource被检测为不可用时,系统会自动切换到下一个可用的DataSource上,这里的DataSource即可认为是Mysql的主从服务器的地址。dataNode是逻辑库对应的分片,如果配置多个分片只需要多个dataNode即可。
dataHost是实际的物理库配置地址,可以配置多主主从等其他配置,多个dataHost代表分片对应的物理库地址,下面的writeHost、readHost代表该分片是否配置多写,主从,读写分离等高级特性。
建库,建表
这里主要是为了熟悉mycat,表字段很省略
CREATE DATABASE IF NOT EXISTS `weibo_simple`;
-- ------------------------------------
-- Table structure for `t_users` 用户表
-- ------------------------------------
DROP TABLE IF EXISTS `t_users`;
CREATE TABLE `t_users` (
`user_id` varchar(64) NOT NULL COMMENT '注册用户ID',
`user_email` varchar(64) NOT NULL COMMENT '注册用户邮箱',
`user_password` varchar(64) NOT NULL COMMENT '注册用户密码',
`user_nikename` varchar(64) NOT NULL COMMENT '注册用户昵称',
`user_creatime` datetime NOT NULL COMMENT '注册时间',
`user_status` tinyint(1) NOT NULL COMMENT '验证状态 1:已验证 0:未验证',
`user_deleteflag` tinyint(1) NOT NULL COMMENT '删除标记 1:已删除 0:未删除',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- -------------------------------------
-- Table structure for `t_message`微博表
-- -------------------------------------
DROP TABLE IF EXISTS `t_message`;
CREATE TABLE `t_message` (
`messages_id` varchar(64) NOT NULL COMMENT '微博ID',
`user_id` varchar(64) NOT NULL COMMENT '发表用户',
`messages_info` varchar(255) DEFAULT NULL COMMENT '微博内容',
`messages_time` datetime DEFAULT NULL COMMENT '发布时间',
`messages_commentnum` int(12) DEFAULT NULL COMMENT '评论次数',
`message_deleteflag` tinyint(1) NOT NULL COMMENT '删除标记 1:已删除 0:未删除',
`message_viewnum` int(12) DEFAULT NULL COMMENT '被浏览量',
PRIMARY KEY (`messages_id`),
KEY `user_id` (`user_id`),
CONSTRAINT `t_message_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `t_users` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/**
user 节点测试表
*/
DROP TABLE IF EXISTS `t_node`;
CREATE TABLE `t_node` (
`node_id` int(11) NOT NULL COMMENT 'ID',
`user_id` int(11) NOT NULL COMMENT '用户ID',
`node_note` varchar(256) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'note',
`node_createtime` datetime NOT NULL,
PRIMARY KEY (`vid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='note表';
配置server.xml文件
<!-- 开启实时统计 -->
<property name="useSqlStat">1</property> <!-- 1为开启实时统计、0为关闭 -->
<!-- 去掉注释 -->
<property name="maxStringLiteralLength">65535</property>
<property name="sequnceHandlerType">0</property>
<property name="backSocketNoDelay">1</property>
<property name="frontSocketNoDelay">1</property>
<!-- 添加user -->
<user name="mycat">
<property name="password">mycat</property>
<property name="schemas">mycat</property>
</user>
配置schema.xml文件
添加weibo_simple数据库的dataNode设置,并添加t_users和t_message表的schema设置,本次配置了双主,读写分离配置,同一个表多个分片的配置可以用dataNode="dn$1-100" 通配方式。
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- 与server.xml中user的schemas名一致 -->
<schema name="mycat" checkSQLschema="true" sqlMaxLimit="100">
<table name="t_users" primaryKey="user_id" dataNode="dn1,dn2" rule="rule1"/>
<table name="t_node" primaryKey="node_id" autoIncrement="true" dataNode="dn1,dn2" rule="rule1" />
<table name="t_message" type="global" primaryKey="messages_id" dataNode="dn1,dn2" />
</schema>
<dataNode name="dn1" dataHost="jdbchost" database="weibo_simple" />
<dataNode name="dn2" dataHost="jdbchost2" database="weibo_simple" />
<dataHost name="jdbchost" maxCon="500" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native">
<heartbeat>select 1</heartbeat>
<writeHost host="maste1" url="192.168.0.1:3306" user="root" password="root">
</writeHost>
<writeHost host="maste2" url="192.168.0.3:3306" user="root" password="root">
</writeHost>
</dataHost>
<dataHost name="jdbchost2" maxCon="500" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native">
<heartbeat>select 1</heartbeat>
<writeHost host="maste1" url="192.168.0.5:3306" user="root" password="root">
</writeHost>
<writeHost host="maste2" url="192.168.0.6:3306" user="root" password="root">
</writeHost>
</dataHost>
</mycat:schema>
配置rule.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://io.mycat/">
<tableRule name="rule1">
<rule>
<columns>user_id</columns>
<algorithm>func1</algorithm>
</rule>
</tableRule>
<function name="func1" class="io.mycat.route.function.PartitionByLong">
<property name="partitionCount">8</property>
<property name="partitionLength">128</property>
</function>
</mycat:rule>
为了更好地定位错误,修改log4j2.xml
<!-- 默认info改为debug -->
<asyncRoot level="debug" includeLocation="true">
水平切分测试
启动mycat数据库
命令行
F:\mycat-server\mycat\bin>startup_nowrap.bat
启动成功
打开navicat for mysql 建立mycat连接
在mycat数据库插入数据,数据同步到mysql实际数据库中
conf下配置文件说明
--server.xml:是Mycat服务器参数调整和用户授权的配置文件。
--schema.xml:是逻辑库定义和表以及分片定义的配置文件。
--rule.xml:是分片规则的配置文件,分片规则的具体一些参数信息单独存放为文件,也在这个目录下,配置文件修改需要重启MyCAT。
--log4j.xml:日志存放在logs/log中,每天一个文件,日志的配置是在conf/log4j.xml中,根据自己的需要可以调整输出级别为debug debug级别下,会输出更多的信息,方便排查问题。
--autopartition-long.txt,partition-hash-int.txt,sequence_conf.properties, sequence_db_conf.properties 分片相关的id分片规则配置文件
--lib MyCAT自身的jar包或依赖的jar包的存放目录。
--logs MyCAT日志的存放目录。日志存放在logs/log中,每天一个文件