在实际项目,当访问量大,并发量高或者业务较复杂的时候。为了优化性能,减轻一个主库 mysql 服务的压力,提升用户体验,会考虑分库分表或者主从模式。项目中会存在大量的读写操作,而且读的操作可能会占很大的比例,如果写的同时使用了锁机制,那么会导致查询等待,也就导致查询很慢。为了减少这种情况的发生,可以使用从库来处理读,主库负责写。
主从又分为几种模式
- 一主一从
- 一主多从
- 多主一从
- 多主多从
这里采用一主多从的模式,实现主从数据同步。同步会有时间延迟,最终确保数据一致性。
原理
- master 将变动记录到二进制日志文件 (binary log) 中
- master 主库将二进制日志文件发送给订阅者 slave
- slave 通过 I / O 线程读取日志文件中的内容写到 relay 日志中
- slave 执行 relay 日志中的事件,将数据存储到本地
注意
- 主从服务操作系统版本和位数一致
- 主库和从库 数据库版本要一致
- master 要开启二进制日志
- master 和 slave 的 server_id 在局域网内必须是唯一的
环境
- 虚拟机
- centos7
- docker
- mysql8
机器名字 | 配置 |
---|---|
master-msql | 1 核 2G 20G 硬盘 |
slave1-mysql | 1 核 2G 20G 硬盘 |
slave2-mysql | 1 核 2G 20G 硬盘 |
Note: 为了方便,这里将每个机器重新命名. master 为主库机器 salve1 位从库 1 的机器 slave2 位从库 2 的机器
安装
- 使用 vmware fusion 安装 centos7 过程省略 …
- 联网、修改机器名
vi /etc/sysconfig/network-scripts/ifcfg-ens33 (名字可能会有不同)
修改
ONBOOT=NO
改为
ONBOOT=yes
systemctl restart network
ip addr 查看 ip 或者 ping www.baidu.com(查看是否联网)yum -y install wget && yum -y install vim
hostnamectl set-hostname master-mysql
hostname
slave1-mysql slave2-mysql 执行以上操作
搭建 mysql
- master-mysql
1.1 创建 env 目录
mkdir env
pwd
/root/env
1.2 进入 env 目录 创建 init_docker.sh、start.sh 和 yml 目录
touch init_docker.sh
chmod +x init_docker.sh
touch start.sh
chmod +x start.sh
mkdir yml
cd yml
touch mysql.yml
init_docker.sh
#! /bin/bash
yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install docker-ce docker-ce-cli containerd.io -y
echo "=====>>>>> 启动 docker..." && sleep 1
systemctl start docker
echo "=====>>>>> 启动成功..." && sleep 1
echo "=====>>>>> test docker..." && sleep 1
docker pull hello-world
docker rmi hello-world
echo "=====>>>>> install docker-compose..." && sleep 1
curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
echo "=====>>>>> test docker-compose..." && sleep 1
docker-compose --version
echo "=====>>>>> 安装成功 " && sleep 1
exit
start.sh
#! /bin/bash
# chmod +x ./init_docker.sh
echo "=====>>>>> 开始安装 docker..." && sleep 1 && echo ""
./init_docker.sh
echo "=====>>>>> docker 安装完毕 " && sleep 1
echo "=====>>>>> 准备安装并启动 mysql " && sleep 1 && echo ""
docker-compose -f yml/mysql.yml up -d
sleep 3 && docker ps && echo ""
echo "=====>>>>> mysql 启动成功 "
echo "=====>>>>> 浏览器访问 7880 端口,数据库密码请查询 yml/mysql.yml " && sleep 2
mysql.yml
version: '2'
services:
mysql:
container_name: mysqld
image: mysql:8.0.19
environment:
MYSQL_ROOT_PASSWORD: root
TZ: Asia/Shanghai
command:
--server_id=1
--binlog_format=MIXED
--slow_query_log='ON'
--long_query_time=20
--character-set_server=utf8mb4
--collation-server=utf8mb4_general_ci
ports:
- 3306:3306
volumes:
- /ext/data/mysql:/var/lib/mysql
adminer:
container_name: adminer
image: adminer:4.8.1
restart: always
environment:
ADMINER_DEFAULT_SERVER: 172.17.0.1
ports:
- 7880:8080
1.3 安装
./start.sh
docker 查看
浏览器访问
ip:7880
root / root
1.4 navicat 客户端连接
- slave1-mysql
2.1 创建 env 目录
mkdir env
pwd
/root/env
2.2 进入 env 目录 创建 init_docker.sh、start.sh 和 yml 目录
touch init_docker.sh
chmod +x init_docker.sh
touch start.sh
chmod +x start.sh
mkdir yml
cd yml
touch mysql.yml
init_docker.sh
#! /bin/bash
yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install docker-ce docker-ce-cli containerd.io -y
echo "=====>>>>> 启动 docker..." && sleep 1
systemctl start docker
echo "=====>>>>> 启动成功..." && sleep 1
echo "=====>>>>> test docker..." && sleep 1
docker pull hello-world
docker rmi hello-world
echo "=====>>>>> install docker-compose..." && sleep 1
curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
echo "=====>>>>> test docker-compose..." && sleep 1
docker-compose --version
echo "=====>>>>> 安装成功 " && sleep 1
exit
start.sh
#! /bin/bash
# chmod +x ./init_docker.sh
echo "=====>>>>> 开始安装 docker..." && sleep 1 && echo ""
./init_docker.sh
echo "=====>>>>> docker 安装完毕 " && sleep 1
echo "=====>>>>> 准备安装并启动 mysql " && sleep 1 && echo ""
docker-compose -f yml/mysql.yml up -d
sleep 3 && docker ps && echo ""
echo "=====>>>>> mysql 启动成功 "
echo "=====>>>>> 浏览器访问 7880 端口,数据库密码请查询 yml/mysql.yml " && sleep 2
mysql.yml
version: '2'
services:
mysql:
container_name: mysqld
image: mysql:8.0.19
environment:
MYSQL_ROOT_PASSWORD: root
TZ: Asia/Shanghai
command:
--server_id=1000
--binlog_format=MIXED
--slow_query_log='ON'
--long_query_time=20
--character-set_server=utf8mb4
--collation-server=utf8mb4_general_ci
ports:
- 3306:3306
volumes:
- /ext/data/mysql:/var/lib/mysql
adminer:
container_name: adminer
image: adminer:4.8.1
restart: always
environment:
ADMINER_DEFAULT_SERVER: 172.17.0.1
ports:
- 7880:8080
2.3 安装
./start.sh
docker 查看
浏览器访问
ip:7880
root / root
2.4 navicat 客户端连接
- slave2-mysql
3.1 创建 env 目录
mkdir env
pwd
/root/env
3.2 进入 env 目录 创建 init_docker.sh、start.sh 和 yml 目录
touch init_docker.sh
chmod +x init_docker.sh
touch start.sh
chmod +x start.sh
mkdir yml
cd yml
touch mysql.yml
init_docker.sh
#! /bin/bash
yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install docker-ce docker-ce-cli containerd.io -y
echo "=====>>>>> 启动 docker..." && sleep 1
systemctl start docker
echo "=====>>>>> 启动成功..." && sleep 1
echo "=====>>>>> test docker..." && sleep 1
docker pull hello-world
docker rmi hello-world
echo "=====>>>>> install docker-compose..." && sleep 1
curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
echo "=====>>>>> test docker-compose..." && sleep 1
docker-compose --version
echo "=====>>>>> 安装成功 " && sleep 1
exit
start.sh
#! /bin/bash
# chmod +x ./init_docker.sh
echo "=====>>>>> 开始安装 docker..." && sleep 1 && echo ""
./init_docker.sh
echo "=====>>>>> docker 安装完毕 " && sleep 1
echo "=====>>>>> 准备安装并启动 mysql " && sleep 1 && echo ""
docker-compose -f yml/mysql.yml up -d
sleep 3 && docker ps && echo ""
echo "=====>>>>> mysql 启动成功 "
echo "=====>>>>> 浏览器访问 7880 端口,数据库密码请查询 yml/mysql.yml " && sleep 2
mysql.yml
version: '2'
services:
mysql:
container_name: mysqld
image: mysql:8.0.19
environment:
MYSQL_ROOT_PASSWORD: root
TZ: Asia/Shanghai
command:
--server_id=2000
--binlog_format=MIXED
--slow_query_log='ON'
--long_query_time=20
--character-set_server=utf8mb4
--collation-server=utf8mb4_general_ci
ports:
- 3306:3306
volumes:
- /ext/data/mysql:/var/lib/mysql
adminer:
container_name: adminer
image: adminer:4.8.1
restart: always
environment:
ADMINER_DEFAULT_SERVER: 172.17.0.1
ports:
- 7880:8080
3.3 安装
./start.sh
docker 查看
浏览器访问
ip:7880
root / root
3.4 navicat 客户端连接
主从搭建
- 使用客户端连接 slave1-mysql
set global sync_binlog=0;
set global innodb_flush_log_at_trx_commit = 2;
CHANGE MASTER TO
MASTER_HOST='172.16.129.135', // 修改成主库真实内网 ip
MASTER_PORT=3306,
MASTER_USER='root',
MASTER_PASSWORD='root',// 修改成主库真实密码
MASTER_LOG_FILE='binlog.000001',
MASTER_LOG_POS=155
for channel '01'; // 通道编号
start slave;
show slave STATUS;
docker restart mysqld
看到 Slave_IO_Running 和 Slave_SQL_Running 为 yes 说明成功
去主库创建 test 库,创建 user 表,添加数据,刷新 slave1-mysql 从库即可发现已同步
- 使用客户端连接 slave2-mysql
set global sync_binlog=0;
set global innodb_flush_log_at_trx_commit = 2;
CHANGE MASTER TO
MASTER_HOST='172.16.129.135', // 修改成主库真实内网 ip
MASTER_PORT=3306,
MASTER_USER='root',
MASTER_PASSWORD='root',// 修改成主库真实密码
MASTER_LOG_FILE='binlog.000001',
MASTER_LOG_POS=155
for channel '02'; // 通道编号
start slave;
show slave STATUS;
docker restart mysqld
看到 Slave_IO_Running 和 Slave_SQL_Running 为 yes 说明成功
刷新即可看到刚才创建的 test 库已同步
mysql 主从卡住问题
STOP slave for channel '01';
show slave STATUS;
set global sql_slave_skip_counter=1;
start slave for channel '01';
nysql 主从延迟问题
-- 设置同步状态 # 重启之后 重新设置
set global sync_binlog=0;
-- 设置同步 flush
set global innodb_flush_log_at_trx_commit = 2;