分库/分表
将存放在一台数据库服务器中的数据按照特定方式进行拆分,分散到多台数据库服务器中,分散单台服务器的负载效果
- 水平(横向)切分
按照表中指定字段的分片规则,将表记录按行切分,分散存储到多个数据库中 - 垂直(纵向)分割
将单个数据库的多个表按业务类型分类,分散存储到不同数据库
Mycat中间件
基于java的分布式数据库系统,为高并发环境的分布式存储提供解决方案
- 适合大量写入数据的存储需求
- 支持mysql,Oracle,sqlserver,monggodb等
- 支持数据读写分离服务
- 提供数据分片服务
- 基于阿里巴巴Cobar研发的开源软件
支持10种分片规则
- 1枚举法 sharding-by-intfile
- 2固定分片 rule1
- 3范围约定法 auto-sharding-long
- 4,求模法 mod-long
- 5日期列分区法 sharding-by-date
- 6通配取模 sharding-by-pattern
- 7ASCII码求模通配 sharding-by-prefixpattern
- 8编程指定 sharding -by-subsring
- 9字符串拆分hash解析 sharding-by-stringhash
- 10 一致hash sharding-bymurmur
工作过程
- 当mycat收到一个SQL命令时
1.解析SQl命令涉及到的表
2.然后查看对应表的配置,如有分片规则,则获取SQL命令里分片字段的值,并匹配[分片函数,获取分片列表
3.然后将SQL命令发往对应的分片服务器去执行
4.最后收集处理所有分片结果数据,并返回客户端 - 拓扑图
构建mycat服务器
yum -y install java-openjdk //安装java包
tar -zxvf Mycat-server-1.6-RELEASE //免安装版
mv myact/ /usr/local/
ls /usr/local/mycat/ //查看mycat文件架构
bin catlet conf lib los version.txt
******************************************************
- bin :mycat命令
- catlet :扩展功能
- conf : 配置文件
- lib :mycat使用的jar包
- logs : 启动日志和运行日志
- wrapper.log :服务启动日志
- mycat.log :SQl脚本执行后报错内容
重要配置文件说明
- server.xml //连接账号及逻辑库
- schema.xml //设置数据分片
- rule.xml //分片规则
- 其他文件 //函数调用文件
***********************************************
创建连接用户
vim /usr/local/mycat/conf/server.xml
<user name="root"> //连接mycat服务时使用的用户名
<property name="password">123456</property> //用户连接mycat用户时使用的密码
<property name="schemas">TESTDB</property> //逻辑库名
</user>
<user name="user">
<property name="password">user</property>
<property name="schemas">TESTDB</property>
<property name="readOnly">true</property>
//只读权限,连接mycat服务后只有读记录的权限,不写这一行则是可读可写
</user>
配置连接数据库
vim /usr/local/mycat/conf/schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">//对TESTDB库下的表做分片存储
<!-- auto sharding by id (long) -->
<table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" /> //对travelrecord表做分片存储
<!-- global table is auto cloned to all defined data nodes ,so can join
with any table whose sharding node is in the same data node -->
<table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
//对company表做分片存储,global全局表,数据不分片存储
<table name="goods" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
<!-- random sharding using mod sharind rule -->
<table name="hotnews" dataNode="dn1,dn2,dn3"
rule="mod-long" />
<table name="employee" primaryKey="ID" dataNode="dn1,dn2,dn3"
rule="sharding-by-intfile" />
<table name="customer" primaryKey="ID" dataNode="dn1,dn2,dn3"
rule="sharding-by-intfile">
<childTable name="orders" primaryKey="ID" joinKey="customer_id"
parentKey="id">
<childTable name="order_items" joinKey="order_id"
parentKey="id" />
</childTable>
<childTable name="customer_addr" primaryKey="ID" joinKey="customer_id"
parentKey="id" />
</table>
<!-- <table name="oc_call" primaryKey="ID" dataNode="dn1$0-743" rule="latest-month-calldate"
/> -->
</schema>
//定义数据库主机名及存储数据的库
<dataNode name="dn1" dataHost="localhost53" database="db1" />
<dataNode name="dn2" dataHost="localhost54" database="db2" />
<dataNode name="dn3" dataHost="localhost55" database="db3" />
//定义localhost53主机名对应的数据库服务器ip地址
<dataHost name="localhost53" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM53" url="192.168.4.53:3306" user="adminplj"
password="123qqq...A">
</writeHost>
</dataHost>
//定义localhost54主机名对应的数据库服务器ip地址
<dataHost name="localhost54" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM54" url="192.168.4.54:3306" user="adminplj"
password="123qqq...A">
</writeHost>
</dataHost>
//定义localhost54主机名对应的数据库服务器ip地址
<dataHost name="localhost55" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM55" url="192.168.4.55:3306" user="adminplj"
password="123qqq...A">
</writeHost>
</dataHost>
:wq
配置数据库服务器,根据分片文件设置创建对应的数据库
mysql> create database db1; //在数据库53上,创建db1库
mysql> create database db2; //在数据库54上,创建db2库
mysql> create database db3; //在数据库55上,创建db3库
在三台数据库服务器上创建授权用户
mysql> grant all on *.* to adminplj@"%" identified by "123qqq...A" ;
***********************************
测试授权用户在mycat服务器上
mysql -h192.168.4.53 -uadminplj -p123qqq...A
mysql -h192.168.4.54 -uadminplj -p123qqq...A
mysql -h192.168.4.55 -uadminplj -p123qqq...A
/usr/local/mycat/bin/mycat start //开启mycat服务
netstat -nputl | grep :8066 //查看服务端口
******************************************
客户端访问,连接分片服务器
mysql -hmycat主机的ip -P端口号 -u用户 -p密码
mysql -h192.168.4.56 -P8066 -uroot –p123456
show databases;
use TESTDB;
show tables;
###########################################
使用sharding-by-initfile枚举分片规则
vim /usr/local/mycat/conf/shcema.xml
<table name="employee" primaryKey="ID" dataNode="dn1,dn2,dn3"
rule="sharding-by-intfile" /> //employee表使用的规则
>>sharding-by-inifile分片规则使用的函数
vim /usr/local/mycat/conf/rule.xml
<tableRule name="sharding-by-intfile">
<rule>
<columns>sharding_id</columns> //数据分片字段名
<algorithm>hash-int</algorithm> //使用的函数名
</rule>
</tableRule>
<function name="hash-int"
class="io.mycat.route.function.PartitionByFileMap">
<property name="mapFile">partition-hash-int.txt</property> //函数调用的配置文件
</function>
>>>修改函数配置文件
vim /usr/local/mycat/conf/partition-hash-int.txt
10000=0 //当sharding_id字段的值是10000时,数据存储在数据节点dn1里
10010=1 //当sharding_id字段的值是10010时,数据存储在数据节点dn2里
10020=2 //当sharding_id字段的值是10020时,数据存储在数据节点dn3里
重启服务
/usr/local/mycat/bin/mycat stop
/usr/local/mycat/bin/mycat start
**********************************************************
客户端连接分片服务器,存取数据,验证规则
mysql -h192.168.4.56 -P8066 -uroot -p123456 //访问服务
.........................
##############################
mod-long分片规则的使用
vim /usr/local/mycat/conf/schema.xml
<table name="hotnews" dataNode="dn1,dn2,dn3" rule="mod-long" />
//注意要删除 primaryKey="ID" autoIncrement="true" 不然无法存储数据
查看规则文件
vim /usr/local/mycat/conf/rule.xml
<tableRule name="mod-long">
<rule>
<columns>id</columns> //数据分片字段
<algorithm>mod-long</algorithm> //函数名
</rule>
</tableRule>
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<!-- how many data nodes -->
<property name="count">3</property> //指定求模数字
</function>
重启服务
/usr/local/mycat/bin/mycat stop
/usr/local/mycat/bin/mycat start
客户端连接分片服务器,存取数据,验证规则
mysql -h192.168.4.56 -P8066 -uroot -p123456 //访问服务
create table hotnews(id int ,title char(30),comment char(200)); //建表
insert into hotnews(id,title,comment)values(9,"sc","xxxxx");
//插入第1条表记录,9和3取余 余0 记录存储在53服务器的db1库里
insert into hotnews(id,title,comment)values(10,"xx","haha");
//插入第2条表记录,10和3取余 余1 记录存储在54服务器的db2库里
insert into hotnews(id,title,comment)values(11,"yy","zz");
//插入第3条表记录,11和3取余 余2 记录存储在55服务器的db3库里
........................
配置新库新表
具体要求如下:
- 逻辑库名BBSDB
- 逻辑表名company2数据不分片,把数据存储到3台数据库服务器上
- 逻辑表名employee2 使用枚举法分片规则把数据存储到3台数据库服务器上
添加新库
[root@mycat56 ~]# vim /usr/local/mycat/conf/server.xml
<user name="root">
……
<property name="schemas">TESTDB,BBSDB</property>//指定逻辑库名
</user>
添加新表
vim /usr/local/mycat/conf/schema.xml
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="BBSDB" checkSQLschema="false" sqlMaxLimit="100">
<table name="company2" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" /> //指定逻辑表名company2
<table name="employee2" primaryKey="ID" dataNode="dn1,dn2,dn3"
rule="sharding-by-intfile" /> //指定逻辑表名employee2
</schema>
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
……
……
</mycat:schema >
重启服务mycat
/usr/local/mycat/bin/mycat stop
/usr/local/mycat/bin/mycat start
客户端连接mycat服务器测试配置
mysql -h192.168.4.56 -P8066 -uroot -p123456 //连接mycat服务器
show databases; //显示已有的数据库
use BBSDB; //切换到BBSDB库
show tables; //查看表