Docker 学习笔记(二)MySQL中继日志、读写分离、主从架构概念 | 使用Docker创建、配置与使用两个MySQL主从库容器

Docker 学习笔记(二)MySQL中继日志、读写分离、主从架构概念 | 使用Docker创建、配置与使用两个MySQL主从库容器_第1张图片

若发现文章有误,欢迎提出宝贵的建议,敬请指教,感谢

文章目录

  • 运行环境
  • 一、MySQL相关概念
    • 1.1 中继日志 relay log
    • 1.2 主从架构 & 读写分离
      • 1.2.1 如何提高数据库的并发能力
      • 1.2.2 主从架构的三大作用
      • 1.2.3 主从复制的原理
  • 二、Docker实现MySQL主从架构
    • 2.1 创建、配置Master库容器
    • 2.2 创建、配置Slave库容器
  • 总结
  • 参 考 资 料

运行环境


  • Ubuntu 21.04
  • Docker 20.10.7
  • MySQL 5.7

一、MySQL相关概念


1.1 中继日志 relay log

  • 中继日志 relay log 只在主从master/slave服务器架构的从服务器上存在。

  • slave为了与master保持一致,要从master读取二进制日志的内容,并且把读取到的信息写入本地的日志文件中,slave本地的日志文件就叫做中继日志(relay log)

  • slave读取relay log,并根据其内容对slave的数据进行更新,完成masterslave的数据同步。

  • 搭建好master/slave之后,relay log 默认会保存在slave的数据目录下。

  • relay log 存储文件名的格式是:slave_name -relay-bin.序号

  • relay log 还有一个索引文件:slave_name-relay-bin.index , 用于定位当前正在使用relay log

relay log 与 二进制日志(bin log)的格式相同,可以用mysqlbinlog 工具进行查看

1.2 主从架构 & 读写分离

1.2.1 如何提高数据库的并发能力

在实际工作中,通常使用 Redis 作为缓存与MySQL配合使用,当有请求的时候,首先会从缓存中进行查找,如果存在就直接取出,如果不存在的话再访问数据库,这样就提升了读取的效率,也减少了对后端数据库的访问压力,Redis的缓存架构是高并发架构中非常重要的一环。

Docker 学习笔记(二)MySQL中继日志、读写分离、主从架构概念 | 使用Docker创建、配置与使用两个MySQL主从库容器_第2张图片

此外,一般对数据库而言都是“读取多,写入少”,即数据库读取数据的压力比较大,解决思路之一就是采用数据库集群的方案,做主从架构,进行读写分离,这样同样可以提升数据库的并发处理能力。

提升数据库高并发访问的步骤,根据需求依次选择其中一种,使用和维护成本是逐渐升高的:

  1. 优化SQL语句索引,这种方式简单有效。
  2. 采用缓存的策略,比如使用Redis将热点数据保存在内存数据库中,提升读取的效率。
  3. 对数据库采用主从架构,进行读写分离。
    Docker 学习笔记(二)MySQL中继日志、读写分离、主从架构概念 | 使用Docker创建、配置与使用两个MySQL主从库容器_第3张图片

1.2.2 主从架构的三大作用

主从同步设计不仅可以提高数据库的吞吐量,还有以下3个方面的作用。

1.读写分离
可通过主从复制的方式来同步数据,然后通过读写分离提高数据库并发处理能力
Docker 学习笔记(二)MySQL中继日志、读写分离、主从架构概念 | 使用Docker创建、配置与使用两个MySQL主从库容器_第4张图片
其中一个为Master主库,负责写入数据,简称为:写库
其他都是Slave从库,负责读取数据,简称为:读库

如图,当Master进行更新时,会自从将数据复制到Slave中,而我们在客户端读取数据时,会从Slave中读取。

面对"读多写少"的需求,采用读写分离的方式,可以实现更高的并发访问,同时我们还能对服务器进行负载均衡,让不同的读请求按照策略均匀的分发到不同的Slave上,让读取更加流畅,读取流畅的另一个原因就是减少了锁表的影响,比如:Master负责写,当Master锁表时,不会影响到Slave进行SELECT的读取。

2.数据备份
将Master的数据复制到Slave上,相当于是一种热备份机制,即在Master正常运行的情况下进行备份,不会影响到服务

3.高可用性
数据备份实际上是一种冗余的机制,通过这种冗余的方式可以换取数据库的高可用性。
当Master服务器出现故障或宕机的情况下,可以切换到Slave上,保证服务的正常运行。

关于高可用的程度,可用一个指标衡量,即 正常可用时间 / 全年时间 ,比如要达到全年99.999%的时间都可以使用,这意味着系统在一年中的不可用时间不得超过`3652460*(1-99.999%) = 5.256 分钟(含系统崩溃的日志、日常维护操作导致的停机时间等),其他时间都需要保证高可用的状态。

1.2.3 主从复制的原理

原理:

Slave 会从Master读取bin log (二进制日志)来进行数据同步。

在主从复制过程中,会基于三个线程来操作,一个主库线程,两个从库线程。
Docker 学习笔记(二)MySQL中继日志、读写分离、主从架构概念 | 使用Docker创建、配置与使用两个MySQL主从库容器_第5张图片
二进制日志转储线程(BinLog Dump Thread)是一个Master库线程。当slave库线程连接时,Master库可以将二进制日志发送给Slave。当Master库读取事件(Event)的时候,会在BinLog上加锁,读取完成后,再将锁释放。

Slave库 I / O 线程会连接到Master库,向Master发送请求更新BinLog。这时Slave的I/O线程就可以读取到Master的BinLog Dump Thread 发送的BinLog更新部分,并且拷贝到本地的Relay Log(中继日志)。

Slave库 SQL 线程 会读取库中的中继日志,并且执行日志中的事件,将Slave库中的数据与Master库保持同步。
Docker 学习笔记(二)MySQL中继日志、读写分离、主从架构概念 | 使用Docker创建、配置与使用两个MySQL主从库容器_第6张图片
注:不是所有版本的MySQl都默认开启服务器的二进制日志。在进行主从同步的时候,首先需检查服务器是否已开启二进制日志。

除非特殊指定,默认情况下Slave会执行所有Master服务器中保存的事件,也可以通过配置,使Slave服务器只执行特定的事件。

同步复制的三步骤:

  1. Master将写操作记录到二进制日志(binlog),这些记录叫做二进制日志事件(binary log envents)
  2. Slave将Master的binary log events 拷贝到它的中继日志(relay log )
  3. Slave 重做中继日志中的事件,将改变应用到自己的数据库中。

MySQL复制是异步并且串行化的,而且重启后会从接入点开始复制。

同步复制的最大问题是延时

同步复制的原则:

  • 每个Slave只能有一个Master
  • 每个Slave只能由一个唯一的服务器ID
  • 每个Master可以有多个Slave

二、Docker实现MySQL主从架构


拉取Mysql5.7的镜像

$ sudo docker pull mysql:5.7

2.1 创建、配置Master库容器

注:由于是在同一个宿主机上使用Docker搭建,所以端口映射不能都为3306,否则会发生冲突,这里则采用Master 3307、Slave 3308的端口映射方式。

第一步,创建Master库容器

$ sudo docker run -p 3307:3306 --name mysql-master \
-v /uni/docker/mysql-master/log:/var/log/mysql \
-v /uni/docker/mysql-master/data:/var/lib/mysql \
-v /uni/docker/mysql-master/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7

第二步,宿主机进入与容器卷同步的目录,添加MySQL配置文件

$ cd /uni/docker/mysql-master/conf

$ vim my.cnf

配置内容如下:

[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=1
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql  
## 开启二进制日志功能
log-bin=mall-mysql-bin  
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M  
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed  
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7  
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062

修改完后重启Master库容器

$ sudo docker restart mysql-master

第三步,进入Master库容器、创建数据同步的用户:

$ sudo docker exec -it mysql-master /bin/bash

myslq -uroot -proot
# 创建 slave用户
mysql> CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
# 赋予 slave用户权限
mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';

2.2 创建、配置Slave库容器

第一步,创建Slave库容器

$ sudo docker run -p 3308:3306 --name mysql-slave \
-v /uni/docker/mysql-slave/log:/var/log/mysql \
-v /uni/docker/mysql-slave/data:/var/lib/mysql \
-v /uni/docker/mysql-slave/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root  \
-d mysql:5.7

第二步,和之前一样,先去宿主机配置的容器卷位置创建Slave库的配置文件

$ cd /uni/docker/mysql-slave/conf

$ vim my.cnf

配置的内容如下:

[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=2
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql  
## 开启二进制日志功能,以备Slave作为其它数据库实例的Master时使用
log-bin=mall-mysql-slave1-bin  
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M  
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed  
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7  
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062  
## relay_log配置中继日志
relay_log=mall-mysql-relay-bin  
## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1  
## slave设置为只读(具有super权限的用户除外)
read_only=1

Salve库配置与Master库配置的区别如下:
Docker 学习笔记(二)MySQL中继日志、读写分离、主从架构概念 | 使用Docker创建、配置与使用两个MySQL主从库容器_第7张图片
配置好后重启Slave库容器

$ sudo docker restart mysql-slave

第三步,在Master库容器中查看主从同步状态

mysql> show master status;

运行结果:
Docker 学习笔记(二)MySQL中继日志、读写分离、主从架构概念 | 使用Docker创建、配置与使用两个MySQL主从库容器_第8张图片
第四步,进入Slave库容器配置主从复制:

$ sudo docker exec -it mysql-slave /bin/bash

mysql -uroot -proot

修改语句标准语法:

change master to master_host='宿主机ip', master_user='slave', master_password='123456', master_port=3307, master_log_file='mall-mysql-bin.000001', master_log_pos=617, master_connect_retry=30;

测试语句(Slave库容器):

mysql> change master to master_host='192.168.25.128', master_user='slave', master_password='123456', master_port=3307, master_log_file='mall-mysql-bin.000001', master_log_pos=617, master_connect_retry=30;

# 接着在Slave库容器中查看主从同步状态,\G表示以KV形式打印
mysql> show slave status \G;

观察是否开启主从复制,主要查看Slave_IO_Running和Slave_SQL_Running这两个线程是否在运行,由于我们没有启动,之前只是指定了它的Master库,所以这里显示为NO
Docker 学习笔记(二)MySQL中继日志、读写分离、主从架构概念 | 使用Docker创建、配置与使用两个MySQL主从库容器_第9张图片
第五步,在Slave库容器中开启slave,再查看IO和SQL线程的运行结果:

mysql> start slave;

mysql> show slave status \G;

运行结果:
Docker 学习笔记(二)MySQL中继日志、读写分离、主从架构概念 | 使用Docker创建、配置与使用两个MySQL主从库容器_第10张图片
此时,线程启动成功了。

最后一步,同时开启Master库和Slave库,进行读写分离的测试:

在Master库容器中,创建随机的一个数据库、数据表,插入随机数据

然后在Slave库容器中进行查询。
Docker 学习笔记(二)MySQL中继日志、读写分离、主从架构概念 | 使用Docker创建、配置与使用两个MySQL主从库容器_第11张图片
至此,基于Docker搭建的MySQL主从架构已完毕。

总结


本次使用Docker搭建了两个节点的MySQL主从架构,了解了MySQL中继日志、读写分离的相关概念,主从架构本质上实现了读写分离,比如在Master库写入数据的同时不会影响在Slave库容器读数据,提高可用性,但同时也容易产生数据不一致的问题,这里没有做讨论,至少我们知道了MySQL也支持类似于分布式的架构。

连接MySQL本身就需要通过IP:端口的形式,说明它肯定是支持远程连接的,这意味着它本身就能通过IP:端口去连接另外的MySQL服务器,虽然我们在平时学习当中经常是使用localhost连接的MySQL,但也不能仅仅局限于本地上的MySQL这种思想,如果有公网IP,开放对应的端口和权限后,只要在有网络的情况下,同样是可以继续远程连接的。

最后就是MySQL的主从架构并不一定是最好的选择,它虽然提高了数据的安全性,但同时也带来了数据延时和成本的问题。

参 考 资 料


[1]MySQL视频资料
[2]Docker视频资料

你可能感兴趣的:(学习笔记,#,Docker,docker,mysql)