Docke综合实践——搭建MySQL主从集群
在学习之前,我们需要先了解:docker compose build批量构建镜像的方式docker-compose.yml:build:用于docker compose构建镜像context:指定dockerfile文件的路径,默认寻找构建镜像dockerfile:显示指定文件的名称args:配置中arg的参数(中,必须配置有对应的参数)Dockerfile:dockerfile2:1.2 构建并
文章目录
一、基础知识讲解
1 、docker compose build构建镜像
在学习之前,我们需要先了解:docker compose build批量构建镜像的方式
1.1 目录结构
tree -L 3
compose_build/ # 项目根目录
├── docker-compose.yml # (239B) 定义了 mynginx 和 mynginx2 两个服务
├── mynginx/ # 第一个服务的构建上下文
│ └── Dockerfile # 默认Dockerfile命名,基础 Nginx 构建
└── mynginx2/ # 第二个服务的构建上下文
└── dockerfile2 # 自定义Dockerfile命名
小提示:
tree是一个查看目录的好用的linux工具,需要下载;- -L是指定显示层级,后面填入需要显示的最大目录层数;
docker-compose.yml:
services:
mynginx: #服务1
image: mytest_build_image:v1.0 指定镜像名称和tag
build: ./mynginx #指定./mynginx目录下的dockerfile构建镜像
mynginx2: #服务2
image: mytest_build_image:v2.0
build: #指定./mynginx2下的dockerfile2(自定义dockerfile文件)构建镜像
context: ./mynginx2
dockerfile: dockerfile2
args:
- NGINX_VERSION=latest
- build:用于docker compose构建镜像
- context:指定dockerfile文件的路径,默认寻找
Dockerfile构建镜像 - dockerfile:显示指定
Dockerfile文件的名称 - args:配置
Dockerfile中arg的参数(Dockerfile中,必须配置有对应的参数)
- context:指定dockerfile文件的路径,默认寻找
Dockerfile:
FROM nginx:latest
RUN echo "hello hyy_blog" > /usr/share/nginx/html/index.html
dockerfile2:
ARG NGINX_VERSION=1.39.1
FROM nginx:${NGINX_VERSION}
RUN echo "hello hyy_blog" > /usr/share/nginx/html/index.html
1.2 构建并查看效果
docker compose build --build-arg NGINX_VERSION=1.27.1
#两个镜像已经构建完成:
docker images *mytest*
REPOSITORY TAG IMAGE ID CREATED SIZE
mytest_build_image v2.0 a4ed32c9e956 11 minutes ago 188MB
mytest_build_image v1.0 70ebf586176e 28 minutes ago 161MB
2、MySQL同步方式
2.1 MySQL主从同步架构

binlog
一种二进制文件,主库发生变化,会把变更记录根据时间顺序写入到这里,后续binlog dump线程会读取这些数据,将其发送给从节点,实现数据同步
binlog dump thread
当从库与主库进行连接时,主库会为每一个从库创建binlog dump thread,负责把binlog中的变更数据同步给从库
IO thread
与主库进行通信,将主库发来的binlog数据传递给relay log
relay log
中继日志,存储从IO thread获取的变更日志,等待被SQL thread 读取并重放
SQL thread
根据relay log中的数据,按顺序重新执行一遍,以确保和主库数据一致(即重放)
2.2 MySQL主从同步类型
2.2.1 全同步(数据一致,但性能低)

-
同步流程:主结点需要等待从节点落表后,发送ACK,才能把数据返回给客户端;
-
优点::主从节点数据一致性最强;
-
缺点::由于需要等待从节点落表并且返回ACK,性能会极大地降低;
2.2.2 异步同步(性能高,但数据一致性差)
MySQL默认采取这种异步同步策略
- 流程: 异步同步相比于全同步,只负责把binlog发送给从节点,后续从节点是否接收到不关系,直接返回数据给客户端
- 优点: 性能比全同步好很多,因为不用等待从节点ACK
- 缺点: 数据一致性降低
- 原因: 对于异步同步,主库和从库存在一个更新的时间差,若主库发送binlog之前挂掉,那么后续从库无法获取到原主库的最新信息(binlog没有发过来)
2.2.3 半同步(性能折中,存在幻读问题)
基于传统异步存在的缺陷,mysql 在 5.5 版本推出半同步复制。可以说时异步同步的改进版本

- 流程: 主库更新
binlog后,保存事务(写入硬盘),同时发送新的binlog给从库,等待从库relaylog成功后的ACK,返回数据给客户端; - 优点: 一定程度缓解数据不一致的问题(需要从节点的
relaylog成功后的ACK),性能比半同步稍差,但比全同步强很多; - 缺点: 性能比异步同步要差,且存在幻读问题
- 幻读原因: 半同步中,提交存储引擎和发送binlog是并发执行的,可能存在这样一个情况:数据已经存储,但是binlog还没有发送给从结点。
别的用户请求主结点时,查询数据已经修改了,但是此时主结点一旦挂掉,由于从节点没有更新binlog数据,从结点充当主结点,别的用户再查询主结点数据数据,发现数据又没了;
- 幻读原因: 半同步中,提交存储引擎和发送binlog是并发执行的,可能存在这样一个情况:数据已经存储,但是binlog还没有发送给从结点。
2.2.4 增强半同步

- 流程: 与半同步类似,不过增强半同步在主结点写入binlog和,
提交存储引擎和发送binlog不在并发执行(避免别的客户督导未同步的数据,进而解决幻读问题),而是等待从节点relaylog ACK后才进行提交存储引擎(硬盘IO); - 优点: 相较于半同步,解决了幻读问题的产生;
- 缺点: 由于
提交存储引擎和发送binlog不在并发执行,性能相较于半同步会低一些;
2.3 MySQL主从形式

3、编排搭建MySQL主从集群
3.0 构建目标
单台服务器,搭建一主二从的MySQL集群,定义绑定卷,不设置网络(默认bridge网络)
3.1 项目路径
tree -L 2
.
├── docker-compose.yml
├── master
│ ├── Dockerfile-master
│ └── master.sql
└── slave
├── Dockerfile-slave
└── slave.sql
3.2 docker-compose.yml
services:
mysql-master:
build:
context: ./ #指定查看Dockerfile文件的路径./默认是项目当前目录(docker-compose.yml的目录)
dockerfile: ./master/Dockerfile-master #指定Dockerfile文件名称
image: mysqlmaster:v1.0 #指定镜像名称:版本
restart: always
container_name: mysql-master
volumes:
- ./mastervarlib:/var/lib/mysql #挂载mysql的数据库数据,类型是绑定卷
ports:
- 9036:3306
environment:
MYSQL_ROOT_PASSWORD: root #指定mysql密码
privileged: true
# 这里的 command 会让 mysql 启动时直接应用这些配置
command: ['--server-id=1', #集群中,需要指定每一个mysql实例的id,每个实例id不能相同
'--log-bin=master-bin', #开启binlog,相当于开启了数据同步
'--binlog-ignore-db=mysql', # 指定mysql这个数据库不要进行同步,因为这个数据库存储了用户、权限等当前实例的重要信息
'--binlog_cache_size=256M', # 指定binlog大小
'--binlog_format=mixed', #binlog日志记录方式为混合模式
'--lower_case_table_names=1', # 声明数据库表明都是小写
'--character-set-server=utf8',#字符集指定utf8
'--collation-server=utf8_general_ci',]
mysql-slave:
build:
context: .
dockerfile: ./slave/Dockerfile-slave
image: mysqlslave:v1.0
restart: always
container_name: mysql-slave
volumes:
- ./slavevarlib:/var/lib/mysql
ports:
- 9037:3306
environment:
MYSQL_ROOT_PASSWORD: root
privileged: true
command: ['--server-id=2',
'--log-bin=master-bin',
'--relay_log=slave-relay', # 开启relay_log,从节点接收主结点binlog日志
'--lower_case_table_names=1',
'--character-set-server=utf8',
'--collation-server=utf8_general_ci',]
depends_on:
- mysql-master
mysql-slave2:
build:
context: .
dockerfile: ./slave/Dockerfile-slave
image: mysqlslave:v1.0
container_name: mysql-slave2
restart: always
volumes:
- ./slavevarlib2:/var/lib/mysql
ports:
- 9038:3306
environment:
- MYSQL_ROOT_PASSWORD=root
privileged: true
depends_on:
- mysql-master
关于 binlog_format:
binlog_format 表示记录 binlog 的方式,主要有三种:
1、Row(基于行)—— 生产环境首选/官方默认
- 原理:不记录 SQL 原文,只记录“具体哪行数据变成了什么样”。例如一条
UPDATE影响了 1000 行,就记录 1000 行最终的二进制数据变化。- 优点:绝对精准。无论使用什么复杂或随机函数,主从数据 100% 一致。
- 缺点:日志量巨大。批量改库时极度消耗磁盘空间和网络带宽。
2、Statement(基于语句)
- 原理:原封不动地记录主库执行过的 SQL 语句。
- 优点:日志极小。节省磁盘 I/O 和带宽,且日志肉眼可读性极强。
- 缺点:易致数据不一致。遇到动态函数(如
NOW()、UUID())或触发器时,从库执行的时间点不同,生成的数据就会错乱。3、Mixed(混合模式)
- 原理:智能折中方案。平时默认用 Statement 模式省空间,一旦检测到 SQL 中包含
NOW()等不确定函数,立刻自动切换成 Row 模式记录最终数据。- 优点:兼顾了执行效率与数据一致性。
- 缺点:日志格式频繁动态切换,黑盒感较强,增加了后期排查问题和数据恢复的审计难度。
3.3 master
Dockerfile-master:
FROM mysql:5.7
# 设置时区(软连接,减少空间占用
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
# 初始化数据库
COPY ./master/master.sql /docker-entrypoint-initdb.d
master.sql:
-- 1. 创建用户(这里不用定义,镜像已经创建好了的)
-- CREATE USER 'root'@'%' IDENTIFIED BY 'root';
-- 2. 授予主从复制相关权限
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'root'@'%';
-- 3. 刷新权限使之立即生效
FLUSH PRIVILEGES;
3.4 slave
Dockerfile-slave:
#和master一样
FROM mysql:5.7
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
COPY ./slave/slave.sql ./docker-entrypoint-initdb.d
slave.sql:
-- 配置主库的连接信息
CHANGE MASTER TO
MASTER_HOST='mysql-master',
MASTER_USER='root',
MASTER_PASSWORD='root',
MASTER_PORT=3306;
-- 启动从库复制链路
START SLAVE;
3.5 构建镜像/启动服务
docker compose build
docker compose up -d
docker ps
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c8669ac2eaa1 mysqlslave:v1.0 "docker-entrypoint.s…" 45 minutes ago Up 45 minutes 33060/tcp, 0.0.0.0:9038->3306/tcp, [::]:9038->3306/tcp mysql-slave2
f59405cc37f2 mysqlslave:v1.0 "docker-entrypoint.s…" 45 minutes ago Up 45 minutes 33060/tcp, 0.0.0.0:9037->3306/tcp, [::]:9037->3306/tcp mysql-slave
16fa37069d45 mysqlmaster:v1.0 "docker-entrypoint.s…" 45 minutes ago Up 45 minutes 33060/tcp, 0.0.0.0:9036->3306/tcp, [::]:9036->3306/tcp mysql-master
3.6 查看从属关系
查看主结点状态
docker exec -it mysql-master bash
bash-4.2# mysql -u root -h 127.0.0.1 -proot
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.7.44-log MySQL Community Server (GPL)
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show master status;
+-------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| master-bin.000005 | 154 | | mysql | |
+-------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
查看从节点状态
docker exec -it mysql-slave bash
bash-4.2# mysql -u root -h 127.0.0.1 -proot
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.7.44-log MySQL Community Server (GPL)
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show slave status;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: mysql-master < 重点,默认是bridge网络,域名就是主结点容器名:mysql-master
Master_User: root
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master-bin.000005
Read_Master_Log_Pos: 154
Relay_Log_File: slave-relay.000010
Relay_Log_Pos: 369
Relay_Master_Log_File: master-bin.000005
Slave_IO_Running: Yes # <--- 重点
Slave_SQL_Running: Yes # <--- 重点
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: 154
Relay_Log_Space: 739
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: 0 # <--- 重点
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: 1
Master_UUID: 7036d065-18fc-11f1-80a0-ce66da72fc8a
Master_Info_File: /var/lib/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:

更多推荐

所有评论(0)