MySQL 高可用架构 - 图1

前言

对于 MySQL 数据库作为各个业务系统的存储介质,在系统中承担着非常重要的职责,如果数据库崩了,那么对于读和写数据库的操作都会受到影响。如果不能迅速恢复,对业务的影响是非常大的。

一、方案选择

对于 MySQL 的高可用,主要分为两步,配置 MySQL 主主模式和 keepalived 软件。拓扑图如下所示:
MySQL 高可用架构 - 图2

MySQL 数据库的主主模式

两个数据库分别部署在两台服务器上,相互同步数据,但是只有一个提供给外部访问,当一个宕机后,另外一个可以继续提供服务,在没有 keepalived 软件的帮助下,只能手动切换。

keepalived 监测、自动重启、流量切换

  • 检测和重启:两台服务器上都部署 keepalived 软件,定时检测 MySQL 服务是否正常,如果一个数据库服务崩了,keepalived 会用脚本尝试重启 mysql 服务。
  • 备份:两个 keepalived 服务都提供了虚拟 IP 供客户端使用,但是流量只会转到一台 MySQL 服务上。
  • 虚拟 IP:keepalived 配置好了后,会有一个 虚拟 IP,对于客户端来说,不关心连接的是哪台 MySQL,访问虚拟 IP 就可以了。
  • 流量切换:如果客户端正在访问的 MySQL 服务崩了后,keepalived 会用写的脚本自动重启 MySQL,如果重启失败,脚本主动停掉 keepalived,客户端的流量就不会访问到这台服务器上的 MySQL 服务,后续访问的流量都会切到另外一台 MySQL 服务。

检测和重启的原理如下所示:
MySQL 高可用架构 - 图3
需要配置的内容如下:

  • 两台 Ubuntu 服务器上启动 MySQL 容器。
  • 配置 MySQL 主从复制架构。
  • 将 MySQL 主从改为主主复制架构。
  • 两台服务器搭建 keepalived 环境监控 MySQL 和自动重启 MySQL。

    二、主主复制的原理

    对于 MySQL 的主主架构,其实原理就是两台服务器互为主从,双向复制。而复制的原理如下:
    主从复制主要有以下流程:
  1. 主库将数据的改变记录到 binlog 中;
  2. 从库会在一定时间间隔内对 master 的 binlog 进行检查,如果发生改变,则开始一个 I/O Thread 请求读取 master 中 binlog ;
  3. 同时主库为每个 I/O 线程启动一个 dump 线程,用于向其发送二进制事件,并保存至从节点本地的中继日志中,从库将启动 SQL 线程从中继日志中读取二进制日志,在本地重放,使得其数据和主节点的保持一致,最后 I/O Thread 和 SQL Thread 将进入睡眠状态,等待下一次被唤醒;

MySQL 高可用架构 - 图4
大白话就是:
从库会生成两个线程,一个 I/O 线程,一个 SQL 线程;
I/O 线程会去请求主库的 binlog,并将得到的 binlog 写到本地的 relay-log (中继日志)文件中;
主库会生成一个 dump 线程,用来给从库 I/O 线程传 binlog;
SQL 线程,会读取 relay log 文件中的日志,并解析成 SQL 语句逐一执行;
接下来先把 MySQL 的基础环境在两台 Ubuntu 服务器上搭建好,后续操作都是基于这个来做的。

三、配置 MySQL 环境

作为演示,在本机启动了两台 Ubuntu 虚拟机,安装有 docker。因为测试和生产环境是用 Docker 跑的,所以将环境的镜像打包后,还原到虚拟机上面。

3.1 备份和还原 MySQL 镜像

保存测试环境的 MySQL 镜像:

  1. sudo docker save -o mysql.tar hcr:5000/hschub/hscmysql:0.0.2
  2. sudo chmod 777 mysql.tar

两台机器导入镜像:

  1. sudo docker load -i mysql.tar

启动容器,需要注意的是需要映射本地文件夹:

  1. sudo docker run -p 3306:3306 --name mysql \
  2. -v /home/hss/mysql/data:/var/lib/mysql \
  3. -v /home/hss/mysql/etc/mysql:/etc/mysql \
  4. -e MYSQL_ROOT_PASSWORD='123456' \
  5. -d 46b

-v代表映射的文件夹,-d表示后台运行,46b代表镜像 id。
进入容器,连接 mysql,node1的mysql 密码是 123456,node2 是 123456。

  1. # 查询容器 id
  2. docker ps
  3. # 进入 mysql 容器
  4. docker exec -it <容器 id> /bin/bash
  5. # 连接 mysql
  6. mysql -u root -p

接下来配置 MySQL 的主从架构,需要注意的是后续搭建的主主架构是基于主从架构来的,区别就是修改了一部分配置。