MySQL:
分库分表
前面为基本概念
中间为参考的操作实例
后面为10种分片规则介绍
定义:将存放在数据库(主机)中的数据,按照特定方式进行拆分,分散存放到多个数据库(主机)中,以达到分散单台设备负载的效果
分割的类型
垂直分割也叫纵向切分:将单个表,拆分多个表,分散到不同的数据库(比如,将某几个字段分到一台或多台主机上,另外的字段分到另外的主机) 将单个数据库的多个表进行分类,按业务类别分散到不同的数据库上
水平分割也叫横向切分:按照表中某个字段的某种规则,把表中的许多记录按行切分,分散到多个数据库中(字段不变,横向切开,每一段分到一个主机)
纵向切分可以分表也可以分库
横向切分只能分表
mycat
软件介绍
基于java的分布式数据库系统中间层,为高并发环境的分布式访问提供解决方案(分库分表,把原本只是一台承担的访问量分到多台来承担,就是有效减轻压力的原因所在)
支持MySQL,Oracle,Sqlserver,Mongodb等
提供数据读写分离服务
可实现数据库服务器的高可用
可以提供数据分片服务
适合数据大量写入数据的存储需求
mysql支持提供的10种分片规则
1 枚举法 sharding-by-intfile
2 固定分片 rule1
3 范围约定 auto-sharing-long
4 求模法 mod-long
5 日期列区分法 sharding-by-date
6 通配取模法 sharding-by-pattern
7 ASCII码求模通配 sharding-by-prefixpattern
8 编程指定 sharding-by-substring
9 字符串拆分hash解析 sharding-by-stringhash
10 一致性hash sharding-by-murmur
工作过程
当Mycat收到一个SQL时
会先解析这个SQL查找涉及到的表,然后看此表的定义
如果有分片规则,则获取到SQL里分片字段的值,并匹配分片函数,得到该SQL对应的分片列表
然后SQL发往这些分片去执行,最后收集和处理所有分片返回的结果数据,并输出到客户端
框架结构
客户端访问mycat 再分发到下面的数据库
配置mycat
Rpm -qa | grep -i jdk 检查是否安装jdk,若没有安装则安装jdk
安装mycat
Tar -zxf Mycat-server 解压包,是免安装的,解压即可以用
Mv mycat/ /usr/local/ 移动解压包(到默认路径)
Ls /usr/local/mycat/ 检查是否移动成功
修改配置文件
Mycat目录结构说明
Bin mycat命令 比如:启动 停止等等
Catlet 扩展功能
Conf 配置文件
Lib mycat使用的jar包 mycat是java开发的
Log mycat启动日志和运行日志
Wrapper.log mycat服务的启动日志,启动有问题可以看这个日志内容
Mycat.log 记录sql脚本执行后的具体报错内容
重要配置文件说明
Server.xml 设置连接mycat服务的账号、密码等
Schema.xml 配置mycat使用的真实数据库和表
Rule.xml 定义mycat分片规则
配置标签说明
……
定义连接mycat服务时使用的用户和密码及逻辑库的名字
……
指定数据节点(物理库的主机名和存储分片数据的数据库名)
……
指定数据库服务器的ip地址及连接数据库时使用的授权用户名及密码
修改配置文件/usr/local/mycat/conf/server.xml
test
TESTDB
user
TESTDB
true
代码解释
1 连接mycat服务时使用的用户名 test
2 使用test用户连接mycat时使用的密码
3 连接上mycat服务后,可以看见的库名多个时,使用逗号分隔(是逻辑上的库名)
8 定义只读权限,使用定义的user用户连接mycat服务后只有读记录的权限
修改配置文件/usr/local/mycat/conf/schema.xml 定义分片信息
代码解释
1 TEST逻辑库名 要与server.xml定义的一样
2,3,4,5,6,7 定义分片的表
修改配置文件/usr/local/mycat/conf/schema.xml 定义分片信息
range start-end ,data node index
K=1000,M=10000.
0-500M=0
500M-1000M=1
1000M-1500M=2
或
0-10000000=0
10000001-20000000=1
配置说明:
上面columns 标识将要分片的表字段,algorithm 分片函数,
rang-long 函数中mapFile代表配置文件路径
所有的节点配置都是从0开始,及0代表节点1,此配置非常简单,即预先制定可能的id范围到某个分片
四、求模法
user_id
mod-long
3
配置说明:
上面columns 标识将要分片的表字段,algorithm 分片函数,
此种配置非常明确即根据id与count(你的结点数)进行求模预算,相比方式1,此种在批量插入时需要切换数据源,id不连续
五、日期列分区法
create_time
sharding-by-date
yyyy-MM-dd
2014-01-01
10
配置说明:
上面columns 标识将要分片的表字段,algorithm 分片函数,
配置中配置了开始日期,分区天数,即默认从开始日期算起,分隔10天一个分区
还有一切特性请看源码
Assert.assertEquals(true, 0 == partition.calculate(“2014-01-01”));
Assert.assertEquals(true, 0 == partition.calculate(“2014-01-10”));
Assert.assertEquals(true, 1 == partition.calculate(“2014-01-11”));
Assert.assertEquals(true, 12 == partition.calculate(“2014-05-01”));
六、通配取模
user_id
sharding-by-pattern
256
2
partition-pattern.txt
partition-pattern.txt
id partition range start-end ,data node index
first host configuration
1-32=0
33-64=1
65-96=2
97-128=3
## second host configuration
129-160=4
161-192=5
193-224=6
225-256=7
0-0=7
配置说明:
上面columns 标识将要分片的表字段,algorithm 分片函数,patternValue 即求模基数,defaoultNode 默认节点,如果不配置了默认,则默认是0即第一个结点
mapFile 配置文件路径
配置文件中,1-32 即代表id%256后分布的范围,如果在1-32则在分区1,其他类推,如果id非数字数据,则会分配在defaoultNode 默认节点
String idVal = “0”;
Assert.assertEquals(true, 7 == autoPartition.calculate(idVal));
idVal = “45a”;
Assert.assertEquals(true, 2 == autoPartition.calculate(idVal));
七、ASCII码求模通配
user_id
sharding-by-prefixpattern
256
5
partition-pattern.txt
partition-pattern.txt
range start-end ,data node index
ASCII
48-57=0-9
64、65-90=@、A-Z
97-122=a-z
first host configuration
1-4=0
5-8=1
9-12=2
13-16=3
second host configuration
17-20=4
21-24=5
25-28=6
29-32=7
0-0=7
配置说明:
上面columns 标识将要分片的表字段,algorithm 分片函数,patternValue 即求模基数,prefixLength ASCII 截取的位数
mapFile 配置文件路径
配置文件中,1-32 即代表id%256后分布的范围,如果在1-32则在分区1,其他类推
此种方式类似方式6只不过采取的是将列种获取前prefixLength位列所有ASCII码的和进行求模sum%patternValue ,获取的值,在通配范围内的
即 分片数,
/**
* ASCII编码:
* 48-57=0-9阿拉伯数字
* 64、65-90=@、A-Z
* 97-122=a-z
*
*/
如
String idVal=”gf89f9a”;
Assert.assertEquals(true, 0==autoPartition.calculate(idVal));
idVal=”8df99a”;
Assert.assertEquals(true, 4==autoPartition.calculate(idVal));
idVal=”8dhdf99a”;
Assert.assertEquals(true, 3==autoPartition.calculate(idVal));
八、编程指定
user_id
sharding-by-substring
0
2
8
0
配置说明:
上面columns 标识将要分片的表字段,algorithm 分片函数
此方法为直接根据字符子串(必须是数字)计算分区号(由应用传递参数,显式指定分区号)。
例如id=05-100000002
在此配置中代表根据id中从startIndex=0,开始,截取siz=2位数字即05,05就是获取的分区,如果没传默认分配到defaultPartition
九、字符串拆分hash解析
user_id
sharding-by-stringhash
512
2
0:2
配置说明:
上面columns 标识将要分片的表字段,algorithm 分片函数
函数中length代表字符串hash求模基数,count分区数,hashSlice hash预算位
即根据子字符串 hash运算
hashSlice : 0 means str.length(), -1 means str.length()-1
/**
* “2” -> (0,2)
* “1:2” -> (1,2)
* “1:” -> (1,0)
* “-1:” -> (-1,0)
* “:-1” -> (0,-1)
* “:” -> (0,0)
*/
public class PartitionByStringTest {
@Test
public void test() {
PartitionByString rule = new PartitionByString();
String idVal=null;
rule.setPartitionLength(“512”);
rule.setPartitionCount(“2”);
rule.init();
rule.setHashSlice(“0:2”);
// idVal = “0”;
// Assert.assertEquals(true, 0 == rule.calculate(idVal));
// idVal = “45a”;
// Assert.assertEquals(true, 1 == rule.calculate(idVal));
//last 4
rule = new PartitionByString();
rule.setPartitionLength("512");
rule.setPartitionCount("2");
rule.init();
//last 4 characters
rule.setHashSlice("-4:0");
idVal = "aaaabbb0000";
Assert.assertEquals(true, 0 == rule.calculate(idVal));
idVal = "aaaabbb2359";
Assert.assertEquals(true, 0 == rule.calculate(idVal));
}
十、一致性hash
user_id
murmur
0
2