springboot 多数据源配合 docker 部署 mysql 主从实现读写分离 (1)
1、使用 docker 部署 mysql 主从 实现主从复制
2、springboot 项目多数据源配置,实现读写分离
一、使用 docker 部署 mysql 主从 实现主从复制
**此次使用的是 windo
ws 版本 docker,mysql 版本是 5.7**
1、使用 docker 获取 mysql 镜像
docker pull mysql:5.7.23 #拉取镜像文件
docker images #查看镜像文件
2、使用 docker 运行 mysql master
docker run --name mysql-master --privileged=true -v F:\dockerV\mysql:/var/lib/mysql -p 3307:3306 -e MYSQL_ROOT_PASSWORD=654321 -d mysql:5.7.23
--name 容器名称 mysql-master
--privileged 指定了当前容器是否真正的具有 root 权限,所谓的 root 权限是指具有宿主机的 root 权限,而不仅仅只是在容器内部有 root 权限
-v 将系统的 F:\dockerV\mysql 挂载到容器的/var/lib/mysql,注意是将宿主机 挂载到 容器内部,而不是将容器内部挂载到宿主机
-p 表示宿主机上的某个端口映射到 docker 容器内的某个端口,这里也就是将宿主机的 3307 端口映射到容器内部的 3306 端口
-e 表示指定当前容器运行的环境变量,该变量一般在容器内部程序的配置文件中使用,而在外部运行容器指定该参数。这里的 MYSQL_ROOT_PASSWORD 表示容器内部的 MySQL 的启动密码
-d 后台运行,镜像文件为 mysql:5.7.23
接下来进入容器内部,修改配置,使其作为 mysql master 运行
docker exec -it mysql-master bash #进入容器内部
配置 mysql master,修改 mysql.cnf
使用 vim 修改 mysql.cnf,没有安装 vim 会提示 bash: vi: command not found 则需要安装 vim
apt-get install vim
apt-get update
apt-get install vim
vim mysqld.cnf #修改cnf文件,添加 server-id 表示master服务标识,同一局域网内注意要唯一 和 log-bin=mysql-bin 开启二进制日志功能,可以随便取,用来完成主从复制
修改完成 mysql 的配置后,需要重启服务生效
service MySQL restart # 重启mysql服务时会使得docker容器停止,我们还需要docker start mysql-master启动容器
docker start mysql-master #启动容器
连接 mysql 客户端,创建用来完成主从复制的账号
mysql -uroot -p654321 #连接mysql
为从服务器创建一个可以用来操作 master 服务器的账户,也就是创建一个专门用来复制 binlog 的账号,并且赋予该账号复制权限,其命令如下
grant replication slave on *.* to 'slaveaccount'@'%' identified by '654321'; #账号slaveaccount 密码654321
flush privileges; #刷新用户权限表
show master status #查看mysql master的状态
记录下上的 position 和 file 在创建 MySQL slave 配置时会用到
到这里 mysql master 已经配置完成了
3、使用 docker 运行 mysql slave
docker run --name mysql-slave --privileged=true -v F:\dockerV\mysql-slave:/var/lib/mysql -p 3308:3306 --link mysql-master:master -e MYSQL_ROOT_PASSWORD=654321 -d mysql:5.7.23
mysql slave 的参数主要和 master 有两点不同
所映射的宿主机的端口号不能与 master 容器相同,因为其已经被 master 容器占用;
必须加上--link 参数,其后指定了当前容器所要连接的容器,mysql-master 表示所要连接的容器的名称,master 表示为该容器起的一个别名,通俗来讲,就是 slave 容器通过这两个名称都可以访问到 master 容器。这么做的原因在于,如果 master 与 slave 不在同一个 docker network 中,那么这两个容器相互之间是没法访问的。
docker exec -it mysql-slave /bin/bash #进入mysql salve容器
vim mysqld.cnf #修改cnf文件,添加 server-id 表示slave服务标识,如果此salve需要作为其他mysql的主,那么就需要配置log-bin=mysql-bin
service MySQL restart # 重启mysql服务时会使得docker容器停止,我们还需要docker start mysql-slave启动容器
docker start mysql-master #启动容器
mysql -uroot -proot #连接mysql服务
配置 mysql slave 使其以 slave 模式运行
change master to master_host='172.17.0.2', master_user='slaveaccount', master_password='654321', master_port=3306, master_log_file='mysql-bin.000001', master_log_pos=2272, master_connect_retry=30;
注意:这一步主要在 slave 是配置 master 的信息,包括 master 的 地址、端口、账号、密码、log 文件、log 文件偏移量、重试。下面介绍这些参数值从何获取
获取 master_host,使用 docker inspect mysql-master 查看 master 容器元数据。其中 IPAdress 是 master_host
获取 master_port,是运行 master 映射容器内部的端口,这里就是 3306
获取 master_user 和 master_password,是第一步中在 master 中创建的 slave 账号
获取 master_log_file 和 master_log_pos,是配置 master 中最后一步使用 show master status 获取的文件和偏移量
获取 master_connect_retry,是 slave 重试连接 master 动作前的休眠时间,单位 s,默认 60s
start slave; #以slave模式运行
show salve status \G; #查看slave的状态
可以看到,Slave_IO_Running:YES 和 Slave_SQL_Running:YES 证明此时主从复制已经就绪,slave 配置到此完成
4、验证主从复制效果
这里我们在连接 master,并创建一张表,添加数据,在从库查看数据是否同步。
在主库创建数据,并在从库查看数据是否同步成功。
mysql> create database test;
Query OK, 1 row affected (0.01 sec)
mysql> use test;
Database changed
mysql> create table t_user(id bigint, name varchar(255));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into t_user(id, name) value (1, 'cgg');
Query OK, 1 row affected (0.01 sec)
mysql> select * from test.t_user;
+------+------+
| id | name |
+------+------+
| 1 | cgg |
+------+------+
1 row in set (0.00 sec)
5、mysql 主从复制原理
主库 db 的更新事件(update、insert、delete)被写到 binlog
主库创建一个 binlog dump thread,把 binlog 的内容发送到从库
从库启动并发起连接,连接到主库
从库启动之后,创建一个 I/O 线程,读取主库传过来的 binlog 内容并写入到 relay log
从库启动之后,创建一个 SQL 线程,从 relay log 里面读取内容,从 Exec_Master_Log_Pos 位置开始执行读取到的更新事件,将更新内容写入到 slave 的 db
二、springboot 项目多数据源配置,实现读写分离
1、主从多数据源配置
yml 配置
server:
port: 8888
servlet:
encoding:
charset: UTF-8
force: true
enabled: true
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://127.0.0.1:3307/test?serverTimezone=GMT%2B8&characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false&useSSL=false
username: root
password: 654321
slave:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://127.0.0.1:3308/test?serverTimezone=GMT%2B8&characterEncoding=utf-8&autoReconnect=true&failOverReadOnly=false&useSSL=false
username: root
password: 654321
数据源配置
/**
@author cgg
**/
@Configuration
@EnableTransactionManagement
public class DynamicDataSourceConfig {
@Bean(name = "slaveDatasource")
@ConfigurationProperties(prefix = "slave.datasource")
public DataSource dbSlave() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "dataSource")
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dbMaster() {
return DruidDataSourceBuilder.create().build();
}
@Bean
@Primary
public DataSource multipleDataSource(@Qualifier("dataSource") DataSource db,
@Qualifier("slaveDatasource") DataSource slaveDatasource) {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
Map<Object, Object> targetDataSources = new HashMap<>(16);
targetDataSources.put("dataSource", db);
targetDataSources.put("slaveDatasource", slaveDatasource);
dynamicDataSource.setTargetDataSources(targetDataSources);
//设置默认数据源为从库,如果写操作业务多,可以默认设置为主库
dynamicDataSource.setDefaultTargetDataSource(slaveDatasource);
return dynamicDataSource;
}
@Bean("sqlSessionFactory")
评论