docker搭建mysql主从集群

发布于:2025-06-28 ⋅ 阅读:(15) ⋅ 点赞:(0)

MySQL主从同步原理

主从同步通过主库(Master)记录变更日志,从库(Slave)读取并重放日志实现数据复制,保障数据冗余和高可用性。

主从架构示意

表格:MySQL主从复制组件及作用

组件 作用
Binary Log 主库记录所有数据变更的日志,是主从同步的核心。
I/O线程 从库的线程,负责从主库获取Binary Log并写入Relay Log。
SQL线程 从库的线程,负责读取Relay Log并执行其中的SQL语句。
Relay Log 从库本地存储主库Binary Log的中间日志,用于SQL线程重放。

MySQL主从复制流程

  1. 主节点MySQL接收到数据变更时,将事务写入Binary Log。
  2. Binary Log通过多线程机制被读取并发送到从节点。
  3. 从节点的I/O线程接收Binary Log内容,写入本地Relay Log。
  4. 从节点的SQL线程读取Relay Log中的SQL语句并执行,最终将数据变更应用到从节点MySQL。

主从同步方式对比

同步方式 原理 优点 缺点
异步复制 (Asynchronous) 主库提交事务后立即返回,不等待从库确认 性能高,延迟低 从库可能滞后,数据一致性较差
半同步复制 (Semi-Synchronous) 主库提交事务后,至少等待一个从库确认接收日志 数据一致性更好 性能略有下降
全同步复制 (Synchronous) 主库提交事务后,等待所有从库确认接收日志 数据一致性最好 性能较低
增强半同步复制 (Rising-Semi-Sync) 对半同步复制的改进,原理类似,主要解决幻读问题 数据一致性更好,解决幻读问题 性能略有下降

部署:

编辑Master目录下的Dockerfile:

FROM mysql:5.7.36
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 

编辑slave目录下的Dockerfile:

FROM mysql:5.7.36
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;

在主目录mysql下创建docker-compose.yml文件进行编辑:

name: mysql

services:
  mysql-master:
    build:
      context: ./
      dockerfile: ./master/Dockerfile
    image: mysqlmaster:1.0
    restart: always
    container_name: mysql-master
    volumes:
      - ./mastervarlib:/var/lib/mysql
    ports:
      - 8080:3306
    environment:
      MYSQL_ROOT_PASSWORD: root
    privileged: true
    command: ['--server-id=1',
      '--log-bin=master-bin',
      '--binlog-ignore-db=mysql',
      '--binlog_cache_size=256M',
      '--binlog_format=mixed',
      '--lower_case_table_names=1',
      '--character-set-server=utf8',
      '--collation-server=utf8_general_ci']

  mysql-slave:
    build:
      context: ./
      dockerfile: ./slave/Dockerfile
    image: mysqlslave:1.0
    restart: always
    container_name: mysql-slave
    volumes:
      - ./slavevarlib:/var/lib/mysql
    ports:
      - 8081:3306
    environment:
      MYSQL_ROOT_PASSWORD: root
    privileged: true
    command: ['--server-id=2',
      '--relay_log=slave-relay',
      '--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
    image: mysqlslave:1.0
    restart: always
    container_name: mysql-slave2
    volumes:
      - ./slavevarlib2:/var/lib/mysql
    ports:
      - 8082:3306
    environment:
      MYSQL_ROOT_PASSWORD: root
    privileged: true
    command: ['--server-id=3',
      '--relay_log=slave-relay',
      '--lower_case_table_names=1',
      '--character-set-server=utf8',
      '--collation-server=utf8_general_ci']
    depends_on:
      - mysql-master

mysql-master:

restart:指定容器的重启策略。
always 表示无论容器因何种原因退出,Docker 都会尝试重新启动它。

volume:用于将主机目录挂载到容器中
./mastervarlib 是主机上的目录,/var/lib/mysql 是容器中 MySQL 默认的数据存储路径。
作用:将 MySQL 的数据存储在主机上,确保容器重启或删除后数据不会丢失。

envirnment:设置环境变量
MYSQL_ROOT_PASSWORD: root 指定 MySQL 的 root 用户密码为 root。
privileged:设置容器以特权模式运行

command:
设置 MySQL 服务器的唯一 ID,主从复制中必须指定,且每个服务器的 ID 必须唯一
启用二进制日志(Binary Log),日志文件前缀为 master-bin,记录主库的写操作
指定忽略mysql系统数据库的二进制日志记录
设置二进制日志缓存的大小为 256MB
设置二进制日志的格式为 mixed
设置表名不区分大小写
设置服务器的默认字符集为 utf8
设置服务器的默认排序规则为 utf8_general_ci

mysql-slave1:

depends-on:指定服务之间的依赖关系
mysql-slave 服务依赖于 mysql-master 服务
确保在启动 mysql-slave 之前,mysql-master 服务已经启动

启动:

docker compose up -d

查看主从复制状态的命令

MySQL命令来检查主从复制状态。以下是完整的操作流程:

docker exec -it mysql-slave mysql -uroot -proot -e "SHOW SLAVE STATUS\G"

这条命令会直接输出从库的复制状态。关键字段包括:

  • Slave_IO_Running(IO线程状态)
  • Slave_SQL_Running(SQL线程状态)
  • Seconds_Behind_Master(主从延迟秒数)
  • Last_IO_Error/Last_SQL_Error(错误信息)

核对以下关键指标:

  • 两个线程必须显示为Yes
    Slave_IO_Running: Yes
    Slave_SQL_Running: Yes
  • Seconds_Behind_Master应为0或较小的数值
  • Master_Log_FileRead_Master_Log_Pos应与主库的SHOW MASTER STATUS输出匹配

测试:

在主库上: 

docker exec -it mysql-master bash

create database test;

mysql> use test;
Database changed
mysql> create table users(sno int,sname varchar(20));
Query OK, 0 rows affected (0.03 sec)


mysql> insert into  users values (1,'xixi');
Query OK, 1 row affected (0.02 sec)


mysql> insert into  users values (2,'haha');
Query OK, 1 row affected (0.01 sec)

在从库上:

mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A


Database changed
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| users          |
+----------------+
1 row in set (0.00 sec)


mysql> select * from users;
+------+-------+
| sno  | sname |
+------+-------+
|    1 | xixi  |
|    2 | haha  |
+------+-------+
2 rows in set (0.00 sec)


网站公告

今日签到

点亮在社区的每一天
去签到