Docker搭建Mysql数据库集群
1. 主从复制概述
复制是指将主数据库的DDL 和 DML 操作通过二进制日志传到从库服务器中,然后在从库上对这些日志重新执行(也叫重做),从而使得从库和主库的数据保持同步。
MySQL支持一台主库同时向多台从库进行复制, 从库同时也可以作为其他从服务器的主库,实现链状复制。
1.1 复制原理
MySQL 的主从复制原理如下。
从上层来看,复制分成三步:
-
Master 主库在事务提交时,会把数据变更作为时间 Events 记录在二进制日志文件 Binlog 中。
-
主库推送二进制日志文件 Binlog 中的日志事件到从库的中继日志 Relay Log 。
-
slave重做中继日志中的事件,将改变反映它自己的数据。
1.2复制优势
MySQL 复制的有点主要包含以下三个方面:
-
主库出现问题,可以快速切换到从库提供服务。
-
可以在从库上执行查询操作,从主库中更新,实现读写分离,降低主库的访问压力。
-
可以在从库中执行备份,以避免备份期间影响主库的服务。
1.3 搭建步骤
1.3.1 docker安装mysql
-
首先适用docker 拉去mysql镜像(需要在虚拟机上安装docker,才能适用docker命令)
docker pull mysql
-
查看下载的mysql镜像
docker images
-
然后使用mysql镜像,分别启动两个容器
#Master(主) docker run -d -p 3307:3306 --name mysql_master -e MYSQL_ROOT_PASSWORD=root docker.io/mysql:latest #Slave(从) docker run -d -p 3308:3306 --name mysql_slave -e MYSQL_ROOT_PASSWORD=root docker.io/mysql:latest
Master对外映射的端口是3307,Slave对外映射的端口是3308。因为docker容器是相互独立的,每个容器有其独立的ip,所以不同容器使用相同的端口并不会冲突。这里我们应该尽量使用mysql默认的3306端口,否则可能会出现无法通过ip连接docker容器内mysql的问题
-
查看正在运行的2个mysql容器情况
docker ps
1.3.2 配置Master(主)
docker exec -it mysql_master /bin/bash
通过docker exec -it a6ede3b2a5b9 /bin/bash
命令进入到Master容器内部,也可以通过docker exec -it mysql——master /bin/bash
命令进入。a6ede3b2a5b9 是容器的id,而mysql-master是容器的名称
cd /etc/mysql
切换到/etc/mysql目录下,然后vi my.cnf
对my.cnf进行编辑。
此时会报出bash: vi: command not found
,需要我们在docker容器内部自行安装vim。使用apt-get install vim
命令安装vim
会出现如下问题:
执行apt-get update
,然后再次执行apt-get install vim
即可成功安装vim。然后我们就可以使用vim编辑my.cnf,在my.cnf中添加如下配置:
#mysql 服务ID,保证整个集群环境中唯一 server-id=1 ? #mysql binlog 日志的存储路径和文件名 log-bin=/var/lib/mysql/mysqlbin ? #错误日志,默认已经开启 #log-err ? #mysql的安装目录 #basedir ? #mysql的临时目录 #tmpdir ? #mysql的数据存放目录 #datadir ? #是否只读,1 代表只读, 0 代表读写 read-only=0 ? #忽略的数据, 指不需要同步的数据库 binlog-ignore-db=mysql ? #指定同步的数据库 #binlog-do-db=db01
-
配置完成之后,需要重启mysql服务使配置生效
-
输入service mysql restart 不能识别的话,就退出容器,然后重新启动容器就行
exit;#退出当前容器
docker restart a6ede3b2a5b9 ;#重启master容器
docker exec -it a6ede3b2a5b9 /bin/bash;#进入master容器
-
重新进入mysql,查看master的状态
show master status;
-
下一步在Master数据库创建数据同步用户,授予用户 slave REPLICATION SLAVE权限和REPLICATION CLIENT权限,用于在主从库之间同步数据。
CREATE USER ‘slave‘@‘%‘ IDENTIFIED BY ‘123456‘; GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO ‘slave‘@‘%‘;
到此Master主服务器就搭建成功。
1.3.3 配置Slave(从)
-
上一步已经运行了主、从两台MySQL服务器,现在进入到MySQL从服务器
docker exec -t mysql_slave /bin/bash
-
进入到mysql 的配置文件目录 ,然后
vi my.cnf
对my.cnf进行编辑(可能遇到找不到vim错误,请参考上一步)
cd /etc/mysql
-
配置如下参数
#mysql服务端ID,唯一 server-id=2 #指定binlog日志 log-bin=/var/lib/mysql/mysqlbin
保存并退出配置文件的编辑模式,并重启mysql服务
-
配置主服务器时,检查过master的状态
执行以下命令,配置从服务器,指定当前从库对应的主库的IP地址,用户名,密码,从哪个日志文件开始的那个位置开始同步推送日志。
change master to master_host= ‘172.17.0.2‘, master_user=‘slave‘, master_password=‘123456‘, master_log_file=‘mysqlbin.000001‘, master_log_pos=711;
命令说明:
master_host :Master的地址,指的是容器的独立ip,可以通过
docker inspect --format=‘{{.NetworkSettings.IPAddress}}‘ 容器名称|容器id
查询容器的ipmaster_port:Master的端口号,指的是容器的端口号
master_user:用于数据同步的用户(上一步在主服务器配置的slave用户)
master_password:用于同步的用户的密码(上一步在主服务器配置的password)
master_log_file:指定 Slave 从哪个日志文件开始复制数据,即上文中提到的 File 字段的值
master_log_pos:从哪个 Position 开始读,即上文中提到的 Position 字段的值
master_connect_retry:如果连接失败,重试的时间间隔,单位是秒,默认是60秒
-
开启主从复制过程,并且查看状态
start slave;#开启主从复制 show slave status \G;#查看主从复制状态
Slave_IO_Running 和 Slave_SQL_Running 都是Yes,说明主从复制已经开启。此时可以测试数据同步是否成功
1.3.4 遇到的问题
-
使用docker重启mysql从服务器,
docker ps -a
命令后发现启动失败,然后使用docker logs containerId检查失败原因
从日志中可以看出是我们刚才在配置文件的适合把server-id写成了server_id造成的。
解决方法:
-
方法一:直接修改容器内文件
使用如下命令,获取到容器的元数据中找到对应数据
docker inspect 84335f13e9e2
找到mysql的配置文件的存放位置,往下翻找到如下图位置,其中UpperDir就是存放MySQL配置文件的地方
重新修改配置文件
cd /var/lib/docker/overlay2/818b484734608ddc6f672e125d495bc945d3b51855e87a104b20cf0a0d8f2010/diff cd /etc/mysql vim my.cnf
-
使用命令show slave status \G;后发现Slave_IO_Running= Connecting 和Slave_SQL_Running=Yes
可以参考该博客:https://blog.csdn.net/weixin_39359455/article/details/104220723
1.3.5 验证主从复制
1. 在主库中创建数据库,创建表,并插入数据
create database db01; user db01; create table user( id int(11) not null auto_increment, name varchar(50) not null, sex varchar(1), primary key (id) )engine=innodb default charset=utf8; insert into user(id,name,sex) values(null,‘Tom‘,‘1‘); insert into user(id,name,sex) values(null,‘Trigger‘,‘0‘); insert into user(id,name,sex) values(null,‘Dawn‘,‘1‘);
2. 在从库中查询数据,进行验证 :
-
在从库中,可以查看到刚才创建的数据库:
在该数据库中,查询user表中的数据: