使用Docker搭建Mysql主从数据库

近期巴以冲突爆发,拦截率90%的铁穹防空系统当场被打到宕机。
使用Docker搭建Mysql主从数据库_第1张图片

我们在日常工作中,也会随着业务的增长,面临海量用户对于服务器的并发访问量造成的性能问题。为此,我们可以搭建数据库集群,实现主从分离和负载均衡,来提高系统的可用性和性能。

接下来,本文就介绍一下,如何利用Docker来搭建MySQL数据库集群,并实现主从分离(1主2从)。

主从分离原理(1主1从)

使用Docker搭建Mysql主从数据库_第2张图片

  1. 服务器(master)收到写请求后,将该操作记录到二进制日志(binary log)中。
  2. 服务器(slave)启动时,会创建两个线程:一个I/O线程(I/O线程负责与主服务器建立连接并请求获取二进制日志数据)和一个SQL线程。
  3. 服务器收到服务器的连接请求后,为I/O线程创建一个专用的log dump线程(多个从库时,每个I/O线程对应不同的log dump线程),log dump线程将二进制日志数据传输给服务器的I/O线程。
  4. 服务器的I/O线程将接收到的二进制日志数据写入中继日志(relay log)文件中。
  5. SQL线程读取中继日志文件中的数据,并解析执行这些二进制日志事件,然后更新服务器上的数据库内容,从而保持主从数据一致。

搭建步骤(主1从2)

使用Docker搭建Mysql主从数据库_第3张图片

数据持久化

为了防止Docker容器被意外删除或者需要重新创建容器时能够快速恢复数据,我们通常需要对MySQL数据库的配置文件和数据做持久化存储。

其中一种方案是将MySQL的配置文件和数据分别挂载到宿主机上的不同目录中,即将宿主机上的目录与容器内的目录进行关联,以保证数据的安全性和可靠性。这样,在容器被删除或者重新创建时,只需要重新挂载这些目录,即可快速恢复MySQL数据库的数据和配置。

  1. 在宿主机上分别创建 MySQL 数据存放的目录

    此次我们将数据存放在/usr/local下面。

    扩展:Linux数据存放问题有一个FHS (Filesystem Hierarchy Standard) 试图制定一个文件层次结构标准,不说这个标准是否一定合理,但学习一下还是很好的。

    Where in the filesystem should I store shared data?

    mkdir -p /usr/local/softwares/mysql/{3306,3310,3311}/{conf,data}
    

    使用Docker搭建Mysql主从数据库_第4张图片

  2. 获得 MySQL 的初始配置文件

    首次挂载文件时,如果在宿主机上找不到对应的配置文件,Docker会自动创建一个空文件。但是,这就会导致容器中的MySQL配置文件也为空,造成配置丢失。所以,为了避免这种情况,我们需要提前在宿主机中准备一个配置文件。

    那,这个文件去哪找呢?

    简单,我们先创建一个MySQL容器,直接将它的配置文件复制一份不就好了。

    docker run -it --name mysqlx -e MYSQL_ROOT_PASSWORD=123 -d mysql
    

    然后使用Docker复制工具,将容器内文件复制到宿主机对应目录。

    docker cp mysqlx:/etc/mysql/my.cnf  /usr/local/softwares/mysql/3306/conf/
    

    现在,我们就可以开始搭建主服务器了。

搭建主(master)服务器(docker容器)

data存放目录(/var/lib/mysql)可在默认生成的my.cnf中查看。

/var/lib/mysql-files 文件不挂载日志中会提示错误,所以也一并挂载上。

docker run -it \
--name mysql_3306 \
--privileged \
--network docker_net \
--ip 172.18.12.2 \
-p 3306:3306 \
-v /usr/local/software/mysql/3306/conf/my.cnf:/etc/mysql/my.cnf \
-v /usr/local/software/mysql/3306/data:/var/lib/mysql \
-v /usr/local/software/mysql/3306/mysql-files:/var/lib/mysql-files \
-e MYSQL_ROOT_PASSWORD=123 \
-d mysql

执行后,可通过 docker ps 查询一下,若不成功,可以通过 docker logs 查看一下报错日志。

好了吗?当然还没有。
使用Docker搭建Mysql主从数据库_第5张图片

现在只是创建了一个普通的服务器,接下来我们将其设置为主服务器。

主(master)服务器配置

修改宿主机中3306/conf/下面的my.cnf文件

  1. default_authentication_plugin=mysql_native_password

    将默认插件设置为mysql_native_password。在MySQL 8.0及以上版本中,默认的插件是caching_sha2_password,而在低版本中,默认插件是mysql_native_password。所以在某些软件或应用程序中,可能不兼容caching_sha2_password(Navicat中输入密码可能会乱码)。

  2. server-id=200

    标识MySQL服务器的唯一ID。集群环境中,每个MySQL实例都需要一个唯一ID。

  3. log_bin=master-logbin

    开启二进制日志(binlog)功能并自定义名称。正如上面所说,服务器执行sql后,会将操作记录写入binlog文件中,所以我们需要开启binlog功能,为了确保其唯一性可识别性以及可维护性我们将名称自定义。

  4. binlog_format=row

    指定二进制日志的格式。MySQL支持三种格式:STATEMENTROWMIXEDstatement格式以SQL语句的形式记录日志,row格式以行的形式记录日志,mixed格式根据具体情况自动选择记录日志的形式。row格式在数据一致性和可靠性方面较好。

[mysqld]
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
datadir         = /var/lib/mysql
secure-file-priv= NULL
default_authentication_plugin=mysql_native_password

# Custom config should go here
!includedir /etc/mysql/conf.d/

server-id=200
log_bin=master-logbin
binlog_format=row

修改完成后,我们将主服务器(mysql_3306)重启,使配置生效。

docker restart mysql_3306

重启后,运行 docker ps 检查一下,正常运行后就表示主服务器配置成功啦!(不成功请检查配置文件)

容器运行成功后,我们使用Navicat测试一下,并创建一个slave用户来进行主从关联。

create user 'slave'@'%' IDENTIFIED WITH mysql_native_password BY '123';
GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'slave'@'%';
flush privileges;

接下来我们就可以开始搭建从服务器了。
请添加图片描述

搭建从(slave)服务器(docker容器)

从服务器搭建与主服务器搭建步骤基本一样。我们先搭建第一个从服务器。

  1. 将主服务器上的 my.cnf 配置文件复制到宿主机 3310/cnf/

    docker cp mysql_3306:/etc/mysql/my.cnf /usr/local/softwares/mysql/3310/conf/
    
  2. 修改 3310/conf/ 下面的 my.cnf 配置文件

    1. relay_log=slave-01-relay:指定中继日志文件的名称。中继日志用于存储从主服务器接收并准备复制到从服务器的日志事件。

    2. read-only=1:将从服务器设置为只读模式,这样可以防止对从服务器进行写操作。这是为了确保从服务器不会被意外修改数据,因为它的目的是用于复制主服务器的数据而不是进行写操作。后面使用用户来控制操作权限。

    [mysqld]
    pid-file        = /var/run/mysqld/mysqld.pid
    socket          = /var/run/mysqld/mysqld.sock
    datadir         = /var/lib/mysql
    secure-file-priv= NULL
    default_authentication_plugin=mysql_native_password
    
    # Custom config should go here
    !includedir /etc/mysql/conf.d/
    
    server-id=201
    log_bin=slave-01-bin
    relay_log=slave-01-relay
    read-only=1
    
  3. 然后创建并运行容器,注意修改ip、端口以及挂载文件路径

    docker run -it \
    --name mysql_3310 \
    --privileged \
    --network docker_net \
    --ip 172.18.12.3 \
    -p 3310:3306 \
    -v /usr/local/software/mysql/3310/conf/my.cnf:/etc/mysql/my.cnf \
    -v /usr/local/software/mysql/3310/data:/var/lib/mysql \
    -v /usr/local/software/mysql/3310/mysql-files:/var/lib/mysql-files \
    -e MYSQL_ROOT_PASSWORD=123 \
    -d mysql
    
  4. 运行成功后,进入容器中MySQL

    docker exec -it mysql_3310 bash
    # 进入mysql
    mysql -uroot -p123
    
  5. 配置主服务器

    master_host 就是主服务器(mysql_3306)的容器ip,用户就是刚刚我们在主mysql下创建的slave用户。

    MASTER_LOG_FILE表示主服务器当前正在写入的binlog文件名。MASTER_LOG_POS指的是主服务器中binlog文件的记录位置。过这两个参数的设置,从服务器可以定位到主服务器binlog文件的特定位置,并从该位置开始进行数据复制。

    这两个参数的值,需要进入主服务器(mysql_3306)中的mysql中查询,查询命令

    show master status;
    

    使用Docker搭建Mysql主从数据库_第6张图片

    change master to master_host='172.18.12.2', master_user='slave',master_password='123',MASTER_LOG_FILE='master-logbin.000002',MASTER_LOG_POS=156;
    

    配置完成后启动

    start slave;
    

    验证

    show slave status \G;
    

    在这里插入图片描述

    若这两个参数值为Yes,则表示创建成功。


第二个从服务器搭建与第一个一样,需要注意以下几点:

  1. 配置文件server-id一定不能相同,如下示例:

    server-id=202
    log_bin=slave-02-bin
    relay_log=slave-02-relay
    read-only=1
    
  2. 创建容器时注意修改ip、端口和挂载的路径名称。

  3. 配置主服务器时,MASTER_LOG_FILE和MASTER_LOG_POS一定要从新进入主MySQL中查询(有可能会变,变化后,从1的参数值无需修改,只需将从2的值设置为最新的查询结果即可)。

为从MySQL创建只读用户

分别在两个从MySQL上创建这个用户,后续从MySQL使用此账户登录。

create user 'sd'@'%' IDENTIFIED WITH mysql_native_password BY '123';
GRANT SELECT ON *.* TO 'sd'@'%';
flush privileges;

到此,主从配置就完成了!!!
使用Docker搭建Mysql主从数据库_第7张图片

问题记录

slave 重置步骤

slave不小心配置错误后,可使用下面方法重置

  1. 关闭slave

    stop slave;
    
  2. 重置slave

    reset slave;
    
  3. 重新配置slave

  4. 启动slave

    start slave;
    

binlog 相关操作命令

  1. 查看日志是否启用
show variables like 'log_bin';
  1. 查看binlog的位置
show variables like '%datadir%';
  1. 显示所有日志文件
show binary logs;
  1. 查询binlog日志
show binlog events in 'master-logbin.000001';

感谢大家读到这里,后续还会有其他相关文章,欢迎继续阅读。

你可能感兴趣的:(Docker,MySQL,数据库,docker,mysql)