MyCAT2分库分表

目录

​​​​​​一、分库分表的原理

1.垂直切分

 2.水平切分 

3.如何分表

1.选择要拆分的表

2.选择分表的定段

3.分库分表的环境准备

1.进入dw0配置

1)进入目录:

2)修改dw0.cnf:

3)修改dr0.cnf:

4)配置文件修改后,复制到容器里面:

5)重启MySQL(dw0,dr0):

6)进入dw0主机里面执行相关配置:

7)创建用户

8)给该用户授予权限:

9)刷新权限:

10)查看状态后面备用:

2.进入dr0配置

1)进入容器并登录:

2)执行主从配置:

3)启动主从(在dr0里面执行):

4)查询主从的状态(dr0):

5)成功的标志:

3.进入dw1配置

1)进入目录:

2)修改dw1.cnf

3)修改dr1.cnf

4)配置文件修改后,复制到容器里面:

5)重启MySQL(dw1,dr1):

6)进入dw1主机里面执行相关配置

7)创建用户:

8)给该用户授予权限:

9)刷新权限:

10)查看状态后面备用:

​​​​​​​4.进入dr1配置

1)进入容器并登录:

2)执行主从配置:

3)启动主从:(在dr1里面执行)

4)查询主从的状态(dr1)

5)成功的标志:

​​​​​​​5.使用Navicat连接测试

​​​​​​​6.配置MyCAT数据源

​​​​​​​7.配置MyCAT集群配置

​​​​​​​8.全局表(广播表)配置

​​​​​​​1.创建数据库

​​​​​​​2.创建表

​​​​​​​3.查看结果

4.添加数据查看结果

​​​​​​​5.查询数据查看结果

​​​​​​​9.分片表配置【重点】

​​​​​​​1.创建表

​​​​​​​2.查看MyCAT生成的配置

​​​​​​​3.添加数据

​​​​​​​4.查询后台物理库

​​​​​​​5.MyCAT中查询

​​​​​​​10.ER表配置

​​​​​​​1.创建表

​​​​​​​2.查看MyCAT生成的配置

​​​​​​​3.添加数据

​​​​​​​4.查询后台物理库

​​​​​​​5.MyCAT中关联查询

​​​​​​​6.疑问

11.分片算法简介

1.取模哈希分片 MOD_HASH

​​​​​​​2.范围哈希分片 RANGE_HASH

​​​​​​​3.字符串哈希分片 UNI_HASH

​​​​​​​4.日期哈希分片 YYYYDD

12.【掌握】MyCAT2全局ID的生成方式

1.为什么要全局ID

​​​​​​​2.雪花算法原理说明

​​​​​​​3.使用默认的雪花算法验证


​​​​​​一、分库分表的原理

一个数据库由很多表构造成,每个表对应不同的业务,垂直切分是指按业务将表进行分类,分布到不同的数据库上面,这样也就将数据或者说压力分担到不同的库上面。

1.垂直切分

基于表或字段划分,表结构不同。我们有单库的分表,也有多库的分表,如下图所示

注意:有紧密关联关系的表应该在一个库里,相互没有关联关系的表可以分到不同的库里面

换句话说:就是我们很多库合在一起组成一个完整的数据库系统(这个不同到集群哦)。

 2.水平切分 

基于数据划分,表结构相同数据不同,也有同库的水平切分和多库的切分。

当我们的客户表数量已经到达数千万甚至上亿的时候,单表的存储容量和查询效率都会出现问题,我们需要进一步对单张表的数据进行水平切分。水平切分的每个数据库的表结构都是一样的,只是存储的数据不一样,比如每个库存储 1000 万的数据。

客户表   20W数据

CREATE TABLE customer(

   ID INT AUTO_INCREMENT,

   NAME VARCHAR(30),

   PRIMARY KEY(ID)

)

订单表  600W数据

CREATE TABLE orders(

   ID BIGINT AUTO_INCREMENT,

   ORDER_TYPE INT,

   CUSTOMER_ID INT,

   AMOUNT DECIMAL(10,2),

   PRIMARY KEY(ID)

)

订单详情表  800W数据

CREATE TABLE orders_detail(

  ID BIGINT AUTO_INCREMENT,

  detail VARCHAR(2000),

  order_id BIGINT,

  PRIMARY KEY(ID)

)

字典表   100条数据

CREATE TABLE dict_order_type(

  ID INT AUTO_INCREMENT,

  order_type VARCHAR(200),

  PRIMARY KEY(ID )

)

3.如何分表

1.选择要拆分的表

MySQL单表存储数据条数是有瓶颈的,单表达到1000W条数据就达到了瓶颈,会严重影响查询效率,所以我们需要进行水平拆分进行优化。例如:我们订单表和详情表里面的数据达到600W行数据,需要进行优化,那么我们就要把订单表的数据进行拆分存储了。

2.选择分表的定段

编号

分表字段

效果

1

id(主键、或创建时间)

查询订单注重时效。历史订单被查询的次数少,如此分片会造成一个节点访问多,一个访问少,不平均

2

customer_id(客户id)

根据客户id去分,两个节点访问平均,一个客户所有的订单都在同一个节点,这样查询就快

3.分库分表的环境准备

我们可以按第6点的方式,搭建MySQL两组主从复制模型。

1.准备四个数据库

2.分别使用Docker启动

名称

ip

port

dw0

192.168.106.133

3312

dr0

192.168.106.133

3313

dw1

192.168.106.133

3314

dr1

192.168.106.133

3315

docker run --name dw0 -p 3312:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:8.0.28 --lower_case_table_names=1

docker run --name dr0 -p 3313:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:8.0.28 --lower_case_table_names=1

docker run --name dw1 -p 3314:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:8.0.28 --lower_case_table_names=1

docker run --name dr1 -p 3315:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:8.0.28 --lower_case_table_names=1

启动完成 docker ps 查看:

1.进入dw0配置

将容器里面的配置文件复制出来,主要修改服务器的配置。在root目录下创建一个mysqlms的目录存放从docker容器里面复制过来的配置文件。

1)进入目录:

cd /mysqlms

docker cp dw0:/etc/mysql/conf.d/docker.cnf dw0.cnf

docker cp dr0:/etc/mysql/conf.d/docker.cnf dr0.cnf

2)修改dw0.cnf:

server-id=1

log-bin=master.bin

3)修改dr0.cnf:

server-id=2

4)配置文件修改后,复制到容器里面:

docker cp dw0.cnf dw0:/etc/mysql/conf.d/docker.cnf

docker cp dr0.cnf dr0:/etc/mysql/conf.d/docker.cnf

5)重启MySQL(dw0,dr0):

docker restart dw0 dr0

6)进入dw0主机里面执行相关配置:

docker exec -it dw0 bash

mysql -uroot -p123456

7)创建用户

create user 'rep'@'%' identified by '123456';

8)给该用户授予权限:

grant replication slave on *.* to 'rep'@'%';

9)刷新权限:

flush privileges;

至此,dw0里面已经创建了一个用户:rep 123456 拥有所有库,所有表replication slave

10)查看状态后面备用:

show master status;

2.进入dr0配置
1)进入容器并登录:

docker exec -it dr0 bash

mysql -u root -p123456

2)执行主从配置:

change master to master_host="192.168.175.109",master_port=3312,master_user="rep",master_password="123456",master_log_file="master.000001",master_log_pos=854;

master_log_file:该文件具体叫什么名称,需要从主机里面去看看上面【查看状态

3)启动主从(在dr0里面执行):

start slave ;

4)查询主从的状态(dr0):

show slave status \G;

5)成功的标志:

​​​​​​​3.进入dw1配置

将容器里面的配置文件复制出来,主要修改服务器的配置。在root目录下创建一个mysqlms的目录存放从docker容器里面复制过来的配置文件。

1)进入目录:

cd /mysqlms

docker cp dw1:/etc/mysql/conf.d/docker.cnf dw1.cnf

docker cp dr1:/etc/mysql/conf.d/docker.cnf dr1.cnf

2)修改dw1.cnf

server-id=1

log-bin=master.bin

3)修改dr1.cnf

server-id=2

4)配置文件修改后,复制到容器里面:

docker cp dw1.cnf dw1:/etc/mysql/conf.d/docker.cnf

docker cp dr1.cnf dr1:/etc/mysql/conf.d/docker.cnf

5)重启MySQL(dw1,dr1):

docker restart dw1 dr1

6)进入dw1主机里面执行相关配置

docker exec -it dw1 bash

mysql -uroot -p123456

7)创建用户:

create user 'rep'@'%' identified by '123456';

8)给该用户授予权限:

grant replication slave on *.* to 'rep'@'%';

9)刷新权限:

flush privileges;

至此:dw1里面已经创建了一个用户:rep 123456 拥有所有库,所有表replication slave

10)查看状态后面备用:

show master status;

​​​​​​​4.进入dr1配置
1)进入容器并登录:

docker exec -it dr1 bash

mysql -u root -p123456

2)执行主从配置:

change master to master_host="192.168.175.109",master_port=3314,master_user="rep",master_password="123456",master_log_file="master.000001",master_log_pos=854,get_master_public_key=1;

master_log_file:该文件具体叫什么名称,需要从主机里面去看看上面【查看状态

3)启动主从:(在dr1里面执行)

start slave ;

4)查询主从的状态(dr1)

show slave status \G;

5)成功的标志:

​​​​​​​5.使用Navicat连接测试

​​​​​​​6.配置MyCAT数据源

通过上面的配置,我们准备了两组主从,分别为:

  1. dw0 dr0 
  2. dw1 dr1

接下来,我们要在MyCAT里面配置这四个数据源。

添加dw0数据源

/*+ mycat:createDataSource{

  "name":"dw0",

  "password":"123456",  "url":"jdbc:mysql://127.0.0.1:3312?useUnicode=true&serverTimezone=UTC&characterEncoding=UTF-8",

  "user":"root",} */;

添加dr0数据源

/*+ mycat:createDataSource{

  "name":"dr0",

  "password":"123456",  "url":"jdbc:mysql://127.0.0.1:3313?useUnicode=true&serverTimezone=UTC&characterEncoding=UTF-8",

  "user":"root",} */;

添加dw1数据源

/*+ mycat:createDataSource{

  "name":"dw1",

  "password":"123456",  "url":"jdbc:mysql://127.0.0.1:3314?useUnicode=true&serverTimezone=UTC&characterEncoding=UTF-8",

  "user":"root",} */;

添加dr1数据源

/*+ mycat:createDataSource{

  "name":"dr1",

  "password":"123456",  "url":"jdbc:mysql://127.0.0.1:3315?useUnicode=true&serverTimezone=UTC&characterEncoding=UTF-8",

  "user":"root",} */;

执行之后我们在MyCAT里面看到如下数据源的配置文件。

​​​​​​​7.配置MyCAT集群配置

注意:自动分片默认要求集群名字以c为前缀,数字为后缀:

  1. c0就是分片表第一个节点;
  2. c1就是第二个节点。

一般情况下我们使用默认的就可以了。

/*! mycat:createCluster{

  "name":"c0",

  "masters":[

    "dw0"

  ],

  "replicas":[

    "dr0"

  ]

} */;

/*! mycat:createCluster{

  "name":"c1",

  "masters":[

    "dw1"

  ],

  "replicas":[

    "dr1"

  ]

} */;

创建完成之后查看MyCAT配置文件里面内容如下:

{

         "clusterType":"MASTER_SLAVE",

         "heartbeat":{

                  "heartbeatTimeout":1000,

                  "maxRetryCount":3,

                  "minSwitchTimeInterval":300,

                  "showLog":false,

                  "slaveThreshold":0.0

         },

         "masters":[

                  "dw0"

         ],

         "maxCon":2000,

         "name":"c0",

         "readBalanceType":"BALANCE_ALL",

         "replicas":[

                  "dr0"

         ],

         "switchType":"SWITCH"

}

​​​​​​​8.全局表(广播表)配置

全局表:所有分片库中都有全量数据的表。分库分表的环境准备好之后,接下来我们在MyCAT里面执行相关的命令,就可以帮我们创建全局表。

​​​​​​​1.创建数据库

CREATE DATABASE db1 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

​​​​​​​2.创建表

use db1;

CREATE TABLE `sys_dict` (

  `id` bigint NOT NULL AUTO_INCREMENT,

  `dict_type` int  ,

  `dict_name` varchar(100) DEFAULT NULL,

  `dict_value` int ,

  PRIMARY KEY (`id`)

) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4 BROADCAST;

上面的SQL中有一个BROADCAST 这个就是全局表的标识。

​​​​​​​3.查看结果

MyCAT的配置文件中:

后端数据库中发现所有的表全部出现了。

4.添加数据查看结果

INSERT INTO sys_dict(dict_type,dict_name,dict_value) VALUES(1,"男",1);

INSERT INTO sys_dict(dict_type,dict_name,dict_value) VALUES(1,"女",0);

所有的库中都有的数据

​​​​​​​5.查询数据查看结果

select * from sys_dict

发现数据并没有重复。

​​​​​​​9.分片表配置【重点】

关键字:dbpartition、tbpartitition、tbpartitions、dbpartitions。以上的运行成功必须是c0、c1的数据源配置没有问题才行。

​​​​​​​1.创建表

CREATE TABLE orders(

   ID BIGINT NOT NULL AUTO_INCREMENT,

   ORDER_TYPE INT,

   CUSTOMER_ID INT,

   AMOUNT DECIMAL(10,2),

   PRIMARY KEY(ID)

) ENGINE=INNODB  DEFAULT CHARSET=utf8mb4

dbpartition BY mod_hash(CUSTOMER_ID) tbpartition By mod_hash(CUSTOMER_ID)

tbpartitions 1 dbpartitions 2

dbpartition BY mod_hash(CUSTOMER_ID): 指定数据库的分片算法及使用哪一条数据进行分片HASH

tbpartition BY mod_hash(CUSTOMER_ID) :指定表的分片算法及使用哪一条数据进行分片HASH

tbpartitions 1  表的分片数量

dbpartitions 2  数据库的分片数量

​​​​​​​2.查看MyCAT生成的配置

​​​​​​​3.添加数据

INSERT INTO ORDERS(ID,ORDER_TYPE,CUSTOMER_ID,AMOUNT) VALUES(1,101,100,100101);

INSERT INTO ORDERS(ID,ORDER_TYPE,CUSTOMER_ID,AMOUNT) VALUES(2,101,100,100101);

INSERT INTO ORDERS(ID,ORDER_TYPE,CUSTOMER_ID,AMOUNT) VALUES(3,101,100,100101);

INSERT INTO ORDERS(ID,ORDER_TYPE,CUSTOMER_ID,AMOUNT) VALUES(4,102,101,101102);

INSERT INTO ORDERS(ID,ORDER_TYPE,CUSTOMER_ID,AMOUNT) VALUES(5,102,101,101102);

INSERT INTO ORDERS(ID,ORDER_TYPE,CUSTOMER_ID,AMOUNT) VALUES(6,102,101,101102);

​​​​​​​4.查询后台物理库

从图中我们可以看到数据库生成了。打开数据库后,里面的表也生成了,里面的数据也分开了,并不在一个表里。

​​​​​​​5.MyCAT中查询

从上图中,我们发现查询的结果也帮我们合并了。

​​​​​​​10.ER表配置

说明:在1.6的版本中,我们ER表的配置有关系的数据必须存放在相同的库中,但是在2.0中不用了,MyCAT2自动帮我们优化了。上面我们创建了一张订单表,接下来我们创建一张订单详情表。

​​​​​​​1.创建表

CREATE TABLE orders_detail(

  ID BIGINT AUTO_INCREMENT,

  detail VARCHAR(2000),

  order_id BIGINT,

  PRIMARY KEY(ID)

) ENGINE=INNODB  DEFAULT CHARSET=utf8mb4

dbpartition BY mod_hash(order_id) tbpartition By mod_hash(order_id)

tbpartitions 1 dbpartitions 2

dbpartition BY mod_hash(order_id) :指定数据库的分片算法及使用哪一条数据进行分片HASH

tbpartition BY mod_hash(order_id) :指定表的分片算法及使用哪一条数据进行分片HASH

tbpartitions 1  表的分片数量

dbpartitions 2  数据库的分片数量

​​​​​​​2.查看MyCAT生成的配置

从上图中我们可以出已经放到分片表里面了。

​​​​​​​3.添加数据

INSERT INTO orders_detail VALUES(1,"详情1",1);

INSERT INTO orders_detail VALUES(2,"详情2",2);

INSERT INTO orders_detail VALUES(3,"详情3",3);

INSERT INTO orders_detail VALUES(4,"详情4",4);

INSERT INTO orders_detail VALUES(5,"详情5",5);

INSERT INTO orders_detail VALUES(6,"详情6",6);

​​​​​​​4.查询后台物理库

从上图可知,dw0里面只存了三条。

发现dw1里面也存放了三条。

​​​​​​​5.MyCAT中关联查询

select * from orders o inner join orders_detail od on(o.id=od.order_id)

​​​​​​​6.疑问

从物理库中我们看到一个库里面的详情数据和定义数据不配套,那是为什么呢?在1.6的版本里面是不允许的。

接下来我们说明下原因:

1)MyCAT2在涉及两个表的JOIN分片字段等价关系的时候可以完成JOIN的下推。

2)MyCAT2无需要指定ER表,是自动识别的。

3)查询配置的表是否具有ER关系 使用如下注释:

/*+ mycat:showErGroup{}*/

结果如下:

上面的group_id 表示相同的组,该组中的表具有相同的存储分布(在MyCAT2中它是这么规定的)。

11.分片算法简介

1.取模哈希分片 MOD_HASH

1)如果分片值是字符串则先对字符串进行Hash转换为数值类型

2)分库键和分表键是同键

3)分表下标=分片值%(分库数量*分表数量)

4)分库下标=分表下标/分表数量

5)分库键和分表键是不同键

6)分表下标= 分片值%分表数量

7)分库下标= 分片值%分库数量

create table travelrecord (

 ....

) ENGINE=InnoDB DEFAULT CHARSET=utf8

dbpartition by MOD_HASH (id) dbpartitions 6

tbpartition by MOD_HASH (id) tbpartitions 6;

​​​​​​​2.范围哈希分片 RANGE_HASH

1)RANGE_HASH(字段1, 字段2, 截取开始下标)

2)仅支持数值类型,字符串类型

3)当时字符串类型时候,第三个参数生效

4)计算时候优先选择第一个字段,找不到选择第二个字段

5)如果是字符串则根据下标截取其后部分字符串,然后该字符串hash成数值

6)根据数值按分片数取余

7)要求截取下标不能少于实际值的长度

8)两个字段的数值类型要求一致

create table travelrecord(

...

)ENGINE=InnoDB DEFAULT CHARSET=utf8

dbpartition by RANGE_HASH(id,user_id,3) dbpartitions 3

tbpartition by RANGE_HASH(id,user_id,3) tbpartitions 3;

​​​​​​​3.字符串哈希分片 UNI_HASH

1)如果分片值是字符串则先对字符串进行hash转换为数值类型

2)分库键和分表键是同键

3)分库下标=分片值%分库数量

4)分表下标=(分片值%分库数量)*分表数量+(分片值/分库数量)%分表数量

5)分库键和分表键是不同键

6)分表下标= 分片值%分表数量

7)分库下标=分片值%分库数量

create table travelrecord (

 ....

) ENGINE=InnoDB DEFAULT CHARSET=utf8

dbpartition by UNI_HASH (id) dbpartitions 6

tbpartition by UNI_HASH (id) tbpartitions 6;

​​​​​​​4.日期哈希分片 YYYYDD

1)仅用于分库

2)DD是一年之中的天数

3)(YYYY*366+DD)%分库数

create table travelrecord (

 ....

) ENGINE=InnoDB DEFAULT CHARSET=utf8

dbpartition by YYYYDD(xxx) dbpartitions 8

tbpartition by xxx(xxx) tbpartitions 12;

12.【掌握】MyCAT2全局ID的生成方式

1.为什么要全局ID

在复杂的分布式系统中,需要对大量的数据和消息进行唯一标识。如在阿里,淘宝,支付,等系统中,数据日渐增长,对数据分库分表后需要有一个唯一ID来标识一条数据或消息;还有如美团和饿了吗的骑手ID 商家ID  优惠券ID等,从以上可以得出,一个能够生成全局唯一ID的系统是非常必要的。

在MyCAT2中,自动默认使用雪花片法生成全局序列号。

如果不需要MyCAT默认全局序列,可以通过配置关闭自动加全局序列;建表语句方式关闭全局序列。

如果不需要使用MyCAT的自增序列,而使用MySQL本身的自增主键的功能。需要在配置中更改对应的建表SQL。不设置auto_increment关键字,这样 MyCAT就不认为这个表有自增主键的功能。就不会使用MyCAT全局序列号,这样,对应的插入SQL在MySQL中去处理,由MySQL的自增主键功能补全。

雪花算法:引入了时间戳的ID保持自增的分布式ID生成算法。

​​​​​​​2.雪花算法原理说明

Twitter开源分布式生成ID算法。

1)优点:基本解决了所有问题

2)缺点:每个节点时间可能不同,生成ID是整体趋势递增的

Snowflake的结构如下(每部分用-分开):

图中的信息如下:

1)第一位未使用,因为二进制中最高位是符号位同,1表示负数,0表示正数。ID不可能为负数。

2)时间戳:41位,最后为2的41次方,大概69.73年,10==2+8

3)然后是5位datacenterId和5位workerId(10位的长度最多支持部署1024个节点) 也可以是3位datacenterId和7位workerId

4)最后12位是毫秒内的计数(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号)每秒生成409.6万个【可怕】

一共加起来刚好64位,为一个Long型。(转换成字符串长度为18)

我们可以使用在线进制转换  进制转化工具测试。

优点

1)毫秒数在高位,自增序列在低位,整个ID都是趋势递增的。

2)不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成ID的性能也是非常高的。

3)可以根据自身业务特性分配bit位,非常灵活。

缺点:强依赖机器时钟,如果机器上时钟回拨,会导致发号重复或者服务会处于不可用状态。

结论:适用于大规模分布式架构。

​​​​​​​3.使用默认的雪花算法验证

如果不需要使用MyCAT的自增序列,而使用MySQL本身的自增主键的功能,需要在配置中更改对应的建表SQL,不设置AUTO_INCREMENT关键字,这样MyCAT就不认为这个表有自增主键的功能,就不会使用MyCAT的全局序列号。对应的插入SQL在MySQL处理,由MySQL的自增主键功能补全自增值。

​​​​​​​1.向订单表里面添加数据

INSERT INTO ORDERS(ORDER_TYPE,CUSTOMER_ID,AMOUNT) VALUES(103,102,102102);

上面的SQL里面没有使用添加ID,那么后台是怎么处理的呢?查看后台数据发现使用的雪花算法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诉予

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值