为什么基于Docker搭建?

  • 资源有限
  • 虚拟机搭建对机器配置有要求,并且安装mysql步骤繁琐
  • 一台机器上可以运行多个Docker容器
  • Docker容器之间相互独立,有独立ip,互不冲突
  • Docker使用步骤简便,启动容器在秒级别

利用Docker搭建主从服务器

首先拉取docker镜像,我们这里使用5.7版本的mysql。然后使用此镜像启动容器,这里需要分别启动主从两个容器。

  1. docker pull mysql:5.7

maseter-msql主容器对外映射的端口是3339slave-mysql从容器对外映射的端口是3340
因为docker容器是相互独立的,每个容器有其独立的ip,所以不同容器使用相同的端口并不会冲突。所以两个容器内的mysql使用默认的3306端口,否则可能会出现无法通过ip连接docker容器内mysql的问题。

  • Master(主):

    1. docker run -p 3339:3306 --name master-mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
  • Slave(从):

    docker run -p 3340:3306 --name slave-mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
    
  • 使用docker ps命令查看正在运行的容器:

    greamrod@greamrod-cp:/mnt/c/Users/11475$ docker ps
    CONTAINER ID   IMAGE       COMMAND                  CREATED          STATUS          PORTS                                                  NAMES
    695a89694c2a   mysql:5.7   "docker-entrypoint.s…"   11 seconds ago   Up 11 seconds   33060/tcp, 0.0.0.0:3340->3306/tcp, :::3340->3306/tcp   slave-mysql
    d591c009f048   mysql:5.7   "docker-entrypoint.s…"   17 seconds ago   Up 16 seconds   33060/tcp, 0.0.0.0:3339->3306/tcp, :::3339->3306/tcp   master-mysql
    greamrod@greamrod-cp:/mnt/c/Users/1147
    
  • 使用如下指令,进入容器内部:

    # 进入 master-mysql 容器内部
    docker exec -it master-mysql /bin/bash
    # 进入 slave-mysql 容器内部
    docker exec -it slave-mysql /bin/bash
    


    配置Master(主)

    进入master-mysql容器: ```bash

    使用 master-mysql容器名称 进入具体某个容器

    docker exec -it master-mysql /bin/bash

或者(二选一)

d591c009f048 是master-mysql容器的ID

docker exec -it d591c009f048 /bin/bash

`docker`容器没有自带的`vim`,我们需要自行安装:
```bash
# 更新 apt-get 
apt-get update
# 安装 vim 软件
apt-get install vim

进入master-mysql主容器,修改mysql(主数据库)的my.cnf配置文件,对设置server-id、log-bin、log-bin-index进行设置,配置如下。

# 进入到`my.cnf`编辑界面
vim /etc/mysql/my.cnf

===================================== 分割线 =======================================

# 对`my.cnf`新增如下修改
[mysqld]
server-id=1
log-bin=master-bin
log-bin-index=master-bin.index

编辑master-mysql中的my.cnf文件.png
从新启动master-mysql主容器中的msyql服务。

service mysql restart

进入master-mysql主容器,并查看容器的独立ip

greamrod@greamrod-cp:/mnt/c/Users/11475$ docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED        STATUS        PORTS                                                  NAMES
695a89694c2a   mysql:5.7   "docker-entrypoint.s…"   15 hours ago   Up 15 hours   33060/tcp, 0.0.0.0:3340->3306/tcp, :::3340->3306/tcp   slave-mysql
d591c009f048   mysql:5.7   "docker-entrypoint.s…"   15 hours ago   Up 15 hours   33060/tcp, 0.0.0.0:3339->3306/tcp, :::3339->3306/tcp   master-mysql
greamrod@greamrod-cp:/mnt/c/Users/11475$
greamrod@greamrod-cp:/mnt/c/Users/11475$
greamrod@greamrod-cp:/mnt/c/Users/11475$ docker inspect --format='{{.NetworkSettings.IPAddress}}' master-mysql
172.17.0.2
greamrod@greamrod-cp:/mnt/c/Users/11475$

查看master-mysql的IP地址.png
进入master-mysql的主容器的mysql(主数据库)中,使用show master status;查看mysql(主数据)的详细信息:

# master-mysql(主数据库容器)
greamrod@greamrod-cp:/mnt/c/Users/11475$ docker exec -it master-mysql /bin/bash
root@d591c009f048:/#
root@d591c009f048:/#
root@d591c009f048:/# mysql -uroot -p123456
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 2
Server version: 5.7.34-log MySQL Community Server (GPL)
Copyright (c) 2000, 2021, 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.000002 |      617 |              |                  |                   |
+-------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

show master status.png
mysql(主数据库)中创建数据同步用户。

mysql> CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.00 sec)

mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
Query OK, 0 rows affected (0.01 sec)


配置Slave(从)

进入slave-mysql从容器,修改mysql(从数据库)的my.cnf配置文件,对设置server-id、relay-log-index、relay-log进行设置,配置如下。

# 进入到`my.cnf`编辑界面
vim /etc/mysql/my.cnf
===================================== 分割线 =======================================
# 对`my.cnf`新增如下修改
server-id=2
relay-log=slave-relay-bin
relay-log-index=slave-relay-bin.index

在Slave配置文件my.cnf中添加如下配置.png
从新启动slave-mysql从容器中的msyql服务。

service mysql restart

进入slave-mysql的从容器的mysql(从数据库)中,执行如下指令:

  • master_host :主容器的独立ip,可以通过docker inspect --format='{{.NetworkSettings.IPAddress}}' 容器名称|容器id查看。
  • master_port:主容器中的mysql(主数据库)端口号。
  • master_user:在主容器中的mysql(主数据库),创建数据同步用户名。
  • master_password:在主容器中的mysql(主数据库),创建数据同步密码。
  • master_log_file:指定mysql(从数据库)从哪个日志文件开始复制数据,对应mysql(主数据库)中提到的File 字段的值
  • master_log_pos:对应mysql(主数据库)中提到的Position 字段的值。
  • master_connect_retry:如果连接失败,重试的时间间隔,单位是秒,默认是60秒。

    mysql> change master to master_host='172.17.0.2', master_user='slave', master_password='123456', master_port=3306, master_log_file='master-bin.000002', master_log_pos=617, master_connect_retry=30;
    Query OK, 0 rows affected, 2 warnings (0.02 sec)
    

    正常情况下,SlaveIORunningSlaveSQLRunning 都是No,因为我们还没有开启主从复制过程。

  • 开启主从复制过程。

    mysql> start slave;
    Query OK, 0 rows affected (0.01 sec)
    
  • 查询主从同步状态。

SlaveIORunningSlaveSQLRunning都是Yes,说明主从复制已经开启。此时可以测试数据同步是否成功。

mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.17.0.2
                  Master_User: slave
                  Master_Port: 3306
                Connect_Retry: 30
              Master_Log_File: master-bin.000002
          Read_Master_Log_Pos: 617
               Relay_Log_File: slave-relay-bin.000002
                Relay_Log_Pos: 321
        Relay_Master_Log_File: master-bin.000002
             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: 617
              Relay_Log_Space: 528
              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: bc3b0f85-bf99-11eb-abc9-0242ac110002
             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:
1 row in set (0.00 sec)

从数据库 的配置 对于 主数据库中的配置.png

主从复制排错

使用start slave开启主从复制过程后,如果SlaveIORunning一直是Connecting,则说明主从复制一直处于连接状态,这种情况一般是下面几种原因造成的,我们可以根据Last_IO_Error提示予以排除:

  • 网络不通:检查ip端口
  • 密码不对:检查是否创建用于同步的用户和用户密码是否正确
  • master_log_pos不对:检查主容器中msyql主数据库的Position

基于MySQL 8.0 镜像搭建时,遇到的错误

image.png
进入主容器的msyql主数据库中,将同步用户的 plugin=caching_sha2_password 修改为 plugin=mysql_native_password

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)

mysql> SELECT plugin FROM mysql.`user` where user = 'slave';
+-----------------------+
| plugin                |
+-----------------------+
| caching_sha2_password |
+-----------------------+
1 row in set (0.00 sec)

mysql> ALTER USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
Query OK, 0 rows affected (0.01 sec)

mysql> SELECT plugin FROM mysql.`user` where user = 'slave';
+-----------------------+
| plugin                |
+-----------------------+
| mysql_native_password |
+-----------------------+
1 row in set (0.00 sec)

使用Navicat连接

使用navicat分别链接 主、从数据库 进行测试链接。往主数据库中导入一个sql文件,从数据库中会自动同步。
从库会自动同步主库中的数据.png

参考链接地址: