本文要介绍的是使用Docker搭建MySQL主从服务器的过程。
简单来讲,Docker是一种基于Linux的容器技术,它能够实现一个隔离的、安全的、独立的容器环境,在这个容器中我们可以安装各种各种的产品,例如MySQL、Tomcat、Nginx等,并且能够实现秒级启动和关闭。相关的入门介绍可以看这篇文章:https://blog.csdn.net/pbrlovejava/article/details/83098373。
Docker的常用命令:
1、docker ps:查看当前运行的容器
2、docker ps -a:查看全部 容器
3、docker images:查看所有拉取到的镜像
4、docker pull 镜像名:版本号 :拉取docker hub中的镜像,如果不指定镜像名则为最新版本的镜像
5、docker rm 容器名:移除镜像
6、docker search 镜像名:搜索镜像
7、docker rmi 镜像名:删除镜像
8、docker run 镜像名:版本号 :启动镜像作为容器,可以带有以下参数
-p 主机端口:容器端口 ,将主机端口映射到容器的端口
-P 随机端口映射
-d 后台运行
--name 指定容器名
-e 指定运行参数
9、docker exec -it 容器名 /bin/bash :进入容器内部
10、docker inspect 容器名:查看容器详细情况,包括主机内ip地址等
MySQL主从复制的作用:
1、从服务器的数据和主服务器的数据保持一致,当主服务器发生故障时可紧急启用从服务器作为主服务器,确保业务继续正常进行。
2、是读写分离的基础,可用来分担主服务的读压力,使读压力分担到从服务器上,提高数据库读写性能瓶颈。
MySQL主从复制的过程:
1、主服务器提交事务时,将DDL和DML信息记录到主服务器的二进制日志中。
2、从服务器的I/O线程读取到主服务器二进制日志的变化,并开始读取日志数据,将其写到从服务器的中继日志中。
3、从服务器的SQL线程读取到中继日志的变化,将其重放为SQL语句或者是行数据,复制到从服务器中,主从复制完毕,这时主从数据一致。
即将读压力从主服务器中分离到从服务器中,下文中将会介绍,本文不做详细介绍。
本次拉取的是MySQL5.5版本镜像:
docker pull mysql:5.5
启动第一个MySQL镜像容器mysql-master作为主服务器,将本机3305端口映射到容器3306端口,初始ROOT密码为123:
docker run -d -p 3305:3306 --name mysql-master -e MYSQL_ROOT_PASSWORD=123 mysql:5.5
现在启动了一个主服务器容器后,需要进入其中修改配置MySQL的配置文件进行相关的配置:
docker exec -it mysql-master /bin/bash
因为需要修改MySQL的配置文件,所以需要在容器中下载vim工具
apt-get update
apt-get install vim
这里需要配置一下主服务器的相关信息:
vi /etc/mysql/my.cnf
[client]
# 默认字符集utf8
default-character-set=utf8
[mysqld]
# 主服务器id
server-id=1
# 开启二进制日志
log-bin=mysql-master-bin-log
# 将二进制日志写入形式改为ROW
binlog_format=ROW
创建的slave用户用于在之后的从服务器主从配置中读取二进制日志的数据。
# 以ROOT用户登录
mysql -u root -p
# 登陆之后,创建一个slave用户,密码为123,不限制登录域名
create user 'slave'@'%' identified by '123';
# 为slave用户授权
grant replication slave,replication client on *.* to 'slave'@'%';
现在需要记录下主服务器的信息供从服务器配置使用,主要有以下量:
show master status\G;
*************************** 1. row ***************************
File: mysql-master-bin-log.000002 //这就是二进制日志名
Position: 1340 //这是偏移量,也就是从这里开始录入
Binlog_Do_DB:
Binlog_Ignore_DB:
1 row in set (0.00 sec)
docker inspect mysql-master
步骤和之前一样:
# 创建从服务器容器
docker run -d -p 3304:3306 --name mysql-slave-1 -e MYSQL_ROOT_PASSWORD=123 mysql:5.5
# 进入容器
docker exec -it mysql-slave-1 /bin/bash
# 下载vim
apt-get update
apt-get install vim
vi /etc/mysql/my.cnf
-------------------------------
[client]
default-character-set=utf8
[mysqld]
server-id=2
log-bin=mysql-slave-bin-log1
# 开启中继日志,这段一定要配置
relay-log=mysql-slave-relay-log1
change master to
master_host='172.17.0.2',
master_port=3306,
master_user='slave',
master_password='123',
master_log_file='mysql-master-bin-log.000001',
master_log_pos=2,
master_connect_retry=30;
show slave status\G
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: 172.17.0.3
Master_User: slave
Master_Port: 3306
Connect_Retry: 30
Master_Log_File: mysql-master-bin-log.000002
Read_Master_Log_Pos: 1340
Relay_Log_File: mysql-relay-log-bin1.1080635
Relay_Log_Pos: 264
Relay_Master_Log_File: mysql-master-bin-log.000002
Slave_IO_Running: No
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 1340
Relay_Log_Space: 799
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 11
1 row in set (0.00 sec)
start slave;
这时如果顺利的话,主从复制已经开启了,主服务器上的更新会同步到从服务器中。
如果需要更换主服务器的配置,那么需要停止主从复制,并且重置主从信息:
stop slave;
reset slave;
主从复制有时可能存在一些问题:
1、从服务器在复制主服务器数据时某些数据缺失:这个的解决办法一般是调整主服务器的二进制日志记录写入数据的格式,将statement改为row,即以行作为数据记录。
set global binlog_format = row;
如果还是不行,那么尝试从主服务器二进制日志的第一个日志的第一行开始复制,即将所有的DML/DDL操作都复制到从服务器的中继日志中并进行SQL重做。
2、报错说找不到主服务器的二进制日志:确定主服务器的二进制日志已经开启:
show global variables like 'bin_log';
没有开启的话需要在my.cnf中配置,如果不是这个问题,那么在主服务器中使用命令检查二进制日志的名字是否配置正确:
show master status\G
3、主从服务器一些参数调优:
对于主服务器,最好将二进制日志的写入模式改为在事务提交后立即记录到二进制日志中,每秒刷新一次日志数据到磁盘中,这样就不会造成每秒写入数据都立即提交到磁盘中,防止产生大量I/O操作;
set global innodb_flush_log_at_trx_commit=2;
对于从服务器,需要设置relay_log_recovery=1,即当slave从库宕机后,假如relay-log损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的relay-log,并且重新从master上获取日志,这样就保证了relay-log的完整性。
set global relay_log_recovery = 1;