[MySQL]-Mycat2&Atlas

[MySQL]-Mycat2&Atlas

liangsen | 2023年3月

本文主要介绍分库分表的基本概念、优缺点,以及常用的数据库分库分表中间件:Mycat2和Atlas。

文章目录

  • [MySQL]-Mycat2&Atlas
  • 一、分库分表
    • 1.1 数据库读写分离
    • 1.2 数据库垂直分库
    • 1.3 数据库水平分库与分表
    • 1.4 怎么选择:垂直?OR 水平?
    • 1.5 缺点?
    • 1.6 常见数据库中间件
  • 二、Mycat2
    • 2.1 原理
    • 2.2 概念
    • 2.3 安装
    • 2.4 配置文件
    • 2.5 启动
    • 2.6 权限
    • 2.7 实例:单实例分表
  • 三、Atlas
    • 3.1 安装
    • 3.2 配置
    • 3.3 管理
    • 3.4 主要功能
    • 3.5 分片策略
  • 四、总结


一、分库分表

我们想一个问题,为什么要对于数据库进行分库分表?我们不妨分析下数据库架构的演变:

1.1 数据库读写分离

我们试想,随着业务的扩展,用户越来越多,数据增长速度越来越快,数据库压力越来越大,对数据库而言,读操作的频率远大于写操作,读操作带来的压力成为了数据库的瓶颈,这时候首先会采取数据库读写分离技术,来提升业务系统的读性能。将数据库分为主从库,主库用于写数据,多个从库用于完成读数据。但是在高并发的情况下,主从库之间的数据同步时存在一定的延迟的。

1.2 数据库垂直分库

我们继续思考,在数据库数据急剧增加的情况下,数据库仍是整个系统的瓶颈。例如电商系统中的用户、商品、订单等等模块,放在一个库中不仅十分臃肿,且难以维护,这时候我们不妨将一些根本互不相关、彼此独立的数据,分别放在不同的数据库中,这样可以将压力分散开来,且提高了系统的吞吐量。

1.3 数据库水平分库与分表

再继续去看,是不是有时候仍会面临单表的数据量庞大,极大的影响的SQL的执行性能,在高并发的查询场景下,性能十分低下,此时,我们可以将原有数据库水平分成多个数据库,再将表记录分布存储在不同的数据库节点上,这种方式我们称为水平分库分表。

1.4 怎么选择:垂直?OR 水平?

垂直分:表数量多造成海量数据,各个业务逻辑划分明确、耦合度低。

水平分:表数据少,但单表数据大造成海量数据。

1.5 缺点?

以上讲述的其实都是分库分表带来的优点,下面一起来看下其缺点:

  • 分布式事务
  • 跨库join
  • 结果集合并、排序
  • 数据迁移扩容的问题

这里对这些不做过多的阐述,我们主要介绍工具的使用及对比。

1.6 常见数据库中间件

[MySQL]-Mycat2&Atlas_第1张图片

二、Mycat2

官网:http://mycatone.top/

仓库地址:
https://github.com/MyCATApache/Mycat2
https://gitee.com/MycatOne/Mycat2

Mycat是由阿里团队基于Cobar进行的二次开发,Mycat2相对于Mycat1.6使用更加便捷,配置更加方便。

2.1 原理

Mycat的原理其实是“拦截”,拦截用户发送的SQL请求,做特定分析后转发给后端真实的数据库,并将结果做适当处理后再返回给用户。

[MySQL]-Mycat2&Atlas_第2张图片

更多:数据源映射关系。

2.2 概念

这里主要介绍一些常见的概念:

  • 逻辑库:数据库代理中的数据库,可包含多个逻辑表。
  • 逻辑表:数据库代理中的表,它可以映射代理连接的数据库中的表。
  • 物理库:数据库代理连接的真实数据库。
  • 物理表:数据库代理连接的真实表。
  • 拆分键:分片键,描述拆分逻辑表的数据规则的字段。
  • 物理分表:指已经进行数据拆分的,在数据库上面的物理表,是分片表的一个分区。
  • 物理分库:包含多个物理分表的库。
  • 分片表:按照一定规则把数据拆分成多个分区的表,在分库分表语境下,属于逻辑表的一种。
  • 全局表、广播表:每个数据库实例都冗余全量数据的逻辑表。
  • ER表:狭义,指父子表的字表,它的分片键指向父表的分片键,且两表的分片算法相同;广义,具有相同数据分布的一组表。
  • 集群:多个数据节点组成的逻辑节点,在mycat2中,把多个数据源地址视为一个数据源地址,并提供自动故障恢复,转移,即实现高可用,负载均衡。

2.3 安装

注意:mycat需要java1.8环境,请提前准备好。

# 1、下载模板
wget http://dl.mycat.org.cn/2.0/install-template/mycat2-install-template-1.21.zip
# 2、下载jar包
wget http://dl.mycat.org.cn/2.0/1.21-release/mycat2-1.21-release-jar-with-dependencies-2022-5-9.jar
# 3、解压模板,将jar放至模板的 lib目录下
unzip mycat2-install-template-1.21.zip
mv mycat2-1.21-release-jar-with-dependencies-2022-5-9.jar ./mycat
# 4、添加权限
chmod 777 ./bin/mycat
chomd 777 ./bin/wrapper-linux-*
# 5、安装java
yum install java-1.8.0-openjdk
# 6、JAVA环境变量设置
JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.181-3.b13.el7_5.x86_64
JRE_HOME=$JAVA_HOME/jre
CLASS_PATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
export JAVA_HOME JRE_HOME CLASS_PATH PATH

mycat2有一款自己的UI工具,本质是java的一个jar包:
下载链接:http://dl.mycat.org.cn/2.0/ui/

本地有JAVA环境,直接双击jar包就可以打开

[MySQL]-Mycat2&Atlas_第3张图片

[MySQL]-Mycat2&Atlas_第4张图片

看着上去UI比较简陋,但不影响我们的使用。

2.4 配置文件

目录如下:

[MySQL]-Mycat2&Atlas_第5张图片

  • server.json,服务器默认配置,不用更改。

在mycat2中,cluster、datasources、schemas、users有了各自的文件夹,其内的文件名称形式:{cluster/datasources/schemas/users}.{cluster/datasources/schemas/users}.josn,且可通过mycat在线输入命令进行更改,不用再像mycat1.6提前进行配置。

在启动Mycat之前我们需要设置一个数据源:

vim ./conf/datasources/prototypeDs.datasource.json

[MySQL]-Mycat2&Atlas_第6张图片

2.5 启动

是的,初始配置很简单,只要你的机器有一套JAVA1.8环境、一套MySQL以及mycat及相关的权限设置好,下面我们来看一下mycat的管理:

cd mycat/bin
./mycat start
./mycat status
./mycat start 启动
./mycat stop 停止
./mycat console 前台运行
./mycat restart 重启服务
./mycat pause 暂停
./mycat status 查看启动状态

eg:
前台运行成功如下:

[MySQL]-Mycat2&Atlas_第7张图片

登录查看,mycat的端口为8066:

[MySQL]-Mycat2&Atlas_第8张图片

你会发现是不是和我们普通的mysql没有什么区别看上去。

2.6 权限

mycat的初始账户密码为:root/123456

想要修改,可在 ./conf/users/root.user.json中进行:

[MySQL]-Mycat2&Atlas_第9张图片

看到这里,我们会发现对于mycat2 的配置其实很简单,初始的启动我们只设置了一个数据源就OK了,其次就是mycat的账户密码,可以自行设置。

下面我们简单举两个实例让大家体会下mycat2分库分表。

2.7 实例:单实例分表

还记得我们在启动mycat前设置了一个数据源了嘛,我们可以使用mysql客户端进行查询:

/*+ mycat:showDataSources{} */;

[MySQL]-Mycat2&Atlas_第10张图片

在这里我们就对这个数据库进行分库分表的实战。

假设背景,现有如下表:

#客户表 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)
);

注意:以下操作均是在Mycat客户端上进行的,不需要在数据源操作。

step1:创建逻辑库

create database eg1;

在这里插入图片描述

可以在conf/schemas中看到,自动生成了eg1.schema.json。

在这里插入图片描述

step2:创建orders表(分库分表),插入数据,进行查询

#在 Mycat 终端直接运行建表语句进行数据分片
CREATE TABLE eg1.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 10 dbpartitions 5;

最下面这句话的意思是,以customer_id 为分片键,采取MOD_HASH分片策略,分5个库,每个库10个表。

分片效果如下:

[MySQL]-Mycat2&Atlas_第11张图片

[MySQL]-Mycat2&Atlas_第12张图片

插入数据,进行查询

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);

[MySQL]-Mycat2&Atlas_第13张图片

step3:创建orders_detail表,插入数据,进行查询

CREATE TABLE orders_detail(
`id` BIGINT NOT NULL AUTO_INCREMENT,
detail VARCHAR(2000),
order_id INT,
PRIMARY KEY(id)
)ENGINE=INNODB DEFAULT CHARSET=utf8
dbpartition BY mod_hash(order_id) tbpartition BY mod_hash(order_id)
tbpartitions 10 dbpartitions 5;

同样在上述的5个分库中,每个库创建10个订单详情表,效果如下:

[MySQL]-Mycat2&Atlas_第14张图片

插入数据,进行查询

INSERT INTO orders_detail(id,detail,order_id) VALUES(1,'detail1',1);
INSERT INTO orders_detail(id,detail,order_id) VALUES(2,'detail1',2);
INSERT INTO orders_detail(id,detail,order_id) VALUES(3,'detail1',3);
INSERT INTO orders_detail(id,detail,order_id) VALUES(4,'detail1',4);
INSERT INTO orders_detail(id,detail,order_id) VALUES(5,'detail1',5);
INSERT INTO orders_detail(id,detail,order_id) VALUES(6,'detail1',6);

[MySQL]-Mycat2&Atlas_第15张图片

step4:查看ER关系

  1. mycat2无需指定ER表,是自动识别的,具体看分片算法的接口

  2. 查看配置的表是否具有ER关系,使用/*+ mycat:showErGroup{}*/查看,结果:

[MySQL]-Mycat2&Atlas_第16张图片

  1. group_id 表示相同的组,该组中的表具有相同的存储分布

  2. 且 mycat2在涉及这两个表的join分片字段等价关系的时候可以完成join的下推,结果:

[MySQL]-Mycat2&Atlas_第17张图片

三、Atlas

GitHub:https://github.com/Qihoo360/Atlas

Atlas是由Qihoo 360,Web平台基础架构图队维护的一个基于MySQL协议的数据库中间件,是在mysql-proxy 0.8.2版本之上的优化。

名字来源:在希腊神话中,阿特拉斯是支撑天球的原始泰坦。他还是天文学和航海学的巨人。

话不多说,开搞直接。

3.1 安装

wget https://github.com/Qihoo360/Atlas/releases/download/2.2.1/Atlas-2.2.1.el6.x86_64.rpm
rpm -ivh ./Atlas-2.2.1.el6.x86_64.rpm 

成功如下:

在这里插入图片描述

3.2 配置

# 1、进入配置目录
cd /usr/local/mysql-proxy/conf
# 2、将test.cnf 备份一下,防止出错
mv ./test.cnf ./test.cnf.bak
# 3、我们可以利用Atlas提供的密码加密功能,后面会用到我们加密的密码
/usr/local/mysql-proxy/bin/encrypt your_password
# 4、编辑配置文件
vim ./test.cnf

[mysql-proxy]
# Atlasd的工作IP和端口
proxy-address = 0.0.0.0:33060
# Atlasd的管理IP和端口
admin-address = 0.0.0.0:2345
# 默认字符集
charset=utf8
# 允许登录管理接口的用户名
admin-username = user
# 管理接口的密码
admin-password = pwd
# 主库的IP和端口号,可设置多个,使用逗号分隔
proxy-backend-addresses = master_host:3306
# 从库的IP和端口号,可设置多个,使用逗号分隔
proxy-read-only-backend-addresses = slave_host:3306
# 允许登录工作接口的用户名与其对应的加密后的密码
pwds = root:ljFlIKX3mx5KsA0UOm9vDA==
# 是否已守护线程运行
daemon = true
# 开启监控进程和工作进程
keepalive = true
# 工作线程数
event-threads = 8
# 日志记录级别
log-level = message
# 日志存放路径
log-path = /usr/local/mysql-proxy/log
# SQL日志开关
sql-log=ON

3.3 管理

cd /usr/local/mysql-proxy/bin
./mysql-proxyd test start   # 开启
./mysql-proxyd test status  # 查看状态
./mysql-proxyd test stop    # 关闭
./mysql-proxyd test restart # 重启
# 登录Atlas的管理端口
mysql -uuser -ppwd -P 2345 -h127.0.0.1

[MySQL]-Mycat2&Atlas_第18张图片

3.4 主要功能

  • 读写分离
  • 负载平衡和故障切换处理
  • IP过滤
  • 数据分片
  • DBA可以顺利地使后端数据库服务器在线或离线
  • 自动删除出现故障的数据库服务器
  • 在不停机的情况下重新加载配置文件

VS mysql-prox

  • 用C重写所有lua代码,lua仅用于管理接口
  • 重新网络模型和线程模型
  • 实现连接池
  • 优化锁机构,性能大幅提升

3.5 分片策略

[MySQL]-Mycat2&Atlas_第19张图片

在Altas中,将数据库可以分为多个组,一个组由一台master,0个或多个slave组成,组之间数据相互独立。

在命中某个组后,会存在组内的读写分离,master负责写,slave负责读。

shardrule: 一个shardrule对应一个分表规则,不同的shardrule通过下划线后面的数字区分。

  1. Rang 方式

根据数据的范围(范围大小不需要相同)进行切分,例如,可以将share key 范围在 0-999的数据存放在Group-0 ,范围在1000-1999的数据放在Group-1中。range是静态的,不支持动态增加范围。

举个栗子:

[shardrule-0]
table = test.sharding_test
type = range
shard-key = id
groups = 0:0-1000,1:1000-1999
  1. Hash 方式

使用取模的方式实现Hash。

举个栗子:

[shardrule-1]
table = test.sharding_hash
type = hash
shard-key = id
groups = 0,1

四、总结

Atlas:不能实现分布式分表,所有的子表必须在同一台DB的同一个database里且所有的子表必须事先建好,Atlas没有自动建表的功能。最新的一次维护已经是4年前了。

Mycat2:配置相对简单,国内开源,最近的一次维护是11个月前。

你可能感兴趣的:(mysql,数据库,java,中间件)