一,MyCat入门
1.什么是mycat
官网:http://www.mycat.org.cn/
mycat是数据库中间件
它可以干什么?
- 读写分离
- 数据分片:垂直拆分,水平拆分
- 多数据源整合
2.数据库中间件
中间件:是一类连接软件组件和应用的计算机软件,以便于软件各部件之间的沟通。
例子:tomcat,kafka,redis等中间件
3.为什么使用macat
- java与数据库紧耦合
- 高访问量高并发对数据库的压力
- 读写请求数据不一致
4.常见数据库中间件对比
- cobar:属于阿里B2B事业群,始于2008年,在阿里服役3年多,接管3000+个MySQL数据库的shema,集群日处理在线SQL请求50亿次以上,由于cobar发起人的离职,cobar停止维护
- mycat:开源社区在阿里cobar基础上进行二次开发,解决了cobar存在的问题,并且加入了许多新的功能在其中
- oneproxy:基于MySQL官网的proxy思想利用c进行开发的,oneproxy是一款商业收费的中间件。舍去了一些功能,专注在性能和稳定性上。
- kingshard:由小团队用go语言开发,需要不断完善
- viress:是YouTube生产在使用,结构很复杂。不支持MySQL原生协议,使用需要改造成本。
- atllas:是360团队基于MySQL proxy改写,功能还需完善,高并发下不稳定
- maxscale:是mariadb研发的中间件
- MySQLroute:是MySQL官网oracle公司发布的中间件
5.mycat原理
mycat的原理中最重要的一个动词是‘拦截’,它拦截了用户发送过来的SQL语句,首先对SQL语句做了一些特定的分析:如分片分析,路由分析,读写分离分析,缓存分析等,然后将此SQL发往后端的真实数据库,并将返回的结构做适当的处理,最终再返回给用户。
6.mycat1.X与mycat2.X的功能对比
功能 | 1.6 | 2.x |
多语句 | 不支持 | 支持 |
blob值 | 支持一部分 | 支持 |
全局二级索引 | 不支持 | 支持 |
任意跨库join(包含复杂查询) | catlet支持 | 支持 |
分片表与分片表JOIN查询 | ER表支持 | 支持 |
关联子查询 | 不支持 | 支持一部分 |
分库同时分表 | 不支持 | 支持 |
存储过程 | 支持固定形式的 | 支持更多 |
支持逻辑视图 | 不支持 | 支持 |
支持物理视图 | 支持 | 支持 |
批量插入 | 不支持 | 支持 |
执行计划管理 | 不支持 | 支持 |
路由注释 | 支持 | 支持 |
集群功能 | 支持 | 支持更多集群类型 |
自动hash分片算法 | 不支持 | 支持 |
支持第三方监控 | 支持mycat-web | 支持普罗米斯,kafka日志等监控 |
流式合拼结果集 | 支持 | 支持 |
范围查询 | 支持 | 支持 |
单表映射物理表 | 不支持 | 支持 |
XA事务 | 弱XA | 支持,事务自动恢复 |
支持MySQL8 | 需要更改mysql8的服务器配置支持 | 支持 |
虚拟表 | 不支持 | 支持 |
joinClustering | 不支持 | 支持 |
union all语法 | 不支持 | 支持 |
BKAJoin | 不支持 | 支持 |
优化器注释 | 不支持 | 支持 |
ER表 | 支持 | 支持 |
全局序列号 | 支持 | 支持 |
保存点 | 不支持 | 支持 |
离线迁移 | 支持 | 支持(实验) |
增量迁移 | CRC32算法支持 | BINLOG追平(实验) |
安全停机 | 不支持 | 支持(实验) |
HAProxy协议 | 不支持 | 支持 |
会话粘滞 | update后select会粘滞 | update后select会粘滞且支持设置时间 |
全局表插入支持全局序列号 | 不支持 | 支持 |
全局表插入支持主表插入自增结果作为序列号 | 不支持 | 支持 |
外部调用的分片算法 | 不支持但可定制 | 支持 |
二,MyCat安装和管理命令
提前安装JDK
[root@localhost ~]# tar -zxf jdk-8u171-linux-x64.tar.gz [root@localhost ~]# ls anaconda-ks.cfg jdk-8u171-linux-x64.tar.gz mysql80-community-release-el7-7.noarch.rpm jdk1.8.0_171 mycat2-install-template-1.20.zip original-ks.cfg [root@localhost ~]# mv jdk1.8.0_171/ /usr/local/java [root@localhost ~]# vi /etc/profile PATH=$PATH:/usr/local/java/bin [root@localhost ~]# source /etc/profile [root@localhost ~]# java -version java version "1.8.0_171" Java(TM) SE Runtime Environment (build 1.8.0_171-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.171-b11, mixed mode)
1.下载安装包
tar(zip)包 : http://dl.mycat.org.cn/2.0/install-template/mycat2-install-template1.20.zip jar 包 : http://dl.mycat.org.cn/2.0/1.21-release/ (下载最新的 jar 包)
2.上传服务器解压
[root@localhost ~]# ls anaconda-ks.cfg mycat2-install-template-1.20.zip original-ks.cfg mycat2-1.21-release-jar-with-dependencies.jar mysql80-community-release-el7-7.noarch.rpm [root@localhost ~]# unzip mycat2-install-template-1.20.zip [root@localhost ~]# mv mycat /usr/local/ [root@localhost mycat]# ls bin conf lib logs [root@localhost mycat]# mv /root/mycat2-1.21-release-jar-with-dependencies.jar ./lib/ [root@localhost mycat]# chmod 777 -R ./lib/
3.为mycat连接的MySQL添加用户
#直接将root改为所有地址可以登录,方便,但是在真实环境中需要根据权限来创建用户 mysql>
4.修改mycat的portotype的配置
启动mycat之前需要确认prototype数据源所对应的mysql数据库配置,修改对应的 user(用户),password(密码),url中的ip
[root@localhost mycat]# vi conf/datasources/prototypeDs.datasource.json { "dbType":"mysql", "idleTimeout":60000, "initSqls":[], "initSqlsGetConnection":true, "instanceType":"READ_WRITE", "maxCon":1000, "maxConnectTimeout":3000, "maxRetryCount":5, "minCon":1, "name":"prototypeDs", "password":"1234.Com", "type":"JDBC", "url":"jdbc:mysql://localhost:3306/mysql?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8", "user":"root", "weight":0 }
5.启动MyCat
[root@localhost mycat]# cd bin/ [root@localhost bin]# chmod 555 * [root@localhost bin]# ./mycat start
6.MyCat管理
./mycat start #开启 ./mycat stop #关闭 ./mycat restart #重启 ./mycat status #查看状态 ./mycat console #前台运行 ./mycat pause #暂停
7.mycat登录
[root@localhost bin]# mysql -uroot -p1234.Com -P 8066 -h 192.168.2.1 选项: -u:用户名 -p:密码 -P:端口 -h:IP地址 [root@localhost bin]# mysql -uroot -p1234.Com -P 9066 #后台管理端口
三,MyCat名词概念描述
1.分库分表
按照一定规则把数据库中的表拆分为多个带有数据库实例,物理库,物理表访问路径的分表
解读:
分库:一个电商项目,分为用户库、订单库等等。
分表:一张订单表数据数百万,达到 MySQL 单表瓶颈,分到多个数据库中 的多张表
2.逻辑库
数据库代理中的数据库,它可以包含多个逻辑表
解读:Mycat 里定义的库,在逻辑上存在,物理上在 MySQL 里并不存在。有可能是 多个 MySQL 数据库共同组成一个逻辑库。类似多个小孩叠罗汉穿上外套,扮演一个大 人。
3.逻辑表
数据库代理中的表,它可以映射代理连接的数据库中的表(物理表)
解读:Mycat 里定义的表,在逻辑上存在,可以映射真实的 MySQL 数据库的表。可 以一对一,也可以一对多。
4.物理库
数据库代理连接的数据库中的库,比如mysql上的information_schema
解读:MySQL 真实的数据库
5.物理表
数据库代理连接的数据库中的表,比如mysql上的information_schema.TABLES
解读:MySQL 真实的数据库中的真实数据表。
6.分库分表中间件
实现了分库分表功能的中间件,功能上相当于分库分表型数据库中的计算节点
7.分库分表型数据库
以分库分表技术构建的数据库,在组件上一般有计算节点,存储节点.它的存储节点一般是一个可独立部署的数据库产品,比如mysql
8.拆分键
即分片键,描述拆分逻辑表的数据规则的字段
解读:比如订单表可以按照归属的用户 id 拆分,用户 id 就是
9.分区
一般指数据分区,计算节点上,水平分片表拆分数据的最小区域
10.分区键
当使用等值查询的时候,能直接映射一个分区的拆分键
11.系统表,元数据表
一般指mysql中的information_schema,performance_schema,mysql三个库下的表
12.物理分表
指已经进行数据拆分的,在数据库上面的物理表,是分片表的一个分区
解读:多个物理分表里的数据汇总就是逻辑表的全部数据
13.物理分库
一般指包含多个物理分表的库
解读:参与数据分片的实际数据库
14.单库分表
在同一个数据库下同一个库表拆分成多个物理分表
15.分库
一般指通过多个数据库拆分分片表,每个数据库一个物理分表,物理分库名字相同
解读:分库是个动作,需要多个数据库参与。就像多个数据库是多个盘子,分库就是 把一串数据葡萄,分到各个盘子里,而查询数据时,所有盘子的葡萄又通过 Mycat2 组 成了完整的一串葡萄。
16.分片表,水平分片表
按照一定规则把数据拆分成多个分区的表,在分库分表语境下,它属于逻辑表的一种
17.单表
没有分片,没有数据冗余的表,
解读:没有拆分数据,也没有复制数据到别的库的表。
18.全局表,广播表
每个数据库实例都冗余全量数据的逻辑表.
它通过表数据冗余,使分片表的分区与该表的数据在同一个数据库实例里,达到join运算能够直接在该数据库实例里执行.它的数据一致一般是通过数据库代理分发SQL实现.也有基于集群日志的实现.
解读:例如系统中翻译字段的字典表,每个分片表都需要完整的字典数据翻译字段。
19.集群
多个数据节点组成的逻辑节点.在mycat2里,它是把对多个数据源地址视为一个数据源地址(名称),并提供自动故障恢复,转移,即实现高可用,负载均衡的组件
解读:集群就是高可用、负载均衡的代名词
20.数据源
连接后端数据库的组件,它是数据库代理中连接后端数据库的客户端
解读:Mycat 通过数据源连接 MySQL 数据库
21.schema(库)
在mycat2中配置表逻辑,视图等的配置
22.物理视图
后端数据库中的视图
23.逻辑视图
在mycat2中的逻辑视图是把一个查询语句视为逻辑表的功能
24.前端会话
一般指Mycat服务器中,该会话指向连接mycat的客户端
25.后端会话
一般指Mycat服务器中,该会话指向连接数据库的客户端
26.后端数据库
在数据库代理中,数据库代理连接的数据库
27.透传SQL
在数据库代理中,指从客户端接收的SQL,它不经过改动,在代理中直接发送到后端数据库
28.透传结果集
在数据库代理中,指从后端数据库返回的结果集,不经过改动,转换,写入到前端会话
29.ER表
狭义指父子表中的子表,它的分片键指向父表的分片键,而且两表的分片算法相同
广义指具有相同数据分布的一组表.
解读:关联别的表的子表,例如:订单详情表就是订单表的 ER 表
30.原型库(prototype)
原型库是 Mycat2 后面的数据库,比如 mysql 库
解读:原型库就是存储数据的真实数据库,配置数据源时必须指定原型库
四,MyCat配置文件介绍
1.配置文件
[root@localhost ~]# cd /usr/local/mycat/conf/ [root@localhost conf]# ll 总用量 32 drwxr-xr-x 2 root root 36 6月 28 2021 clusters drwxr-xr-x 2 root root 41 5月 29 11:01 datasources -rw-r--r-- 1 root root 3338 3月 5 2021 dbseq.sql -rw-r--r-- 1 root root 316 11月 2 2021 logback.xml -rw-r--r-- 1 root root 0 3月 5 2021 mycat.lock drwxr-xr-x 2 root root 31 6月 28 2021 schemas drwxr-xr-x 2 root root 6 6月 28 2021 sequences -rw-r--r-- 1 root root 776 12月 28 2021 server.json -rw-r--r-- 1 root root 1643 3月 5 2021 simplelogger.properties drwxr-xr-x 2 root root 233 6月 28 2021 sql drwxr-xr-x 2 root root 6 6月 28 2021 sqlcaches -rw-r--r-- 1 root root 49 3月 5 2021 state.json drwxr-xr-x 2 root root 28 6月 28 2021 users -rw-r--r-- 1 root root 211 3月 5 2021 version.txt -rw-r--r-- 1 root root 4165 1月 13 2022 wrapper.conf clusters:集群 datasources:数据源 server.json:服务配置 user:用户目录
2.用户(user)
配置用户相关信息
1.所在目录
mycat /conf/users
2.命名方式
{用户名}.user.json
3.配置内容
[root@localhost conf]# vi users/root.user.json { "dialect":"mysql", "ip":null, "password":"123456", "transactionType":"xa", "username":"root" } #字段含义: #username:用户名 #password:密码 #isolation:设置初始化的事务隔离级别 #transactionType:事务类型 可选值: proxy 本地事务,在涉及大于 1 个数据库的事务,commit 阶段失败会导致不一致,但是兼容性最好 xa 事务,需要确认存储节点集群类型是否支持 XA 可以通过语句实现切换 set transaction_policy = 'xa' set transaction_policy = 'proxy' 可以通过语句查询 SELECT @@transaction_policy
3.数据源(datasource)
配置mycat连接的数据源信息
1.所在目录
mycat /conf/datasources
2.命名方式
{数据源名字}.datasource.json
3.配置内容
[root@localhost conf]# vi datasources/prototypeDs.datasource.json { "dbType":"mysql", "idleTimeout":60000, "initSqls":[], "initSqlsGetConnection":true, "instanceType":"READ_WRITE", "maxCon":1000, "maxConnectTimeout":3000, "maxRetryCount":5, "minCon":1, "name":"prototypeDs", "password":"1234.Com", "type":"JDBC", "url":"jdbc:mysql://localhost:3306/mysql?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8", "user":"root", "weight":0 } 字段含义: dbtype:数据库类型,mysql name:用户名 password:密码 type:数据源类型,默认JDBC url:访问数据库地址 idletimeout:空闲连接超时时间 initsqls:初始化sql initsqlsgetconnection:对于JDBC每次获取连接是否都执行initSqls instanceType:配置实例只读还是读写 可选值:READ_WRITE,READ,WRITE
4.集群(cluster)
配置集群信息
1.所在目录
mycat /conf/clusters
2.命名方式
{集群名字}.clusteer.json
3.配置内容
[root@localhost conf]# vi clusters/prototype.cluster.json { "clusterType":"MASTER_SLAVE", "heartbeat":{ "heartbeatTimeout":1000, "maxRetry":3, "minSwitchTimeInterval":300, "slaveThreshold":0 }, "masters":[ #配置多个节点,在主挂的时候会选一个检测存活的数据源作为主节点 "prototypeDs" ], "maxCon":200, "name":"prototype", "readBalanceType":"BALANCE_ALL", "switchType":"SWITCH" } 字段: clusterType:集群类型 可选值: single_node:单一节点 master_slave:普通主从 garela_cluster:garela cluster /PXC 集群 MHA:MHA集群 MGR:MGR集群 readBalanceType:查询负责均衡策略 可选值: BALANCE_ALL(默认值):获取集群中所有数据源 BALANCE_ALL_READ:获取集群中允许读的数据源 BALANCE_READ_WEITE:获取集群中允许读写的数据源,但允许读的数据源优先 BALANCE——NODE:获取集群中允许写数据源,即主节点中选择 switchType:切换类型 可选值: NOT_SWITCH:不进行主从切换 SWITCH:进行主从切换
5.逻辑库表(schema)
配置逻辑库表,实现分库分表
1.所在目录
mycat /conf/shemas
2.命名方式
{库名}.schema.json
3.配置内容
[root@localhost conf]# vi schemas/mysql.schema.json #库配置 "locality":{ "schemaName":"mysql", "tableName":"spm_baseline", "targetName":"prototype" } #schemaName:逻辑库名 #targetName:目的数据源或集群 targetName自动从prototype目标加载test库下的物理表或者视图作为单表,prototype必须是MySQL服务器 #单表配置 { "schemaName": "mysql-test", "normalTables": { "role_edges": { "createTableSQL":null,//可选 "locality": { "schemaName": "mysql",//物理库,可选 "tableName": "role_edges",//物理表,可选 "targetName": "prototype"//指向集群,或者数据源 } }
五,搭建读写分离
我们通过mycat和mycat的主从复制配合搭建数据库的读写分离,实现MySQL的高可用性,我们将搭建,一主一从,双主双从两种读写分离模式。
1.搭建一主一从
一个主机用于处理所有写请求,一台从机负责所有读请求
1.搭建MySQL数据库主从复制
1.主MySQL配置
[root@localhost ~]# vi /etc/my.cnf server-id=1 log-bin=mysql-bin [root@localhost ~]# systemctl restart mysqld
2.其他配置
#设置不要复制的数据库(可以设置为多个) binlog-ignore-db=dbname binlog-ignore-db=information_schema #设置需要复制的数据库 binlog-do-db=dbname #设置binlog格式 binlog_format=statement
2.从MySQL配置
[root@localhost ~]# vi /etc/my.cnf server-id=2 log-bin=mysql-bin [root@localhost ~]# systemctl restart mysqld
3.主MySQL添加授权用户和二进制日志信息
mysql> grant replication slave on *.* to slave@'%' identified by '1234.Com'; mysql> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000002 | 438 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec)
4.在从机上做主从
mysql> change master to master_host='192.168.2.1',master_user='slave',master_password='1234.Com',master_log_pos=438,master_log_file='mysql-bin.000002'; Query OK, 0 rows affected, 2 warnings (0.00 sec) mysql> start slave; Query OK, 0 rows affected (0.00 sec) mysql> show slave status\G Slave_IO_Running: Yes #数据传输 Slave_SQL_Running: Yes #SQL执行
5.测试验证(主MySQL)
mysql> create database mydb1; Query OK, 1 row affected (0.00 sec) mysql> use mydb1; Database changed mysql> create table mytb1(id int,name varchar(50)); Query OK, 0 rows affected (0.00 sec) mysql> insert into -> mytb1 values(1,'zhangsan'); Query OK, 1 row affected (0.03 sec) mysql> insert into mytb1 values(2,'lisi'); Query OK, 1 row affected (0.00 sec) mysql> select * from mytb1; +------+----------+ | id | name | +------+----------+ | 1 | zhangsan | | 2 | lisi | +------+----------+ 2 rows in set (0.00 sec)
2.配置mycat读写分离
1.创建数据源
[root@localhost mycat]# mysql -uroot -p123456 -P8066 -h192.168.2.1 mysql> create database mydb1; [root@localhost mycat]# vi conf/schemas/mydb1.schema.json { "customTables":{}, "globalTables":{}, "normalProcedures":{}, "normalTables":{}, "schemaName":"mydb1", "targetName": "prototype", "shardingTables":{}, "views":{} }
2.登录mycat添加数据源
[root@localhost mycat]# mysql -uroot -p123456 -P8066 -h192.168.2.1 mysql> /*+ mycat:createDataSource{ "name":"rwSepw","url":"jdbc:mysql://192.168.2.1:3306/mydb1?useSSL=false&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true", "user":"root","password":"1234.Com" } */; Query OK, 0 rows affected (0.02 sec) mysql> mysql> /*+ mycat:createDataSource{ "name":"rwSepr","url":"jdbc:mysql://192.168.2.2:3306/mydb1?useSSL=false&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true", "user":"root","password":"1234.Com" } */; Query OK, 0 rows affected (0.03 sec) #查询配置数据源结果 mysql> /*+ mycat:showDataSources{} */\G
3.更新集群信息,添加dr0从节点,实现读写分离
mysql> /*!mycat:createCluster{"name":"prototype","masters":["rwSepw"],"replicas":["rwSepr"]} */; Query OK, 0 rows affected (0.03 sec) mysql> /*+ mycat:showClusters{} */; #查看集群配置文件 +-----------+-------------+-------------------+-------------+----------+---------------+-------------------------------------------+-------------------------------------------+-----------+ | NAME | SWITCH_TYPE | MAX_REQUEST_COUNT | TYPE | WRITE_DS | READ_DS | WRITE_L | READ_L | AVAILABLE | +-----------+-------------+-------------------+-------------+----------+---------------+-------------------------------------------+-------------------------------------------+-----------+ | prototype | SWITCH | 2000 | BALANCE_ALL | rwSepw | rwSepw,rwSepr | io.mycat.plug.loadBalance.BalanceRandom$1 | io.mycat.plug.loadBalance.BalanceRandom$1 | true | +-----------+-------------+-------------------+-------------+----------+---------------+-------------------------------------------+-------------------------------------------+-----------+ 1 row in set (0.01 sec) ava.lang.RuntimeException: java.lang.IllegalArgumentException: ignored rw Sepr
修改集群配置文件
[root@localhost mycat]# vi /usr/local/mycat/conf/clusters/prototype.cluster.json { "clusterType":"MASTER_SLAVE", "heartbeat":{ "heartbeatTimeout":1000, "maxRetryCount":3, "minSwitchTimeInterval":300, "showLog":false, "slaveThreshold":0.0 }, "masters":[ "rwSepw" ], "replicas":[ "rwSepr" ], "maxCon":2000, "name":"prototype", "readBalanceType":"BALANCE_ALL", "switchType":"SWITCH" } readBalanceType 查询负载均衡策略 可选值: BALANCE_ALL(默认值) 获取集群中所有数据源 BALANCE_ALL_READ 获取集群中允许读的数据源 BALANCE_READ_WRITE 获取集群中允许读写的数据源,但允许读的数据源优先 BALANCE_NONE 获取集群中允许写数据源,即主节点中选择 switchType NOT_SWITCH:不进行主从切换 SWITCH:进行主从切换
4.重启mycat
[root@localhost mycat]# ./bin/mycat restart Stopping mycat2... Stopped mycat2. Starting mycat2...
5.验证读写分离
在从MySQL上修改数据 mysql> update mytb1 set name='wangwu' where id=2; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 然后使用mycat登录 查询来查看数据不同
六,双主双从读写分离
一个主机 m1 用于处理所有写请求,它的从机 s1 和另一台主机 m2 还有它的从机 s2 负责所有读请求。当 m1 主机宕机后,m2 主机负责写请求,m1、m2 互为备机。架构图 如下
1.环境
角色 | IP地址 |
master1 | 192.168.2.1 |
slave1 | 192.168.2.2 |
master2 | 192.168.2.3 |
slave2 | 192.168.2.4 |
2.搭建双主双从
1.一主一从
根据上面的读写分离的步骤做两遍
2.双主双从
master1与master2互作主从
1.master1配置
mysql> change master to master_host='192.168.2.3',master_user='slave',master_password='1234.Com',master_log_pos=438,master_log_file='mysql-bin.000001'; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> start slave; Query OK, 0 rows affected (0.00 sec)
2.master2配置
mysql> change master to master_host='192.168.2.1',master_user='slave',master_password='1234.Com',master_log_pos=6394,master_log_file='mysql-bin.000001'; Query OK, 0 rows affected, 2 warnings (0.01 sec) mysql> start slave; Query OK, 0 rows affected (0.00 sec)
3.测试
查看是否master1创建库,四台同步
3.实现多种主从
1.双主双从
*m1:主机 *m2:备机,也负责读 *s1,s2:从机
2.添加两个数据源
注意:如果不是从一主一从做的需要添加四个数据源
1.登录mycat操作
/*+ mycat:createDataSource{ "name":"rwSepw2","url":"jdbc:mysql://192.168.2.3:3306/mydb1?useSSL=false&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true", "user":"root","password":"1234.Com" } */; /*+ mycat:createDataSource{ "name":"rwSepr2","url":"jdbc:mysql://192.168.2.4:3306/mydb1?useSSL=false&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true", "user":"root","password":"1234.Com" } */;
2.修改集群配置文件
[root@localhost mycat]# vi /usr/local/mycat/conf/clusters/prototype.cluster.json { "clusterType":"MASTER_SLAVE", "heartbeat":{ "heartbeatTimeout":1000, "maxRetryCount":3, "minSwitchTimeInterval":300, "showLog":false, "slaveThreshold":0.0 }, "masters":[ "rwSepw","rwSepw2" ], "replicas":[ "rwSepr","rwSepr2","rwSepw2" ], "maxCon":2000, "name":"prototype", "readBalanceType":"BALANCE_ALL", "switchType":"SWITCH" }
七,分库分表
1.分库分表原理
一个数据库由很多表的构成,每个表对应着不同的业务,垂直切分是指按照业 务将表进行分类,分布到不同 的数据库上面,这样也就将数据或者说压力分担到不同 的库上面,如下图:
系统被切分成了,用户,订单交易,支付几个模块
2.如何分库
一个问题:在两台主机上的两个数据库中的表,能否关联查询?
答案:不可以关联查询。
分库的原则:有紧密关联关系的表应该在一个库里,相互没有关联关系的表可以分到 不同的库里。
例子:
#客户表 rows:20万 CREATE TABLE customer( id INT AUTO_INCREMENT NAME VARCHAR(200), PRIMARY KEY(id) ); #订单表 rows:600万 CREATE TABLE orders( id INT AUTO_INCREMENT, order_type INT, customer_id INT, amount DECIMAL(10,2), PRIMARY KEY(id) ); #订单详细表 rows:600万 CREATE TABLE orders_detail( id INT AUTO_INCREMENT, detail VARCHAR(2000), order_id INT, PRIMARY KEY(id) ); #订单状态字典表 rows:20 CREATE TABLE dict_order_type( id INT AUTO_INCREMENT, order_type VARCHAR(200), PRIMARY KEY(id) );
以上四个表如何分库?客户表分在一个数据库,另外三张都需要关联查询,分在另外 一个数据库。
3.如何分表
1.选择要拆分的表
MySQL 单表存储数据条数是有瓶颈的,单表达到 1000 万条数据就达到了瓶颈,会 影响查询效率,需要进行水平拆分(分表)进行优化。
例如:例子中的 orders、orders_detail 都已经达到 600 万行数据,需要进行分表 优化。
2.分库字段
以 orders 表为例,可以根据不同自字段进行分表
分表字段 | 效果 |
id(主键,或创建时间) | 查询订单注重是时效,历史订单被查询的次数少,如此分片会造成一个节点访问多,一个访问少,不平均 |
customer_id(客户id) | 根据客户id去分,两个节点访问平均,一个客户的所有订单都在同一个节点 |
4.实现分库分表
Mycat2 一大优势就是可以在终端直接创建数据源、集群、库表,并在创建时指定 分库、分表。与 1.6 版本比大大简化了分库分表的操作
1.添加数据库,存储数据源
/*+ mycat:createDataSource{ "name":"dw0", "url":"jdbc:mysql://192.168.2.1:3306", "user":"root", "password":"1234.Com" } */; /*+ mycat:createDataSource{ "name":"dr0", "url":"jdbc:mysql://192.168.2.1:3306", "user":"root", "password":"1234.Com" } */; /*+ mycat:createDataSource{ "name":"dw1", "url":"jdbc:mysql://192.168.2.2:3306", "user":"root", "password":"1234.Com" } */; /*+ mycat:createDataSource{ "name":"dr1", "url":"jdbc:mysql://192.168.2.2:3306", "user":"root", "password":"1234.Com" } */;
2.添加集群配置
把新添加的数据源配置成集群
/*!mycat:createCluster{"name":"c0","masters":["dw0"],"replicas":["dr0"]} */; /*! {mycat:createCluster{"name":"c1","masters":["dw1"],"replicas":["dr1"]} */;
3.创建全局表
#添加数据库db1 CREATE DATABASE db1; #在建表语句中加上关键字 BROADCAST(广播,即为全局表) CREATE TABLE db1.`travelrecord` ( `id` bigint NOT NULL AUTO_INCREMENT, `user_id` varchar(100) DEFAULT NULL, `traveldate` date DEFAULT NULL, `fee` decimal(10,0) DEFAULT NULL, `days` int DEFAULT NULL, `blob` longblob, PRIMARY KEY (`id`), KEY `id` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 BROADCAST
4.创建分片表(分库分表)
#在 Mycat 终端直接运行建表语句进行数据分片 CREATE TABLE db1.orders( id BIGINT NOT NULL AUTO_INCREMENT, order_type INT, customer_id INT, amount DECIMAL(10,2), PRIMARY KEY(id), KEY `id` (`id`) )ENGINE=INNODB DEFAULT CHARSET=utf8 dbpartition BY mod_hash(customer_id) tbpartition BY mod_hash(customer_id) tbpartitions 1 dbpartitions 2; #数据库分片规则,表分片规则,以及各分多少片 INSERT INTO orders(id,order_type,customer_id,amount) VALUES(1,101,100,100100); INSERT INTO orders(id,order_type,customer_id,amount) VALUES(2,101,100,100300); INSERT INTO orders(id,order_type,customer_id,amount) VALUES(3,101,101,120000); INSERT INTO orders(id,order_type,customer_id,amount) VALUES(4,101,101,103000); INSERT INTO orders(id,order_type,customer_id,amount) VALUES(5,102,101,100400); INSERT INTO orders(id,order_type,customer_id,amount) VALUES(6,102,100,100020); SELECT * FROM orders; #同样可以查看生成的配置信息 #进入相关目录查看 schema 配置 vim /usr/local/mycat/conf/schemas/db1.schema.json
ongblob,
PRIMARY KEY (id
),
KEY id
(id
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 BROADCAST
#### 4.创建分片表(分库分表) ```sql #在 Mycat 终端直接运行建表语句进行数据分片 CREATE TABLE db1.orders( id BIGINT NOT NULL AUTO_INCREMENT, order_type INT, customer_id INT, amount DECIMAL(10,2), PRIMARY KEY(id), KEY `id` (`id`) )ENGINE=INNODB DEFAULT CHARSET=utf8 dbpartition BY mod_hash(customer_id) tbpartition BY mod_hash(customer_id) tbpartitions 1 dbpartitions 2; #数据库分片规则,表分片规则,以及各分多少片 INSERT INTO orders(id,order_type,customer_id,amount) VALUES(1,101,100,100100); INSERT INTO orders(id,order_type,customer_id,amount) VALUES(2,101,100,100300); INSERT INTO orders(id,order_type,customer_id,amount) VALUES(3,101,101,120000); INSERT INTO orders(id,order_type,customer_id,amount) VALUES(4,101,101,103000); INSERT INTO orders(id,order_type,customer_id,amount) VALUES(5,102,101,100400); INSERT INTO orders(id,order_type,customer_id,amount) VALUES(6,102,100,100020); SELECT * FROM orders; #同样可以查看生成的配置信息 #进入相关目录查看 schema 配置 vim /usr/local/mycat/conf/schemas/db1.schema.jso