海量数据存储解决方案之分库分表原理解析及mycat安装及使用_已经存在大量数据 可以使用mycat分表吗_踩踩踩从踩的博客-CSDN博客
Mycat核心概念工作原理及高级特性分析_mycat-mini-monitor_踩踩踩从踩的博客-CSDN博客
前言
在之前的文章中,介绍了一部分的mycat,这些数据访问中间键,我们了解原理,对于数据中间键不具备的某些功能进行扩展,首先要明确,;在现实开发过程中,面对复杂的业务问题已经够头疼了,我相信大家都不愿意在花太多时间应对技术复杂,也就是为什么在公司中都有成熟技术中间件选型用来解决开发中分库分表数据访问的问题,其他都修修补补罢了;这篇文章介绍的mycat,也是国内吧,很多公司都比较喜欢使用的数据访问中间件,但是不要以为这个就是全部,你们上网一搜其实还有很多的,成熟的生态,是我们考虑中间键很重要的原因,并不是说技术多厉害多厉害,国内的大部分公司还是强调的是业务,毕竟生存嘛,废话不多说,继续今天的mycat。
mycat的基本介绍
Mycat 是什么?从定义和分类来看,它是一个开源的分布式数据库系统,是一个实现了 MySQL 协议的Server,前端用户可以把它看作是一个数据库代理,用 MySQL 客户端工具和命令行访问,而其后端可以用MySQL 原生(Native) 协议与多个 MySQL 服务器通信,也可以用 JDBC 协议与大多数主流数据库服务器通信,其核心功能是分表分库,即将一个大表水平分割为 N 个小表,存储在后端 MySQL 服务器里或者其他数据库里。
Mycat 发展到目前的版本,已经不是一个单纯的 MySQL 代理了,它的后端可以支持 MySQL、 SQL Server、Oracle、 DB2、 PostgreSQL 等主流数据库,也支持 MongoDB 这种新型 NoSQL 方式的存储,未来还会支持更多类型的存储。而在最终用户看来,无论是那种存储方式,在 Mycat 里,都是一个传统的数据库表,支持标准的SQL 语句进行数据的操作,这样一来,对前端业务系统来说,可以大幅降低开发难度,提升开发速度,在测试阶段,可以将一个表定义为任何一种 Mycat 支持的存储方式,比如 MySQL 的 MyASIM 表、内存表、或者MongoDB、 LevelDB 以及号称是世界上最快的内存数据库 MemSQL 上。试想一下,用户表存放在 MemSQL 上,大量读频率远超过写频率的数据如订单的快照数据存放于 InnoDB 中,一些日志数据存放于 MongoDB 中,而且还能把 Oracle 的表跟 MySQL 的表做关联查询,你是否有一种不能呼吸的感觉?而未来,还能通过 Mycat 自动将一些计算分析后的数据灌入到 Hadoop 中,并能用 Mycat+Storm/Spark Stream 引擎做大规模数据分析,看到这里,你大概明白了, Mycat 是什么? Mycat 就是 BigSQL, Big Data On SQL Database。
很多人看到上面的描述之后,可能还是比较懵逼,不知道mycat到底是个啥,下面我们来详细讲解下对于不同的角色,mycat到底是个啥?
对于**DBA**而言,可以这么理解mycat:
Mycat就是MySQL Server,而Mycat后面连接的MySQL Server,就好像是MySQL的存储引擎,如InnoDB,MyISAM等,因此,Mycat本身并不存储数据,数据是再后端的MySQL上存储的,因此数据可靠性以及事务都是MySQL保证的,简单说,Mycat就是MySQL最佳伴侣,它再一定程度上让MySQL拥有了能跟Oracle PK的能力。
对于软件工程师来说,可以这么理解mycat:
Mycat就是一个近似等于MySQL的数据库服务器,你可以用连接MySQL的方式去连接Mycat,除了端口不同,默认的mycat端口是8066而不是mysql的3306,因此需要再连接字符串上增加端口信息,大多数情况下,可以用你熟悉的对象映射框架使用mycat,但建议对于分片表,尽量使用基础的SQL语句,因为这样能达到最佳性能,特别是几千万甚至几百亿条记录的情况下。
mycat的原理
mycat的原理并不复杂,复杂的是代码,如果代码也不复杂,那么早就成为了一个传说了。
mycat的原理中最重要的一个动作是“拦截”,它拦截了用户发送过来的SQL语句,首先对SQL语句做了一些特定的分析:如分片分析、路由分析、读写分离分析、缓存分析等,然后将此SQL发送后端的真实数据库,并将返回的结果做适当的处理,最终再返回给用户。
上述图片里,orders表被分为了三个分片datanode(简称dn),这三个分片是分布在两台MySQL Server上(Datahost),即datanode=database@datahost方式,因此你可以用一台到N台服务器来分片,分片规则为(sharding rule)典型的字符串枚举分片规则,一个规则的定义是分片字段(sharding column)+分片函数(rule function),这里的分片字段为prov而分片函数为字符串枚举方式。
当mycat收到一个SQL时,会先解析这个SQL,查找涉及到的表,然后看此表的定义,如果有分片规则,则获取到SQL里分片字段的值,并分配分片函数,得到该SQL对应的分片列表,然后将SQL发往这些分片去执行,最后收集和处理所有分片返回的结果数据,并输出到客户端,以select * from orders where prov = ?语句为例,查到prov=wuhan,按照分片函数,wuhan返回dn1,于是sql就发给了mysql1,去取db1上的查询结果,并返回给用户。
应用场景
mycat发展到现在,使用的场景已经很丰富,而且不断有新用户给出新的创新性的方案,以下是典型的应用场景:
1、单纯的读写分离,此时配置最为简单,支持读写分离,主从切换
2、分库分表,对于超过1000万的表进行分片,最大支持1000亿的单表分片
3、多租户应用,每个应用一个库,但应用程序只连接mycat,从而不改造程序本身,实现多租户化
4、报表系统,借助mycat的分表能力,处理大规模报表的统计
5、整合多数据源
6、作为海量数据实时查询的一种简单有效方案,比如100亿条频繁查询的记录需要在3秒内查询出来结果,除了基于主键的查询,还可能存在范围查询或其他属性查询,此时mycat可能是最简单有效的选择
7、数据库路由器,mycat基于mysql实例的连接池复用机制,可以让每一个应用最大程度地共享一个mysql实例地所有连接池,让数据库地并发访问能力大大提升
为什么使用mycat
1、java与数据库紧耦合
2、高访问量高并发对数据库的压力
3、读写请求数据不一致
数据库中间件对比
mycat的核心概念
mycat是数据库中间件,就是介于数据库与应用之间,进行数据处理和交互的中间服务。从原有的一个库,被切分为多个分片数据库,所有的分片数据库集群构成了整个完整的数据库存储。
逻辑库
对于实际应用而言,其实并不需要知道中间件的存在,开发人员只需要知道数据库的概念即可,所以数据库中间件可以被看作是一个或多个数据库集群构成的逻辑库。
在云计算时代,数据库中间件可以以多租户的形式给一个或多个应用提供服务,每个应用访问的可能是一个独立或者共享的物理库,常见的如阿里云数据库服务器RDS
逻辑表
既然有逻辑库,那么就应该有逻辑表,在分布式数据库中,对应用来说,读写数据的表就是逻辑表。逻辑表可以使数据切分后,分步在一个或多个分片库中,也可以不做数据切分,不分片,只有一个表构成
分片表
分片表,是指哪些原有的很大数据的表,需要切分到多个数据库的表,这样每一个分片都会有一部分数据,所有分片构成了完整的数据。
非分片表
一个数据库中并不是所有的表都很大,某些表是可以不用进行切分的,非分片是相对分片表来说的,就是那些不需要进行数据切分的表。
ER表
关系型数据库是基于实体关系模型之上,通过其描述了真实世界中事物与关系,mycat中的ER表既是来源于此。根据这一思路,提出了基于ER关系的数据分片策略,子表的记录与所关联的父表记录存放在同一个数据分片上,即子类依赖于父类,通过表分组保证数据join不会跨库操作。表分组是解决跨分片数据join的一种很好的思路,也是数据切分规划的重要一条规则。
全局表
一个真实的业务系统中,往往存在大量的类似字典表的表,这些表基本上很少变动,字典表具有以下几个特点:
1、变动不频繁
2、数据量总体变化不大
3、数据规模不大,很少有超过数十万条记录
对于这类的表,在分片的情况下,当业务表因为规模而进行分片以后,业务表与这些附属的字典表之间的关联,就成了比较棘手的问题,所以mycat中通过数据冗余来解决这类表的join,即所有的分片都有一份数据的拷贝,所有将字典表或者符合字典表特性的一些表定义为全局表。
数据冗余是解决跨分片数据join的一种很好思路,也是数据切分规划的另外一条重要原则
分片节点(dataNode)
数据切分后,一个大表被分到不同的分片数据库上面,每个表分片所在的数据库就是分片节点(dataNode)
节点主机(dataHost)
数据切分后,每个分片节点(dataNode)不一定都会独占一台机器,同一机器上面可以有多个分片数据库,这样一个或多个分片节点(dataNode)所在的机器就是节点主机(dataHost),为了规避单节点主机并发数限制,尽量将读写压力高的分片节点(dataNode)均衡的放在不同的节点主机(dataHost)。
分片规则
数据切分是指一个大表被分成若干个分片表,就需要一定的规则,这样按照某种规则把数据分到某个分片的规则就是分片规则,数据切分选择合适的分片规则非常重要,将极大的避免后续数据处理的难度。
全局序列号
数据切分后,原有的关系数据库中的主键约束在分布式条件下将无法使用,因此需要引入外部机制保证数据唯一性标识,这种保证全局性的数据唯一标识的机制就是全局序列号。
多租户
多租户技术或称多重租赁技术,是一种软件架构技术,它是在探讨与实现如何于多用户的环境下共用相同的系统或程序组件,并且扔可确保各用户间数据的隔离性。在云计算时代,多租户技术在共用的数据中心以单一系统架构与服务提供多数客户端相同甚至可定制化的服务,并且仍然可以保障客户的数据隔离。目前各种各样的云计算服务就是这类技术范畴,例如阿里云数据库服务(RDS),阿里云服务器等等。
mycat的安装及使用
mycat的安装
从官网下载需要的安装包,并且上传到具体的虚拟机中,
下载地址为:http://dl.mycat.org.cn/1.6.7.5/2020-4-10/
解压文件到/usr/local文件夹下
tar -zxvf Mycat-server-1.6.7.5-release-20200422133810-linux.tar.gz -C /usr/local
配置环境变量
vi /etc/profile
添加如下配置信息:
export MYCAT_HOME=/usr/local/mycat
export PATH=$MYCAT_HOME/bin:$PATH:$JAVA_HOME/bin
当执行到这步的时候,其实就可以启动了,但是为了能正确显示出效果,最好修改下mycat的具体配置,让我们能够正常进行访问。
配置mycat
进入到/usr/local/mycat/conf目录下,修改该文件夹下的配置文件
修改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/">
<user name="root" defaultAccount="true">
<property name="password">123456</property>
<property name="schemas">TESTDB</property>
<property name="defaultSchema">TESTDB</property>
</user>
</mycat:server>
修改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" dataNode="dn1">
</schema>
<dataNode name="dn1" dataHost="host1" database="msb" />
<dataHost name="host1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.85.111:3306" user="root"
password="123456">
<readHost host="hostS1" url="192.168.85.112:3306" user="root" password="123456"></readHost>
</writeHost>
</dataHost>
</mycat:schema>
启动mycat
mycat的启动有两种方式,一种是控制台启动,一种是后台启动,在初学的时候建议大家使用控制台启动的方式,当配置文件写错之后,可以方便的看到错误,及时修改,但是在生产环境中,使用后台启动的方式比较稳妥。
控制台启动:去mycat/bin目录下执行 ./mycat console
后台启动:去mycat/bin目录下执行 ./mycat start
按照如上配置在安装的时候应该不会报错,如果出现错误,根据错误的提示解决即可。
登录验证
从另外的虚拟机去登录访问当前mycat,输入如下命令即可
mysql -uroot -p123456 -P 9066 -h 192.168.85.111
此时访问的是mycat的管理窗口,可以通过show @@help查看可以执行的命令
数据窗口的登录
从另外的虚拟机去登录访问mycat,输入命令如下:
mysql -uroot -p123456 -P8066 -h 192.168.85.111
当都能够成功的时候以为着mycat已经搭建完成。
读写分离
通过mycat和mysql的主从复制配合搭建数据库的读写分离,可以实现mysql的高可用性,下面我们来搭建mysql的读写分离。
一主一从
在node01上修改/etc/my.cnf的文件
yaml
#mysql服务唯一id,不同的mysql服务必须拥有全局唯一的id
server-id=1
#启动二进制日期
log-bin=mysql-bin
#设置不要复制的数据库
binlog-ignore-db=mysql
binlog-ignore-db=information-schema
#设置需要复制的数据库
binlog-do-db=msb
#设置binlog的格式
binlog_format=statement
在node02上修改/etc/my.cnf文件
`yaml
#服务器唯一id
server-id=2
#启动中继日志
relay-log=mysql-relay
重新启动mysql服务
在node01上创建账户并授权slave
```sql
grant replication slave on *.* to 'root'@'%' identified by '123456';
--在进行授权的时候,如果提示密码的问题,把密码验证取消
set global validate_password_policy=0;
set global validate_password_length=1;
```
查看master的状态
```
show master status
```
在node02上配置需要复制的主机
```
CHANGE MASTER TO MASTER_HOST='192.168.85.111',MASTER_USER='root',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=437;
```
启动从服务器复制功能
```
start slave;
```
查看从服务器状态
```
show slave status\G
```
当执行完成之后,会看到两个关键的属性Slave_IO_Running,Slave_SQL_Running,当这两个属性都是yes的时候,表示主从复制已经准备好了,可以进行具体的操作了
双主双从
在上述的一主一从的架构设计中,很容易出现单点的问题,所以我们要想让生产环境中的配置足够稳定,可以配置双主双从,解决单点的问题。
此架构中,可以让一台主机用来处理所有写请求,此时,它的从机和备机,以及备机的从机复制所有读请求,当主机宕机之后,另一台主机负责写请求,两台主机互为备机。
主机分布如下:
| 编号 | 角色 | ip | 主机名 |
| ---- | ------- | -------------- | ------ |
| 1 | master1 | 192.168.85.111 | node01 |
| 2 | slave1 | 192.168.85.112 | node02 |
| 3 | master2 | 192.168.85.113 | node03 |
| 4 | slave2 | 192.168.85.114 | node04 |
修改node01上的/etc/my.cnf文件
`yaml
#主服务器唯一ID
server-id=1
#启用二进制日志
log-bin=mysql-bin
# 设置不要复制的数据库(可设置多个)
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
#设置需要复制的数据库
binlog-do-db=msb
#设置logbin格式
binlog_format=STATEMENT
# 在作为从数据库的时候, 有写入操作也要更新二进制日志文件
log-slave-updates
#表示自增长字段每次递增的量,指自增字段的起始值,其默认值是1, 取值范围是1 .. 65535
auto-increment-increment=2
# 表示自增长字段从哪个数开始,指字段一次递增多少,他的取值范围是1 .. 65535
auto-increment-offset=1
修改node03上的/etc/my.cnf文件
```yaml
#主服务器唯一ID
server-id=3
#启用二进制日志
log-bin=mysql-bin
# 设置不要复制的数据库(可设置多个)
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
#设置需要复制的数据库
binlog-do-db=msb
#设置logbin格式
binlog_format=STATEMENT
# 在作为从数据库的时候,有写入操作也要更新二进制日志文件
log-slave-updates
#表示自增长字段每次递增的量,指自增字段的起始值,其默认值是1,取值范围是1 .. 65535
auto-increment-increment=2
# 表示自增长字段从哪个数开始,指字段一次递增多少,他的取值范围是1 .. 65535
auto-increment-offset=2
修改node02上的/etc/my.cnf文件
```yaml
#从服务器唯一ID
server-id=2
#启用中继日志
relay-log=mysql-relay
```
修改node04上的/etc/my.cnf文件
```yaml
#从服务器唯一ID
server-id=4
#启用中继日志
relay-log=mysql-relay
```
所有主机重新启动mysql服务
在两台主机node01,node03上授权同步命令
```sql
GRANT REPLICATION SLAVE ON *.* TO 'root'@'%' IDENTIFIED BY '123456';
```
查看两台主机的状态
```sql
show master status;
```
在node02上执行要复制的主机
```sql
CHANGE MASTER TO MASTER_HOST='192.168.85.111',MASTER_USER='root',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=154;
```
在node04上执行要复制的主机
```sql
CHANGE MASTER TO MASTER_HOST='192.168.85.113',MASTER_USER='root',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=154;
```
启动两个从机的slave并且查看状态,当看到两个参数都是yes的时候表示成功
```sql
start slave;
show slave status;
```
完成node01跟node03的相互复制
```sql
--在node01上执行
CHANGE MASTER TO MASTER_HOST='192.168.85.113',MASTER_USER='root',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=442;
--开启slave
start slave
--查看状态
show slave status\G
--在node03上执行
CHANGE MASTER TO MASTER_HOST='192.168.85.111',MASTER_USER='root',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000002',MASTER_LOG_POS=442;
--开启slave
start slave
--查看状态
show slave status\G
```
这篇文章只是做了个大概,可以看看我之前的文章 包括rule规则的配置等等,其实这种中间键,大家配置一次就知道怎么做了。