shardingsphere之sharding-proxy读写分离学习笔记
引言
读写分离在业务中应该是比较常见的,当满足以下几点就可以考虑将数据进行读写分离,减轻数据库的压力和提高响应速度。
(1)业务对数据库是读多写少。
(2)单台服务器或者单个数据库的性能已经不能满足当前业务对数据库大量读取请求。
(3)数据量不是特别巨大,单表还没超过五百万行记录,还不需要分库分表。
重要提示
演示环境
- 阿里云ECS服务器,CentOS Linux release 7.7.1908 (Core)
- docker版本:Docker version 19.03.8, build afacb8b
- 本地系统:windows7
版本信息
- spring-boot 2.1.6.RELEASE
- mybatis-plus-generator 3.1.0
- mybatis-plus-boot-starter 3.1.0
- druid-spring-boot-starter 1.1.18
- sharding-proxy 4.0.1
- mysql 8.0.20
代码示例和参考
用于演示的代码和相关的参考链接已经放到文章的末尾。sql文件放置在sql文件夹,请求信息放置在postMan文件夹,导入postman执行即可。
读写分离简介
读写分离主要分为两步,一是设置数据库实现主从复制,二是在代码层面实现增删改操作到主数据库,读的操作到从数据库,提高数据库的响应能力。
主从复制
太多的理论知识就不在这里赘述了,可以参考MYSQL主从复制原理,有兴趣的可以进行深入研究,选择适合自己的解决方案。
主从复制的原理和流程
(1)Master主库将数据变更DataChanges记录 binlog日志中。
(2)Slave起一个I/O线程连接到Master,dump读取Master的binlog日志并写入到Slave的中继日志Relaylog中
(3)Slave中的SQL线程读取中继日志Relaylog进行SQL回放执行操作,完成主从复制,保证主从最终一致性。
sharding-proxy简介
概念
太多的理论知识我就不赘述了,麻烦自己到官网去看。
sharding-jdbc 和 sharding-proxy对比
特点
配置好之后可作为独立的数据源使用,一个逻辑数据库代理着几个真实数据库,可以用客户端软件比如Navicat Premium 直接去连接和操作。很好的帮助我们处理读写分离的问题,基本不需要对现有的业务代码修改,减少时间成本。
使用情况
基础环境的搭建
本文是基于阿里云ECS服务器上的docker搭建数据库的,使用docker安装会比传统的方式效率高很多。
下面会把详细的安装步骤和注意的地方一一列出来。这里演示的是一主三从,一个主库master,三个从库slave0,slave1,slave2。
小插曲
对于mysql的安装,一开始我是选择在windows7下面用docker安装的。在安装docker的时候出现一大堆问题,初始化也很麻烦,搞了一个下午也没搞完。所以我转到阿里云上面安装。当然也可以在windows下使用解压的方式安装mysql,这个就自行谷歌吧。
docker的安装
(1)卸载旧的docker,可选。
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine
(2)安装yum工具类
sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
(3)启用Docker源
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
(4)安装Docker
sudo yum -y install docker-ce
(5)配置国内的Docker仓库,加快Docker镜像下载速度
vim /etc/docker/daemon.json
{
"registry-mirrors" : [
"https://registry.docker-cn.com"
]
}
(6)启动docker
sudo systemctl start docker
(7) 检查是否安装成功,如果出现正常的信息则表示安装成功。
sudo docker info
安装mysql并配置主从复制
拉取mysql镜像
(1)查看mysql镜像版本
可以直接访问 MySQL镜像库地址,直接复制对应的命令即可拉取镜像。
或者使用命令查看
docker search mysql
(2)拉取镜像
docker pull mysql:8.0.20
(3)查看已拉取的镜像
docker images
安装配置master库
(1)运行mysql容器
docker run -itd --name master_3307 -p 3307:3306 -e MYSQL_ROOT_PASSWORD=root mysql:8.0.20
参数介绍
- –name master_3307 表示容器的名称为master_3307
- -p 3307:3306 表示将宿主机的3307端口映射到docker的3306端口
- -e MYSQL_ROOT_PASSWORD=root 表示设置用户root的密码为root
- mysql:8.0.20 表示使用的镜像版本
小插曲
其实一个镜像可以复用安装成多个容器的,一开始我还以为一个镜像只能对应一个容器呢。
(2)检查是否安装成功
docker ps
下图是成功安装了master,slave0,slave1,slave2结果。
简单备注
docker pull mysql:8.0.20 和docker pull mysql:8.0其实拉取的是同一版本的镜像,这个看镜像ID一致即可知道。
(3)修改配置信息
进入容器内部
docker exec -it master_3307 bash
更新基础软件和安装vim
apt-get update
apt-get install vim
编辑配置文件
vi /etc/mysql/my.cnf
新增信息
[mysqld]
## 同一局域网内注意要唯一
server-id=100
## 开启二进制日志功能,可以随便取(关键)
log-bin=mysql-bin
## 永久设置时区时间
default-time_zone = '+8:00'
修改后保存退出编辑
:wq
备注
- 按照上面顺序操作可以避免下方两个提示。
bash: vi: command not found
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package vim
- 配置default-time_zone = ‘+8:00’,不然当datetime类型的默认值为CURRENT_TIMESTAMP时,插入的时间会比系统时间少了8个小时
(4)创建用户并授权,用于在主从库之间同步数据。
进入mysql内部
mysql -uroot -proot
创建同步用户
CREATE USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY 'slave';
授予权限
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
备注
如果本地要用客户端比如Navicat Premium连接,最好设置root的认证方式
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'root';
否则连接可能会报错
2059 - authentication plugin 'caching_sha2_password' cannot be loaded...
(5)查看关键信息
查看两个关键信息,File和Position字段的值后面将会用到,在后面的操作完成之前,需要保证Master库不能做任何操作,否则将会引起状态变化,File和Position字段的值变化。
show master status;
(6)重启容器
退出mysql
exit
退出容器
exit
重启容器
docker restart master_3307
至此,master数据库安装配置完成。
slave数据库安装配置
(1)查看master的容器ip,后面设置会用到
docker inspect --format='{
{.NetworkSettings.IPAddress}}' master_3307
(2)运行容器
docker run -itd --name slave0_3308 -p 3308:3306 -e MYSQL_ROOT_PASSWORD=root mysql:8.0.20
(3)进入容器内部
docker exec -it slave0_3308 bash
(4)安装vim
apt-get update
apt-get install vim
(5)修改配置文件
vi /etc/mysql/my.cnf
(6)新增信息
[mysqld]
## 设置server_id,注意要唯一
server-id=1001
## 开启二进制日志功能,以备Slave作为其它Slave的Master时使用
log-bin=mysql-slave-bin
## relay_log配置中继日志
relay_log=edu-mysql-relay-bin
## 永久设置时区时间
default-time_zone = '+8:00'
(7)设置主从信息
进入mysql内部
mysql -uroot -proot
重要提示:
如果本地要用客户端比如Navicat Premium连接,最好设置root的认证方式
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'root';
设置主从信息
change master to master_host='172.17.0.2', master_user='slave', master_password='slave', master_port=3306, master_log_file='mysql-bin.000001', master_log_pos= 3174, master_connect_retry=30,get_master_public_key=1;
参数介绍
- master_host :Master的地址,指的是容器的独立ip,可以通过下面命令来查看
docker inspect --format='{
{.NetworkSettings.IPAddress}}' 容器名称|容器id查询容器的ip
- master_port:Master的端口号,指的是容器的端口号
- master_user:用于数据同步的用户
- master_password:用于同步的用户的密码
- master_log_file:指定 Slave 从哪个日志文件开始复制数据,即上文中提到的 File 字段的值
- master_log_pos:从哪个 Position 开始读,即上文中提到的 Position 字段的值
- master_connect_retry:如果连接失败,重试的时间间隔,单位是秒,默认是60秒
备注
之所以设置get_master_public_key=1,是因为开启主从复制的时候可能会报出下方的异常。原因是mysql8默认使用插件caching_sha2_password,有些client连接报这个错误,需要拿到server的public key来加密password。
ERROR 2061 (HY000): Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection.
(7)查看主从同步状态
show slave status \G;
正常情况下,SlaveIORunning 和 SlaveSQLRunning 都是No,因为我们还没有开启主从复制过程。
(8)开启主从复制
start slave;
(9)再次查询主从同步状态
show slave status \G;
SlaveIORunning 和 SlaveSQLRunning 都是Yes,说明主从复制已经开启。
(10)重启容器
退出mysql
exit
退出容器
exit
重启容器
docker restart slave0_3308
剩余的slave1_3309,slave2_3310的安装配置方法和salve0_3308的方法是一样的,区别就是cnf文件中的server-id不能相同罢了。
出现异常参考
(1)使用start slave开启主从复制过程后,如果SlaveIORunning一直是Connecting,则说明主从复制一直处于连接状态,这种情况一般是下面几种原因造成的,我们可以根据 Last_IO_Error提示予以排除。
- 网络不通
解决方法:检查ip,端口 - 密码不对
检查是否创建用于同步的用户和用户密码是否正确 - pos不对
检查Master的 Position
(2)如果开启主从复制失败,需要修改和重新启动,可参考下方提示
停止主从复制
stop slave;
重置之前的配置信息
reset slave;
修改信息
change master to ......
启动主从复制
start slave;
备注
如果不重置修改后直接启动可能会报出下方的异常
ERROR 1872 (HY000): Slave failed to initialize relay log info structure from the repository
开放阿里云安全组端口
到阿里云安全组设置那里开放3307,3308,3309,3310端口,无需开放防火墙firewall端口。
使用客户端连接
小插曲
第一次安装好之后开放了安全组端口,可是使用客户端输入公网ip和账号密码死活连接不上,这个也困扰了我很久。后面过了段时间发现设置的安全组规则不见了,直接重新设置就可以连接了,难以费解。
简单测试
在master库创建一个test数据库,如果从库也有则代表安装成功。至此主从复制的工作已经完成,接下来就是代码层面的读写分离了。
开始整合sharding-proxy
(1)其实大部分的工作都是在编写conf目录下的yml文件,配置好之后应用还是跟以前的方式一样连接和操作,基本不需要对代码进行修改。
(2)逻辑数据源可以配置多个,每个yml文件代表一个逻辑数据源,可手动创建yml文件和编写规则实现多个逻辑数据源的使用。
(3)本文演示的是单个逻辑数据源的配置和使用。