MyCat2

本文详细介绍了Mycat2数据库中间件,包括其作为MySQL代理的角色,核心功能如数据分片、读写分离和多数据源整合。讲解了Mycat2与ShardingJDBC的区别,并展示了如何通过Docker部署MySQL主从复制集群以及配置Mycat2实现读写分离。同时,文中还探讨了Mycat2的分库分表策略,如垂直分库、水平分表、ER表和广播表的实现。通过对Mycat2配置文件的解析,读者可以理解其如何管理和优化数据库操作。
摘要由CSDN通过智能技术生成

1.MyCat2概述

1.1 什么是MyCa

官网: http://mycatone.top
Mycat 是基于 java 语言编写的数据库中间件,是一个实现了 MySQL 协议的服务器,前端用户可以把它看作是一个数据库代理,用 MySQL 客户端工具和命令行访问,而其后端可以用 MySQL 原生协议与多个 MySQL 服务器通信,也可以用 JDBC 协议与大多数主流数据库服务器通信,其核心功能是分库分表和读写分离,即将一个大表水平分割为 N 个小表,存储在后端 MySQL 服务器里或者其他数据库里。

MyCat 是基于阿里开源的 Cobar 产品而研发,Cobar 的稳定性、可靠性、优秀的架构和性能以及众多成熟的使用案例使得 MyCat 变得非常的强大。

imagepng

Mycat对于我们Java程序员来说,就是一个近似等于 MySQL 的数据库服务器,你可以用连接 MySQL 的方式去连接 Mycat(除了端口不同,默认的Mycat 端口是 8066 而非MySQL 的 3306,因此需要在连接字符串上增加端口信息)。

1.2 Mycat的作用

1.2.1 数据分片

数据分片包括里:垂直分片和水平分片,垂直分片包括:垂直分库和垂直分表,水平分片包括: 水平分库和水平分表。

1)垂直分库

  • 数据库中不同的表对应着不同的业务,垂直切分是指按照业务的不同将表进行分类,分布到不同的数据库上面
  • 将数据库部署在不同服务器上,从而达到多个服务器共同分摊压力的效果

imagepng

2)垂直分表

表中字段太多且包含大字段的时候,在查询时对数据库的IO、内存会受到影响,同时更新数据时,产生的binlog文件会很大,MySQL在主从同步时也会有延迟的风险。

  • 将一个表按照字段分成多表,每个表存储其中一部分字段。
  • 对职位表进行垂直拆分, 将职位基本信息放在一张表, 将职位描述信息存放在另一张表

imagepng

œ垂直拆分带来的一些提升

  • 解决业务层面的耦合,业务清晰
  • 能对不同业务的数据进行分级管理、维护、监控、扩展等
  • 高并发场景下,垂直分库一定程度的提高访问性能
  • 垂直拆分没有彻底解决单表数据量过大的问题

3) 水平分库

  • 将单张表的数据切分到多个服务器上去,每个服务器具有相应的库与表,只是表中数据集合不同。 水平分库分表能够有效的缓解单机和单库的性能瓶颈和压力,突破IO、连接数、硬件资源等的瓶颈.

    imagepng

    简单讲就是根据表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面, 例如将订单表 按照id是奇数还是偶数, 分别存储在不同的库中。

4) 水平分表

  • 针对数据量巨大的单张表(比如订单表),按照规则把一张表的数据切分到多张表里面去。 但是这些表还是在同一个库中,所以库级别的数据库操作还是有IO瓶颈。

    imagepng

总结

  • 垂直分表: 将一个表按照字段分成多表,每个表存储其中一部分字段。
  • 垂直分库: 根据表的业务不同,分别存放在不同的库中,这些库分别部署在不同的服务器.
  • 水平分库: 把一张表的数据按照一定规则,分配到不同的数据库,每一个库只有这张表的部分数据.
  • 水平分表: 把一张表的数据按照一定规则,分配到同一个数据库的多张表中,每个表只有这个表的部分数据.

1.2.2 读写分离

读写分离指的是:主库负责处理事务性的增删改操作,从库负责处理查询操作,能够有效的避免由数据更新导致的行锁,使得整个系统的查询性能得到极大的改善。

注意: 读写分离的数据节点中的数据内容是一致,所以要先搭建主从复制架构

imagepng

1.2.3 多数据源整合

Java工程里需要同时控制(连接)多个数据源:

  1. 业务需要。比如项目里要实现两个DB的双写/数据迁移,或者微服务边界划分不清使得一个工程直连了多个DB。
  2. 读写分离。大型一点的网站,为了提升DB的吞吐量和性能以及高可用性,数据库一般都会采用集群部署(1个Master+N个Slave模式)。
  3. NoSQL数据库。使用NOSQL数据库存储大量的一次性非业务数据,比如日志类的数据

imagepng

1.3 Mycat与ShardingJDBC的区别

  1. mycat是一个中间件的第三方应用,sharding-jdbc是一个jar包

  2. 使用mycat时不需要修改代码,而使用sharding-jdbc时需要修改代码

  3. Mycat 是基于 Proxy,它复写了 MySQL 协议,将 Mycat Server 伪装成一个 MySQL 数据库,而 Sharding-JDBC 是基于 JDBC 的扩展,是以 jar 包的形式提供轻量级服务的。

  • Mycat(proxy中间件层)

    imagepng

  • Sharding-jdbc(应用层):

    imagepng

1.4 Mycat2新特性

Mycat2的提升:

imagepng

新特性总结

  • 多语句,指的是可以批量执行建表语句
  • 支持blob,blob二进制大对象
  • 全局二级索引,用全局二级索引后,能有效减少全表扫描,对于减少连接使用,减少计算节点与存储节点的数据传输有帮助.
  • 支持任意跨库跨表join查询
  • 支持跨库跨表的关联子查询
  • 支持分库同时分表,把分库分表合一,统一规划
  • 存储过程: 存储过程支持多结果集返回、支持接收affectRow
  • 支持逻辑视图
  • 支持批量插入: 支持rewriteInsertBatchedStatementBatch参数(设置为true),用于提高批量插入性能。
  • 支持执行计划管理:Mycat2的执行计划管理主要作用是管理执行计划,加快SQL到执行计划的转换。
  • 路由注释,Mycat2对于路由注释的支持更加快捷方便,减少繁琐的配置
  • 自动hash分片算法: 由1.6版本的手动配置算法,到2.0的自动hash分
  • 支持第三方工具
  • 单表映射物理表,可以直接将单表映射到物理表,更快速的创建数据库表
  • XA事务,首先数据库要支持XA事务
  • 支持MySQL8

2.环境准备

2.1 准备测试环境

1)搭建两台虚拟机,分别部署MySQL和Mycat2

  • 192.168.58.100服务器上的MySQL要部署到docker中,方便后面我们快速搭建MySQL集群, 并且MySQL的版本使用MySQL8。
  • 192.168.58.200服务器,安装Mycat2之前要安装JDK,并且必须选择JDK1.8 避免出现其他问题。

imagepng

2.2 Docker基本使用

1)安装docker

# 1、yum 包更新到最新 
yum update

# 2、安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的 
yum install -y yum-utils device-mapper-persistent-data lvm2

# 3、 设置yum源
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

# 4、 安装docker,出现输入的界面都按 y 
yum install -y docker-ce

# 5、 查看docker版本,验证是否验证成功
docker -v

2)镜像加速方案

默认情况,将从docker hub(https://hub.docker.com/)下载docker镜像太慢,一般都会配置镜像加速器;

建议配置阿里云镜像加速,编辑该文件:

vim /etc/docker/daemon.json  

在该文件中输入如下内容:

{
   
  "registry-mirrors": ["https://3ad96kxd.mirror.aliyuncs.com"]
}

配置完成记得刷新配置

sudo systemctl daemon-reload
sudo systemctl restart docker

3)镜像相关命令

  • 查看镜像 docker images
  • 搜索镜像 docker search imageName
  • 拉取镜像 docker pull imageName:version
  • 删除镜像 docker rmi imageId rmi–>remove Image

4)查看容器

查看正在运行的容器

docker ps

查看所有容器(查看正在运行的和已经停止运行的)

docker ps –a
docker ps -all

查看最后一次运行的容器

docker ps –l

查看停止的容器

docker ps -f status=exited

5)创建容器命令

docker run 参数 镜像名称:镜像标签 /bin/bash

创建容器常用的参数说明:

-i:表示运行容器,如果不加该参数那么只是通过镜像创建容器,而不启动。

-t:表示容器启动后会进入其命令行。加入这两个参数后,容器创建就能登录进去。即分配一个伪终端(如果只加it两个参数,创建后就会自动进去容器)。

-d:在run后面加上-d参数,则会创建一个守护式容器在后台运行(这样创建容器后不会自动登录容器)。

--name :为创建的容器命名。

-v:表示目录映射关系(前者是宿主机目录,后者是映射到宿主机上的目录),可以使用多个-v做多个目录或文件映射。注意:最好做目录映射,在宿主机上做修改,然后共享到容器上。

-p:表示端口映射,前者是宿主机端口,后者是容器内的映射端口。可以使用多个-p做多个端口映射,例如:可以将Docker中Tomcat容器的8080端口映射到宿主机上的某一个端口8080,那么以后访问tomcat只需要:http://宿主机的IP:8080/

进入容器之后,初始化执行的命令:/bin/bash;可写可不写

6) 删除指定的容器,正在运行的容器无法删除

#删除容器
docker rm 容器名称(容器ID)
#删除镜像
docker rmi 镜像ID(镜像名称)

2.3 Docker部署单机MySQL

  1. 搜索mysql镜像
docker search mysql
  1. 拉取 mysql8 镜像
 docker pull mysql:8.0.29
  1. 使用docker方式创建MySQL服务器

**注意:**如果此时防火墙是开启的,则先关闭防火墙,并重启docker,否则后续安装的MySQL无法启动

#关闭docker
systemctl stop docker

#关闭防火墙
systemctl stop firewalld

#永久关闭
systemctl disable firewalld 

#启动docker
systemctl start docker

在docker中创建并启动MySQL服务器:端口3310

docker run -d \
-p 3310:3306 \
-v /msb/mysql/conf:/etc/mysql/conf.d \
-v /msb/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name msb-mysql \
mysql:8.0.29

参数说明:

  • -p 3310:3306:表示端口映射,前者是宿主机端口,后者是容器内的映射端口,将容器的 3306 端口映射到宿主机的 3310 端口。

  • -v /msb/mysql/conf:/etc/mysql/conf.d: 配置文件映射,前面是宿主机目录,后面是映射到宿主机上的文件,这样就可以在宿主机上做修改,然后共享到容器上

  • -v /msb/mysql/data:/var/lib/mysql :数据文件目录映射,避免容器出现问题,导致数据丢失。

  • -e MYSQL_ROOT_PASSWORD=123456:初始化 root 用户的密码。

  • –name msb-mysql :容器名称

  • mysql:8.0.29 :镜像名称

  1. 进入容器,操作mysql
docker exec –it msb-mysql /bin/bash
  1. 使用Navicat连接容器中的mysql 因为我们做了端口映射,所以连接的是192.168.58.100:3310

3.Mycat2 安装与启动

3.1 制作安装包

Mycat2不提供安装包,只提供核心JAR包,JAR包可以独立运行,安装包是使用Java Service Wrapper做壳的,如果需要安装包,需要自己制作。

JAR可以作为Java库引入自己业务项目中使用,Mycat2中的各个组件的设计都是可以独立使用的

步骤如下:

  1. 下载对应的tar或zip安装包,以及对应的jar包

    zip包地址:http://dl.mycat.io/2.0/install-template/mycat2-install-template-1.20.zip

    jar包地址:http://dl.mycat.io/2.0/1.21-release/mycat2-1.21-release-jar-with-dependencies-2022-3-14.jar

  2. 解压下载下来的zip包, 然后将下载好的jar包放入到 mycat/lib 目录下,如下图:

    imagepng

  3. 上传到Linux,这里我们将MyCat上传到192.168.58.200,这台服务器。Mycat 作为数据库中间件要和数据库部署在不同机器上。

# 授予 bin 目录下所有命令 可执行权限
[root@localhost mycat]# chmod +x bin/*
  1. 安装 JDK1.8
1.查看云端yum库中目前支持安装的jdk软件包
yum search java|grep jdk

2.选择版本安装jdk
yum install -y java-1.8.0-openjdk*

3.安装完成后,验证是否安装成功
java -version


4.查找jdk安装位置
find / -name 'java'

默认安装路径一般为:
/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.151-5.b12.el7_4.x86_64/jre/bin/java

3.2 启动MyCat

1)MyCat需要连接的MySQL数据库中,创建用户,并赋予权限 (也可以直接使用root用户)

-- 修改默认密码校验方式
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';

-- 用户名mycat,密码123456
CREATE USER 'mycat'@'%' IDENTIFIED BY '123456';

-- 官方文档强调要给root账号添加XA RECOVER权限
GRANT XA_RECOVER_ADMIN  ON *.* TO 'root'@'%';

-- 视情况给mycat赋予权限
GRANT ALL PRIVILEGES ON *.* TO 'mycat'@'%' ;
flush privileges;

2)配置mycat要连接的数据源

mycat连接真正数据库的信息目录是在 /mycat/conf/datasources

配置原型库的数据源信息 prototypeDs.datasource.json,  主要是 url、user、password这三个参数

{
   
        "dbType":"mysql",
        "idleTimeout":60000,
        "initSqls":[],
        "initSqlsGetConnection":true,
        "instanceType":"READ_WRITE",
        "maxCon":1000,
        "maxConnectTimeout":3000,
        "maxRetryCount":5,
        "minCon":1,
        "name":"prototypmysql
        "password":"123456",
        "type":"JDBC",
        "url":"jdbc:mysql://192.168.58.100:3310/mysql?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8",
        "user":"mycat",
        "weight":0
}

3)mycat相关命令

进入bin目录

./mycat status 状态
./mycat start 启动
./mycat stop 停止
./mycat restart 重启服务
./mycat pause 暂停

4)Mycat用户配置

文件目录及配置文件

cd /root/software/mycat/conf/users

[root@localhost users]# ll
总用量 4
-rw-r--r--. 1 root root 107 123 04:06 root.user.json

[root@localhost users]# vim root.user.json 

只需要配置用户名,密码

{
   
        "dialect":"mysql",
        "ip":null,
        "password":"123456",  
        "transactionType":"xa",
        "username":"root"
}

5)启动mycat,使用图形工具链接,mycat默认端口8066

imagepng

3.3 连接Mycat

1)连接成功后,创建执行下面的建库建表语句

-- 创建数据库
CREATE DATABASE user_db CHARACTER SET utf8;

-- 创建表
CREATE TABLE users (
  id INT(11) PRIMARY KEY AUTO_INCREMENT,
  NAME VARCHAR(20) DEFAULT NULL,
  age INT(11) DEFAULT NULL
); 

-- 插入数据
INSERT INTO users VALUES(NULL,'user1',20);
INSERT INTO users VALUES(NULL,'user2',21);
INSERT INTO users VALUES(NULL,'user3',22);

2)在Mycat中执行成功,Mycat所代理的数据库中也会增加一个user_db数据库和users表

imagepng

imagepng

mycat.xa_log 是事务日志表会在Mycat2启动时候在存储节点上建立。

mycat.spm_plan mycat执行计划相关的表

4.Mycat2 核心概念

  • 分库分表
    • 按照一定的规则把数据库中的表拆分为多个带有数据库实例,物理库,物理表访问路径的分表。
  • 逻辑库
    • 对数据进行分片之后,从原来的与一个库,被切分为了多个分片数据库,所有的分片数据库构成了整个完整的数据库存储。Mycat在操作时,使用逻辑库代表整个完整的数据库集群,方便对于整个集群进行操作。
  • 物理库
    • MySQL中真实存在的数据库
  • 物理表
    • MySQL中真实存在的表
  • 分片键
    • 用于分片的数据库字段,是将数据库进行水平拆分的关键字段
    • 例:将订单表的订单主键设置为分片键,根据订单主键进行取模分片。
  • 物理分表
    • 指的是已经进行数据拆分的,在数据库上面的物理表,是分片表的一个分区,多个物理分表中的数据汇总起来就是逻辑表的全部数据。
  • 物理分库
    • 一般是指包含多个分表的库,数据切分之后每一个大表被分不到不同的数据库上面,每个表分片所在的数据库就是物理分库。
  • 单表
    • 没有分片,没有数据冗余的表
  • 全局表
    • 变动不频繁
    • 数据总量变化不大
    • 经常被用来进行关联查询
    • 比如说: 地址表 、字典表 这一类都是属于全局表,在每个数据库中都有这样一张或几张全局表,每个数据库中的全局表的数据是要保持一致的。
  • ER表
    • Mycat提出了基于E-R关系的数据分片策略,子表的记录与所有关联的父表的记录存放在同一个数据分片上,子表依赖于父表,通过表分组保证 数据的join不会跨库。
  • 集群
    • 多个数据节点组成的逻辑节点。
  • 数据源
    • 连接后端数据库的组件,它是数据库代理中连接后端数据库的客户端。
  • 原型库
    • 原型库是Mycat2后面的数据库,MySQL

5.Mycat2 核心配置文件

Mycat2作为一个数据库中间件,它所有的功能其实都是通过一些列配置文件定制一系列业务规则,通过与MySQL协作,提供具体的业务功能。所有Mycat2的所有功能都体现在他的配置文件中。

服务相关配置文件所在的目录是: mycat/conf

imagepng

5.1 用户配置

1)配置用户相关信息的目录在: mycat/conf/users

2)命名方式:{用户名}.user.json

3)配置内容如下:

{
   
        "dialect":"mysql",
        "ip":null,
        "password":"123456",
        "transactionType":"xa",
        "username":"root"
}

字段含义
ip:客户端访问ip,建议为空,填写后会对客户端的ip进行限制
username:用户名
password:密码
isolation:设置初始化的事务隔离级别
    READ_UNCOMMITTED :1
    READ_COMMITTED :2
    REPEATED_READ:3,默认
    SERIALIZABLE:4

tractionType:事务类型,可选值, 可以通过语句实现切换
    set transaction policy ='xa'
    set transaction.policy ='proxy'

proxy 表示本地事务,在涉及大于1个数据库的事务, commit阶段失败会导致不一致,但是兼容性最好xa事务,需要确认存储节点集群类型是否支持XA.

5.2 数据源配置

配置Mycat连接的数据源信息
1)所在目录 mycat/conf/datasources 2)命名方式 {数据源名字} . datasource.json 3)配置内容如下:

{
        "dbType":"mysql",
        "idleTimeout":60000,
        "initSqls":[],
        "initSqlsGetConnection":true,
        "instanceType":"READ_WRITE",
        "maxCon":1000,
        "maxConnectTimeout":3000,
        "maxRetryCount":5,
        "minCon":1,
        "name":"prototypeDs",
        "password":"123456",
        "type":"JDBC",
        "url":"jdbc:mysql://192.168.58.100:3310/mysql?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8",
        "user":"mycat",
        "weight":0
}

字段含义
    dbType:数据库类型,mysql
    name:用户名
    password:密码
    type:数据源类型,默认JDBC
    url:访问数据库地址
    idleTimeout:空闲连接超时时间 
    initSqls:初始化sql
    initSqlsGetConnection:对于jdbc每次获取连接是否都执行initSqls
    nstanceType:配置实例只读还是读写, 可选值:READ_WRITE,READ,WRITE
    weight:负载均衡权重

连接相关配置
    "maxCon": 100,
    "maxConnectTimeout" : 3000,
    "RetryCount" : 5,
    "minCon": 1,

5.3 集群配置

1)配置集群信息,所在目录 mycat/conf/clusters 2)命名方式:{集群名字} . cluster.json 3)配置内容如下:

{
   
        "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:普通主从
    JSTER:garela- cluster/PXC 集群
    MHA: MHA集群
    MGR: MGR集群

readBalanceType:查询负载均衡策略,可选值:
    BALANCE_ALL(默认值),获取集群中所有数据源
    BALANCE_ALL_READ,获取集群中允许读的数据源
    BALANCE_READ_WRITE,获取集群中允许读写的数据源,但允许读的数据源优先
    BALANCE_NONE,获取集群中允许写数据源,即主节点中选择

switchType:切换类型

5.4 逻辑库表

1)配置逻辑库表,实现分库分表,所在目录 mycat/conf/schemas 2)命名方式 {库名} . schema.json 3)配置内容如下:

vim mysql.schema.json

{
   
    "customTables":{
   },
    "globalTables":{
   },       //全局表配置
    "normalProcedures":{
   },
    "normalTables":{
      // MySQL中真实表信息
        "users":{
   
      //建表语句
            "createTableSQL":"CREATE TABLE user_db.users (\n\tid INT(11) PRIMARY KEY AUTO_INCREMENT,\n\tNAME VARCHAR(20) DEFAULT NULL,\n\tage INT(11) DEFAULT NULL\n)",
            "locality":{
   
                "schemaName":"user_db",  //物理库
                "tableName":"users",     //物理表
                "targetName":"prototype" //指向集群或者数据源
            }
        }
    },
    "schemaName":"user_db",   
    "shardingTables":{
   }, //分片表配置
    "views":{
   }
}

//详细分库分表配置,后面的内容会有讲解

注意:配置的schema的逻辑库逻辑表必须在原型库(prototype)中有对应的物理库物理表,否则不能启动

6.Mycat2实现读写分离

读写分离原理:读写分离就是让主库处理事务性操作,从库处理select查询。数据库复制被用来把事务性查询导致的数据变更同步到从库,同时主库也可以select查询。

实现读写分离是基于MySQL的主从复制架构的,通过一主多从的配置方式,可以将查询请求均匀的分散到多个数据副本,能够进一步的提升系统的处理能力。 所以这里我们先要搭建一下MySQL的主从复制集群。

imagepng

6.1 Docker搭建MySQL主从复制集群

6.1.1 MySQL主从同步原理

MySQL通过binlog完成主备同步,实现最终一致性。

  • Mysql 中有一种日志叫做 binlog(二进制日志)。这个日志会记录下所有修改了数据库的SQL 语句(insert,update,delete,create/alter/drop table, grant 等等)
  • 主从复制的原理其实就是把主服务器上的 binlog 复制到从服务器上执行一遍,这样从服务器上的数据就和主服务器上的数据相同了。

与主从复制相关的线程有三个

  • 主库上的dump_thread
  • 备库上的io_thread、sql_thread

与主从复制相关的日志有binlog、relaylog

  • binlog: 记录数据库的写入操作,以二进制的形式保存在日志文件;
  • relaylog: Slave 接收 Master 的同步日志,会先放到中继日志 relay log 里, slave 的读操作也会基于 relay log。

imagepng

  1. master将数据改变记录到 二进制日志(bina
  • 9
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值