写点什么

MyCat 集成 MySQL 完成数据库集群建设

用户头像
831143
关注
发布于: 2021 年 02 月 26 日
MyCat集成MySQL完成数据库集群建设

1.数据库的分区技术

1.1 分区的概念

数据库的分区技术,主要解决海量的数据存储与查询问题。

提高数据库查询效率方法:

1、使用索引技术

2、使用缓存技术

上述两种方法存在缺陷:数据量非常大时不好处理


当 MySQL 数据库一个表的数据量远超过 1000W + 时,会影响服务器的性能吗?

答案:会影响


解决方案:

1、分库分表

2、分区

3、在上述的基础之上,使用索引 + 缓存技术

4、全文检索引擎技术(暂时跟这里无关)


《阿里巴巴的编码规范》推荐单表数据超过 500W,或者文件的容量超 2G,就需要分库分表,或者分区

分区:将一个表从物理上进行拆分成多个文件进行存储,但是从逻辑上来/或者从视图上来看,只有一张表。

1.2 分区有哪些技术?

现在几乎所有的关系型数据都提供了分区技术,但是 mysql 是从 5.1 开始才提供的。它是借鉴 Oracle 分区技术实现的。

Range 分区

基于给定连续区间的列值进行分区,例如:按照员工的工号(no)进行分区,1-10 一个区间,10-20 一个区间,20-40 一个区间,40-……区间

List 分区

基于离散值集合的列值进行分区,例如:存储学生,按照学院的教室编号(no)进行分区,[1,5,8] 在一个区间, [2,4,6]在一个区间,[3,7,9]在一个区间……

Hash 分区

基于估计区间个数的一种分区技术,例如:存储学生,固定的分为:10 个区间,使用学生的学号与 10 进行取余,余数是几就放置在哪个分区文件中

Key 分区

类似于按照 HASH 分区,区别在于 KEY 分区只支持计算一列或多列,且 MySQL 服务器提供自身的哈希函数(例如:密码函数 password()),它还可以操作字符串(性能非常的差,不推荐)

一个区间就对应着一个物理文件


目前来讲,使用最多的是前 3 种分区技术

1.3 分区的具体实现

Rage 分区的实现

使用场景:假设现在有一张表,该表用于保存有 20 家分公司的所有职工数据,

这 20 家分公司编号分别从 1 到 20,如果想要分配到 4 个分区,则需要使用如下的语句

CREATE TABLE t_emps (   id            bigint         not null        auto_increment,   store_id      int            not null,   user_name     varchar(20)    null,   job_no        int            not null,   hired         date           not null,   remark        varchar(200)   null,   constraint PK_T_EMPLOYEES primary key clustered (id,store_id))PARTITION BY RANGE (store_id) (    PARTITION p0 VALUES LESS THAN (5),    PARTITION p1 VALUES LESS THAN (10),    PARTITION p2 VALUES LESS THAN (15),    PARTITION p3 VALUES LESS THAN (20));
复制代码

MYSQL 官网上,要求分区字段为了提升查询效率,也必须添加主键约束


图片1.png


如果未来,我不知道需要开多少家分公司,那么使用可以 MaxValue 作为做大区间。

List 分区的实现

LIST 分区技术与 RANGE 分区技术很类似,只是它操作的不再是连续区间,而是具体的数值

应用场景:假设现在有一张表,该表用于保存有 20 家分公司的所有职工数据,这 20 家分公司编号分别从 1 到 20,如果要按照固定值进行分区,应该使用如下语句:

CREATE TABLE t_emps (   id            bigint         not null       auto_increment,   store_id      int            not null,   user_name     varchar(20)    null,   job_no        int            not null,   hired         date           not null,   remark        varchar(200)   null,   constraint PK_T_EMPLOYEES primary key clustered (id,store_id))PARTITION BY LIST (store_id) (    PARTITION p0 VALUES IN (1,2,4,5,6),    PARTITION p1 VALUES IN (3,7,8,9,10),    PARTITION p2 VALUES IN (11,12,13,14,15,16),    PARTITION p3 VALUES IN (17,18,19,20));
复制代码

store_id 一定是一个能够参与计算的值,可以是:YEAR(hired)

Hash 分区的实现

使用将要插入到表中的这些行的列值进行计算

应用场景:假设现在有一张表,该表用于保存有 20 家分公司的所有职工数据,

这 20 家分公司编号分别从 1 到 20,如果按照入职时间来进行分区,入职时间是不可预

订的,并且分区数已经固定为 4 个,则应该使用如下语句

CREATE TABLE t_emps (   id            bigint         not null       auto_increment,   store_id      int            not null,   user_name     varchar(20)    null,   job_no        int            not null,   hired         date           not null,   remark        varchar(200)   null,   constraint PK_T_EMPLOYEES primary key clustered (id,hired))PARTITION BY HASH(YEAR(hired))PARTITIONS 4;
复制代码

计算规则:将入职的年份,与 4 进行取余,余数代表着 具体的分区

Key 分区的实现

KEY 分区技术与 HASH 分区技术相似,但是它的基准点可以不是整数类型,可以是如字符串等类型字段。如果放置一个字符串,MYSQL 内部就需要先经过一系列的运算,得到一个数值,然后,将该数值与 4 进行取余,余数就代表分区

CREATE TABLE t_emps (   id            bigint         not null       auto_increment,   store_id      int            not null,   user_name     varchar(20)    not null,   job_no        int            not null,   hired         date           not null,   remark        varchar(200)   null,   constraint PK_T_EMPLOYEES primary key clustered (id,user_name))PARTITION BY KEY(user_name)PARTITIONS 4;
复制代码

1.4 分区的适用场景


2. 数据库的主从复制

2.1 主从复制的概念

大型网站为了软解大量的并发访问,除了在网站实现分布式负载均衡,远远不够。到了数据业务层、数据访问层,如果还是传统的数据结构,或者只是单单靠一台服务器来处理如此多的数据库连接操作,数据库必然会崩溃,特别是数据丢失的话,后果更是不堪设想。这时候,我们会考虑如何减少数据库的连接,下面就进入我们今天的主题。

利用主从数据库来实现读写分离,从而分担主数据库的压力。在多个服务器上部署 mysql,将其中一台认为主数据库,而其他为从数据库,实现主 从同步。其中主数据库负责主动写的操作,而从数据库则只负责主动读的操作(slave 从数据库仍然会被动的进行写操作,为了保持数据一致性),这样就可以很大程度上的避免数据丢失的问题,同时也可减少数据库的连接,减轻主数据库的负载。

当连接不够时,解决连接的问题!!!

2.2 主从复制的方式

同步复制

所谓的同步复制,意思是 master 的变化,必须等待 slave-1,slave-2,...,slave-n 完成后才能返回。这样,显然不可取,也不是 MYSQL 复制的默认设置。比如,在 WEB 前端页面上,用户增加了条记录,需要等待很长时间。

异步复制

如同 AJAX 请求一样。master 只需要完成自己的数据库操作即可。至于 slaves 是否收到二进制日志,是否完成操作,不用关心。master 只保证 slaves 中的一个操作成功,就返回,其他 slave 不管。这个功能,是由 google 为 MYSQL 引入的。

2.3 主从复制的原理

整个主从复制的核心:binary.log

注意:从库异步读取主库的变化,不是主库同步向从库推

缺点:应用程序在获取实时性比较高的数据时,可能拿到手上的数据有延迟。所以如果对于实时性比较高的,建议还是从主库获取

2.4 主从复制的目标

1、数据热备,及时备份

2、读写分离,减轻主库的连接压力

2.5 主从赋值的实现

注意:下列操作使用到了 docker 相关知识

准备 3 台数据库

默认情况,mysql 数据库是没有开启 “二进制日志”的,如果需要开启,就需要手动配置

使用如下命令,开启一个 mysql 的容器:

docker run --name mysql01 -p 3306:3306 -v /root/mysql/data-3306:/var/lib/mysql -e MYSQLROOTPASSWORD=123456 -d daocloud.io/library/mysql:5.7.4
复制代码

使用如下命令,从容器中复制 my.cnf 到宿主机:

docker cp mysql01:/usr/local/mysql/my.cnf /usr/local/my.cnf
复制代码

 使用 docker stop mysql01 && docker rm mysql01 移除 mysql01 容器

分别修改 3 台数据库对应的配置文件

主节点 my.cnf 的模板

# For advice on how to change settings please see# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
[mysqld]
# Remove leading # and set to the amount of RAM for the most important data# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.# innodb_buffer_pool_size = 128M
# Remove leading # to turn on a very important data integrity option: logging# changes to the binary log between backups.# log_bin# 开启二进制日志记录功能log-bin=mysql-bin# 配置集群环境下的 服务ID(不能重复)server-id=1# These are commonly set, remove the # and set as required.# basedir = .....# datadir = .....# port = .....# server_id = .....# socket = .....
# Remove leading # to set options mainly useful for reporting servers.# The server defaults are faster for transactions and fast SELECTs.# Adjust sizes as needed, experiment to find the optimal values.# join_buffer_size = 128M# sort_buffer_size = 2M# read_rnd_buffer_size = 2M
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
复制代码

从节点 s1.cnf 的模板

# For advice on how to change settings please see# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
[mysqld]
# Remove leading # and set to the amount of RAM for the most important data# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.# innodb_buffer_pool_size = 128M
# Remove leading # to turn on a very important data integrity option: logging# changes to the binary log between backups.# log_bin# 开启二进制日志记录功能log-bin=mysql-bin# 配置集群环境下的 服务ID(不能重复)server-id=2# These are commonly set, remove the # and set as required.# basedir = .....# datadir = .....# port = .....# server_id = .....# socket = .....
# Remove leading # to set options mainly useful for reporting servers.# The server defaults are faster for transactions and fast SELECTs.# Adjust sizes as needed, experiment to find the optimal values.# join_buffer_size = 128M# sort_buffer_size = 2M# read_rnd_buffer_size = 2M
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
复制代码

从节点 s2.cnf 的模板

# For advice on how to change settings please see# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
[mysqld]
# Remove leading # and set to the amount of RAM for the most important data# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.# innodb_buffer_pool_size = 128M
# Remove leading # to turn on a very important data integrity option: logging# changes to the binary log between backups.# log_bin# 开启二进制日志记录功能log-bin=mysql-bin# 配置集群环境下的 服务ID(不能重复)server-id=3# These are commonly set, remove the # and set as required.# basedir = .....# datadir = .....# port = .....# server_id = .....# socket = .....
# Remove leading # to set options mainly useful for reporting servers.# The server defaults are faster for transactions and fast SELECTs.# Adjust sizes as needed, experiment to find the optimal values.# join_buffer_size = 128M# sort_buffer_size = 2M# read_rnd_buffer_size = 2M
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
复制代码

启动 3 台服务器

docker run --name mysql01 -p 3306:3306 -v /usr/local/my.cnf:/etc/mysql/my.cnf -v /root/mysql/data-3306:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d daocloud.io/library/mysql:5.7.4

docker run --name mysql02 -p 3307:3306 --link mysql01:mysql01 -v /usr/local/s1.cnf:/etc/mysql/my.cnf -v /root/mysql/data-3307:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d daocloud.io/library/mysql:5.7.4


docker run --name mysql03 -p 3308:3306 --link mysql01:mysql01 -v /usr/local/s2.cnf:/etc/mysql/my.cnf -v /root/mysql/data-3308:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d daocloud.io/library/mysql:5.7.4
复制代码

开启成功的效果:

备注:

也可以在连接工具上,使用 show binary logs;查看二进制日志是否开启,数值越大的,内容越新。

如果要查看某一个具体文件的内容:可以使用 show binlog events in 'mysql-bin.000003'

主库授权

在主库的连接工具上,执行如下命令:

grant all on *.* to 'feiyu'@'%' identified by '123456'; flush privileges;
复制代码



执行之后,使用show master status查看主库的最新状态

设置从库读取主库的位置

在从库的连接工具上,分别执行以下语句:

change master to masterhost='mysql01',masteruser='feiyu',masterpassword='123456',masterlog_file='mysql-bin.000003',master_logpos=1173,masterport=3306;

 

设置从库从哪里获取数据

master_host='mysql01' 主库的位置,一般配置 IP,但是 Docker 容器环境下,可以配置容器的名称

masteruser='feiyu',masterpassword='123456'  从库靠什么账号以及密码登录主库

masterlogfile='mysql-bin.000003',master_log_pos=1173 从库读取主库的哪一个二进制日志文件,从哪一个地方开始读取

master_port=3306 主库的端口号

开启主从复制

在从库的连接工具上,输入以下命令

start slave; 该命令即可开启主从复制

show slave status 查看主从复制是否开启成功

3. 数据库的分库分表

3.1 分库分表的概念

分表:就是将表进行拆分,垂直拆分法和水平拆分法

垂直拆分法:将一个大表中的字段拆分成多个不同的表,然后使用外键进行关联(我们在设计数据库采用的是“范式三原则”,已经实现过了,几乎拆无可拆) 不推荐

水平拆分法:将不同的数据,放置表结构相同的不同的表内部。

分库:同上,就是将数据库进行拆分,垂直拆分法以及水平拆分法

垂直拆分法:将一个数据库的不同的表,按照业务放置在不同的数据库,例如:电商系统拆分为:客户资料数据库,商品数据库,订单数据库,库存数据库,物流数据库……

水平拆分法:将表结构相同的表,拆分到不同的数据库中,例如:人口统计系统中:四川人资料库,河南人资料库,上海人资料库,青海人资料库……

总结一下:拆的原理如上,拆好拆,但是拆了以后不可避免的会出现:分布式事务问题,多个数据库源管理的问题,拆并不是只拆一次

3.2 MyCat 的概述

当业务非常复杂以后,数据库的拆分可能不可避免,多个数据库就需要有一个东西,可以统一管理,mycat 刚好合适。

数据库中间件:应用程序-中间件-数据库集群


myCat 的特点:

1、它给数据库集群提供了一个透明代理

2、它是 Java 语言开发的,调试和配置相对而言就非常的简单


3.3 MyCat 中的常见术语

数据库中间件:位于应用程序与数据库集群中的软件,就叫中间件

逻辑库(schema): 通过 mycat 显示给应用程序看的数据库

逻辑表(table): 显示在逻辑库中的表

分片表:使用的分片规则的逻辑表

不分片表:没有使用 rule=""分片规则的表,就是非分片表

分片节点:数据切分后,一个大表被分到不同的分片数据库上面,每个表分片所在的数据库就是分片节点(dataNode)

节点主机:数据切分后,每个分片节点(dataNode)不一定都会独占一台机器,同一机器上面可以有多个分片数据库,这样一个或多个分片节点(dataNode)所在的机器就是节点主机(dataHost),为了规避单节点主机并发数限制,尽量将读写压力高的分片节点(dataNode)均衡的放在不同的节点主机(dataHost)。节点主机代表每一个单独的数据库!!

分片规则:前面讲了数据切分,一个大表被分成若干个分片表,就需要一定的规则,这样按照某种业务规则把数据分到某个分片的规则就是分片规则,数据切分选择合适的分片规则非常重要,将极大的避免后续数据处理的难度。

3.4 MyCat 如何使用

使用docker search mycat命令查询是否有 fify/mycat 镜像存在

使用docker pull fify/mycat将该镜像下载到宿主机

3.4.1 准备 3 台数据库

docker run --name mysql10 -p 3310:3306 -v /root/mysql/data-3310:/var/lib/mysql -e MYSQLROOTPASSWORD=123456 -d daocloud.io/library/mysql:5.7.4
 
docker run --name mysql11 -p 3311:3306 -v /root/mysql/data-3311:/var/lib/mysql -e MYSQLROOTPASSWORD=123456 -d daocloud.io/library/mysql:5.7.4
 
docker run --name mysql12 -p 3312:3306 -v /root/mysql/data-3312:/var/lib/mysql -e MYSQLROOTPASSWORD=123456 -d daocloud.io/library/mysql:5.7.4
复制代码

并确保 3 台服务器都能正常运行!!!

3.4.2 进行数据库的准备

分表在 3 台 docker 容器上,创建 3 个不同的数据库

mysql10 ->db1

mysql11 ->db2

mysql12 ->db3

 分表在 db1,db2,db3 执行以下语句

CREATE TABLE `t_goods` ( `id` bigint NOT NULL , `name` varchar(100) DEFAULT NULL, `price` double DEFAULT NULL, `type` varchar(100) DEFAULT NULL, `address` varchar(100) DEFAULT NULL, `data` datetime DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8; 
复制代码

分表在 db1,db2 执行以下语句

CREATE TABLE `t_order` ( `id` bigint NOT NULL , `order_no` varchar(100) DEFAULT NULL, `order_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8; 
复制代码

3.4.3 MyCat 环境的准备

Mycat 的官网http://www.mycat.org.cn/上,下载 mycat 的安装包

下载的目录,不是为了安装,而是为了使用它的 conf 配置



3.4.4 配置 MyCat 集群

对于 Mycat 来讲,最重要的配置文件:

schema.xml 用来配置 mycat + mysql 的集群

server.xml  用来配置连接账号信息

配置 Server.xml 文件

	<?xml version="1.0" encoding="UTF-8"?><!-- - - Licensed under the Apache License, Version 2.0 (the "License"); 	- you may not use this file except in compliance with the License. - You 	may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 	- - Unless required by applicable law or agreed to in writing, software - 	distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT 	WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the 	License for the specific language governing permissions and - limitations 	under the License. --><!DOCTYPE mycat:server SYSTEM "server.dtd"><mycat:server xmlns:mycat="http://io.mycat/">	<system>	<property name="nonePasswordLogin">0</property> <!-- 0为需要密码登陆、1为不需要密码登陆 ,默认为0,设置为1则需要指定默认账户-->	<property name="useHandshakeV10">1</property>	<property name="useSqlStat">0</property>  <!-- 1为开启实时统计、0为关闭 -->	<property name="useGlobleTableCheck">0</property>  <!-- 1为开启全加班一致性检测、0为关闭 -->
<property name="sequnceHandlerType">2</property> <!--<property name="sequnceHandlerPattern">(?:(\s*next\s+value\s+for\s*MYCATSEQ_(\w+))(,|\)|\s)*)+</property>--> <!--必须带有MYCATSEQ_或者 mycatseq_进入序列匹配流程 注意MYCATSEQ_有空格的情况--> <property name="sequnceHandlerPattern">(?:(\s*next\s+value\s+for\s*MYCATSEQ_(\w+))(,|\)|\s)*)+</property> <property name="subqueryRelationshipCheck">false</property> <!-- 子查询中存在关联查询的情况下,检查关联字段中是否有分片字段 .默认 false --> <!-- <property name="useCompression">1</property>--> <!--1为开启mysql压缩协议--> <!-- <property name="fakeMySQLVersion">5.6.20</property>--> <!--设置模拟的MySQL版本号--> <!-- <property name="processorBufferChunk">40960</property> --> <!-- <property name="processors">1</property> <property name="processorExecutor">32</property> --> <!--默认为type 0: DirectByteBufferPool | type 1 ByteBufferArena | type 2 NettyBufferPool --> <property name="processorBufferPoolType">0</property> <!--默认是65535 64K 用于sql解析时最大文本长度 --> <!--<property name="maxStringLiteralLength">65535</property>--> <!--<property name="sequnceHandlerType">0</property>--> <!--<property name="backSocketNoDelay">1</property>--> <!--<property name="frontSocketNoDelay">1</property>--> <!--<property name="processorExecutor">16</property>--> <!-- <property name="serverPort">8066</property> <property name="managerPort">9066</property> <property name="idleTimeout">300000</property> <property name="bindIp">0.0.0.0</property> <property name="frontWriteQueueSize">4096</property> <property name="processors">32</property> --> <!--分布式事务开关,0为不过滤分布式事务,1为过滤分布式事务(如果分布式事务内只涉及全局表,则不过滤),2为不过滤分布式事务,但是记录分布式事务日志--> <property name="handleDistributedTransactions">0</property> <!-- off heap for merge/order/group/limit 1开启 0关闭 --> <property name="useOffHeapForMerge">0</property>
<!-- 单位为m --> <property name="memoryPageSize">64k</property>
<!-- 单位为k --> <property name="spillsFileBufferSize">1k</property>
<property name="useStreamOutput">0</property>
<!-- 单位为m --> <property name="systemReserveMemorySize">384m</property>

<!--是否采用zookeeper协调切换 --> <property name="useZKSwitch">false</property>
<!-- XA Recovery Log日志路径 --> <!--<property name="XARecoveryLogBaseDir">./</property>-->
<!-- XA Recovery Log日志名称 --> <!--<property name="XARecoveryLogBaseName">tmlog</property>--> <!--如果为 true的话 严格遵守隔离级别,不会在仅仅只有select语句的时候在事务中切换连接--> <property name="strictTxIsolation">false</property> <property name="useZKSwitch">true</property> </system> <!-- 全局SQL防火墙设置 --> <!--白名单可以使用通配符%或着*--> <!--例如<host host="127.0.0.*" user="root"/>--> <!--例如<host host="127.0.*" user="root"/>--> <!--例如<host host="127.*" user="root"/>--> <!--例如<host host="1*7.*" user="root"/>--> <!--这些配置情况下对于127.0.0.1都能以root账户登录--> <!-- <firewall> <whitehost> <host host="1*7.0.0.*" user="root"/> </whitehost> <blacklist check="false"> </blacklist> </firewall> --> <!-- 配置应用程序连接 mycat 服务器的账号和密码--> <!-- 请删除defaultAccount="true"--> <user name="root" > <property name="password">123456</property> <property name="schemas">TESTDB</property> <!-- 表级 DML 权限设置 --> <!-- <privileges check="false"> <schema name="TESTDB" dml="0110" > <table name="tb01" dml="0000"></table> <table name="tb02" dml="1111"></table> </schema> </privileges> --> </user>
<user name="user"> <property name="password">user</property> <property name="schemas">TESTDB</property> <property name="readOnly">true</property> </user>
</mycat:server>
复制代码

配置 schema.xml 文件

<?xml version="1.0"?><!DOCTYPE mycat:schema SYSTEM "schema.dtd"><mycat:schema xmlns:mycat="http://io.mycat/">		<!-- schema 代表的是逻辑库,而table代表的是需要显示在该数据库中逻辑表-->	<!-- 逻辑库:表示需要显示给应用程序看的数据库	逻辑表:表示在逻辑库中,用户能看到的表	-->	<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
<!--rule="sharding-by-murmur" 分片规则 sharding-by-murmur Hash一致算法分片 --> <table name="t_order" dataNode="dn1,dn2" primaryKey="id" rule="sharding-by-murmur" /> <!--rule="auto-sharding-long" 范围分片算法 id在 0-500M 在dn1节点上,id在500M-1000M 的在dn2节点上,id在1000M-1500M在dn3节点上 --> <table name="t_goods" dataNode="dn1,dn2,dn3" primaryKey="id" rule="auto-sharding-long"/>
</schema>
<!-- dataNode 的节点,每一个节点都代表一个数据库--> <!--dataHost 如果不是docker环境,请配置IP地址--> <!--database 具体的物理库--> <dataNode name="dn1" dataHost="mysql10" database="db1" /> <dataNode name="dn2" dataHost="mysql11" database="db2" /> <dataNode name="dn3" dataHost="mysql12" database="db3" />
<!-- dataHost 每个单独的数据库节点的详细配置--> <dataHost name="mysql10" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <!--配置写数据的规则--> <!--url="mysql10:3306" 配置ip[容器的名称]:端口 用来mycat向 数据库写入数据--> <!--user="root" password="123456" 用来mycat连接 mysql服务器的账号和密码--> <writeHost host="host1" url="mysql10:3306" user="root" password="123456" /> </dataHost> <!-- dataHost 每个单独的数据库节点的详细配置--> <dataHost name="mysql11" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <!--配置写数据的规则--> <!--url="mysql10:3306" 配置ip[容器的名称]:端口 用来mycat向 数据库写入数据--> <!--user="root" password="123456" 用来mycat连接 mysql服务器的账号和密码--> <writeHost host="host2" url="mysql11:3306" user="root" password="123456" /> </dataHost> <!-- dataHost 每个单独的数据库节点的详细配置--> <dataHost name="mysql12" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <!--配置写数据的规则--> <!--url="mysql10:3306" 配置ip[容器的名称]:端口 用来mycat向 数据库写入数据--> <!--user="root" password="123456" 用来mycat连接 mysql服务器的账号和密码--> <writeHost host="host3" url="mysql12:3306" user="root" password="123456" /> </dataHost>
</mycat:schema>
复制代码

将配置文件上传至/usr/local/mycat 目录下


启动 mycat 容器

9066 为管理端口

8066 为数据端口

docker run --name mycat -d -p 9066:9066 -p 8066:8066 --link mysql10:mysql10 --link mysql11:mysql11 --link mysql12:mysql12 -v /usr/local/mycat/conf:/usr/local/mycat/conf/ fify/mycat:latest--link mysql10:mysql10 链接命令,由于mycat的配置文件中使用到mysql10所以需要链接
复制代码

添加数据,并校验结果

INSERT INTO t_goods (id,name,price,type,address,data) VALUES ('1', '小米9', '3800', '数码产品', '河南', '2019-04-09 00:43:32'); INSERT INTO t_goods (id,name,price,type,address,data) VALUES ('2', '苹果电脑', '15000', '数码产品', '成都', '2019-04-02 00:44:07'); INSERT INTO t_goods (id,name,price,type,address,data) VALUES ('3', '长虹电吹风', '45', '家用电器', '北京', '2019-04-01 00:46:28'); INSERT INTO t_goods (id,name,price,type,address,data) VALUES ('5000000', '苏泊尔电饭锅', '380', '家用电器', '北京', '2019-04-01 00:47:17'); INSERT INTO t_goods (id,name,price,type,address,data) VALUES ('5000001', '火星人集成灶', '18000', '燃气灶具', '武汉', '2019-04-07 00:47:59'); INSERT INTO t_goods (id,name,price,type,address,data) VALUES ('5000002', '蒙牛纯甄', '8','食品', '新疆', '2019-04-07 00:48:50'); INSERT INTO t_goods (id,name,price,type,address,data) VALUES ('10000001', '原味道瓜子', '30', '食品', '成都', '2019-04-07 00:49:25'); INSERT INTO t_goods (id,name,price,type,address,data) VALUES ('10000002', '冷吃兔', '45','食品', '自贡', '2019-04-01 00:49:44'); INSERT INTO t_goods (id,name,price,type,address,data) VALUES ('10000003', '张飞牛肉', '34', '食品', '南充', '2019-04-02 00:50:09'); INSERT INTO t_order (id,order_no,order_time) VALUES(1,'9527','2019-07-28'); INSERT INTO t_order (id,order_no,order_time) VALUES(2,'9528','2019-07-28'); INSERT INTO t_order (id,order_no,order_time) VALUES(5,'9528','2019-08-28'); INSERT INTO t_order (id,order_no,order_time) VALUES(500,'9529','2019-08-28'); 
复制代码

目前 t_goods 表使用的是 mycat 默认的分配策略,也就是根据 id 来进行分片的,1-5000000 被分配到第一张表,5000001-10000000 被分配到第二张表,10000001-15000000 被分配到第三张表。

 

t_order 表使用的是 mycat 哈希一致分配策略,也就是根据 id 的 Hash 值在 Hash 环上顺时针寻找距离最近的服务器节点,然后将数据进行存放

3.5 mycat 工作流程

Mycat 的原理并不复杂,复杂的是代码。Mycat 的原理中最重要的一个动词是“拦截”,它拦截了用户发送过来的 SQL 语句,首先对 SQL 语句做了一些特定的分析:如分片分析、路由分析、读写分离分析、缓存分析等,然后将此 SQL 发往后端的真实数据库,并将返回的结果做适当的处理,最终再返回给用户。

执行的流程为:

Orders 表被分为三个分片 datanode(简称 dn),这三个分片是分布在两台 MySQL Server 上(DataHost),即 datanode=database@datahost 式,因此你可以用一台到 N 台服务器来分片,分片规则为(sharding rule)典型的字符串枚举 分片规则,一个规则的定义是分片字段(sharding column) +分片函数(rule function),这里的 分片字段为 prov 而分片函数为字符串枚举方式。

以 select * from orders where prov=?语句为例,查到 prov=wuhan,按照分片函数,wuhan 返回 dn1,于是 SQL 就发给了 MySQL1,去取 DB1 上的查询结果,并返回给用户。

3.6 整合主从复制

修改 schema.xml 文件,配置主从复制

<?xml version="1.0"?><!DOCTYPE mycat:schema SYSTEM "schema.dtd"><mycat:schema xmlns:mycat="http://io.mycat/">		<!-- schema 代表的是逻辑库,而table代表的是需要显示在该数据库中逻辑表-->	<!-- 逻辑库:表示需要显示给应用程序看的数据库	逻辑表:表示在逻辑库中,用户能看到的表	-->	<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
<!--rule="sharding-by-murmur" 分片规则 sharding-by-murmur Hash一致算法分片 --> <table name="t_order" dataNode="dn1,dn2" primaryKey="id" rule="sharding-by-murmur" /> <!--rule="auto-sharding-long" 范围分片算法 id在 0-500M 在dn1节点上,id在500M-1000M 的在dn2节点上,id在1000M-1500M在dn3节点上 --> <table name="t_goods" dataNode="dn1,dn2,dn3" primaryKey="id" rule="auto-sharding-long"/>
<!--没有使用rule="" 分片规则的表,就是非分片表 --> <table name="t_user" dataNode="dn4" primaryKey="id"/> </schema>
<!-- dataNode 的节点,每一个节点都代表一个数据库--> <!--dataHost 如果不是docker环境,请配置IP地址--> <!--database 具体的物理库--> <dataNode name="dn1" dataHost="mysql10" database="db1" /> <dataNode name="dn2" dataHost="mysql11" database="db2" /> <dataNode name="dn3" dataHost="mysql12" database="db3" /> <!-- 主从复制的节点--> <dataNode name="dn4" dataHost="mysql01" database="woniu" /> <!-- dataHost 每个单独的数据库节点的详细配置--> <dataHost name="mysql10" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <!--配置写数据的规则--> <!--url="mysql10:3306" 配置ip[容器的名称]:端口 用来mycat向 数据库写入数据--> <!--user="root" password="123456" 用来mycat连接 mysql服务器的账号和密码--> <writeHost host="host1" url="mysql10:3306" user="root" password="123456" /> </dataHost> <!-- dataHost 每个单独的数据库节点的详细配置--> <dataHost name="mysql11" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <!--配置写数据的规则--> <!--url="mysql10:3306" 配置ip[容器的名称]:端口 用来mycat向 数据库写入数据--> <!--user="root" password="123456" 用来mycat连接 mysql服务器的账号和密码--> <writeHost host="host2" url="mysql11:3306" user="root" password="123456" /> </dataHost> <!-- dataHost 每个单独的数据库节点的详细配置--> <dataHost name="mysql12" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <!--配置写数据的规则--> <!--url="mysql10:3306" 配置ip[容器的名称]:端口 用来mycat向 数据库写入数据--> <!--user="root" password="123456" 用来mycat连接 mysql服务器的账号和密码--> <writeHost host="host3" url="mysql12:3306" user="root" password="123456" /> </dataHost> <!-- dataHost 每个单独的数据库节点的详细配置--> <!-- balance="1" 表示开启负载均衡,目的是为了:控制从多个从库中,读取数据--> <dataHost name="mysql01" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"> <heartbeat>select user()</heartbeat> <!--配置写数据的规则--> <!--url="mysql10:3306" 配置ip[容器的名称]:端口 用来mycat向 数据库写入数据--> <!--user="root" password="123456" 用来mycat连接 mysql服务器的账号和密码--> <writeHost host="host4" url="mysql01:3306" user="root" password="123456" > <!--配置数据读取规则--> <readHost host="hostS1" url="mysql02:3306" user="root" password="123456" /> <readHost host="hostS2" url="mysql03:3306" user="root" password="123456" /> </writeHost> </dataHost>
</mycat:schema>
复制代码

上传 schema.xml 到/usr/local/mycat/conf 下

开启 mycat,检验结果

docker run --name mycat -d -p 9066:9066 -p 8066:8066 --link mysql01:mysql01 --link mysql02:mysql02 --link mysql03:mysql03 --link mysql10:mysql10 --link mysql11:mysql11 --link mysql12:mysql12 -v /usr/local/mycat/conf:/usr/local/mycat/conf/ fify/mycat:latest
复制代码



发布于: 2021 年 02 月 26 日阅读数: 43
用户头像

831143

关注

还未添加个人签名 2021.02.26 加入

欢迎访问个人网站:feiyu831143.com.cn 一起学习交流

评论

发布
暂无评论
MyCat集成MySQL完成数据库集群建设