利用 Docker 快速实现 MySQL binlog 主从备份

Posted FesonX

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用 Docker 快速实现 MySQL binlog 主从备份相关的知识,希望对你有一定的参考价值。

Docker

Intro

主从备份是容灾的一种手段, 模拟主从备份可以有下面几种方式:

  • 不差钱方式, 买几台主机测试, 这种方式也比较接近线上环境.
  • 通过创建几台虚拟机来模拟. 这种方式对本机性能要求相对较高. 相对不差钱可以选这种方式, 但安装几台虚拟机也不是一件效率高的事.
  • 在一台主机上创建多个数据库实例. 缺点是环境无法隔离, 需要额外加多一些配置
  • 通过 Docker-compose 直接创建多个数据库容器, 暴露端口访问即可.

binlog 是MySQL数据库的二进制日志,用于记录用户对数据库操作的SQL语句(不包括 SELECT),可以在配置文件开启,也可以在 mysql 客户端开启. 可以在客户端键入show plugins; 查看 binlog 是否已安装开启( Active )

+----------------------------+----------+--------------------+---------+---------+
| Name                       | Status   | Type               | Library | License |
+----------------------------+----------+--------------------+---------+---------+
| binlog                     | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| mysql_native_password      | ACTIVE   | AUTHENTICATION     | NULL    | GPL     |
| sha256_password            | ACTIVE   | AUTHENTICATION     | NULL    | GPL     |
| PERFORMANCE_SCHEMA         | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| MEMORY                     | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |
| CSV                        | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |

环境准备

0.1 测试环境

必须安装有 dockerdocker-compose 用于构建容器环境, 本测试在 Ubuntu 16.04 及下列版本下进行, 使用其他版本可能会有使用差异.

docker-compose 1.25.4
docker 19.03.6

有关安装的细节, 请搜索相关关键词, 或者直接根据 Docker 官方文档 进行安装

0.2 Docker 加速

由于众所周知的原因, 拉取镜像时可能会很慢, 推荐设置国内的镜像源进行加速
Ubuntu/Centos/Debian 下修改或创建此文件 /etc/docker/daemon.json
示例文件内容如下, 可以自由添加镜像源. 镜像源有可能会宕机, 镜像源测试请参阅docker-registry-cn-mirror-test


    "registry-mirrors":[
        "https://dockerhub.azk8s.cn",
        "https://docker.mirrors.ustc.edu.cn",
        "https://reg-mirror.qiniu.com"
    ],
    "debug": true,
    "experimental": false
  

一. Docker 文件准备

1.1 文件目录

  • Dockerfile 是一个文本文件, 只需要 touch Dockerfile 创建即可.
  • docker-compose.yml 是用于运行多个 Docker 容器的配置文件, 使用 yaml 语言.

如只准备测试一主一从, 那么移除 slave02 目录, 添加多个从服务器则相应增加文件夹.

├── docker-compose.yml
├── master
│   ├── Dockerfile
│   └── my.cnf
├── slave01
│   ├── Dockerfile
│   └── my.cnf
└── slave02
    ├── Dockerfile
    └── my.cnf

1.2 docker-compose 文件及解释

  • environment
    在创建 MySQL 密码时, 测试用途用 root 没问题, 其他时候记得创建复杂密码, 至少可以使用 uuidgen 命令生成.
    支持在创建时同时创建一个数据库, 创建多个或进行其他数据初始化, 建议依靠外部 SQL 文件.
  • links
    这个不是推荐的配置方式, 不利于扩展, 但在此处我们只是用于测试. 可以自由添加你要的从服务器名称, 用于容器间的连接. 更推荐配置 networks
  • ports
    冒号左边为暴露的端口, 右边为容器内部的端口号, 在不配置网络的情况下(此时默认为 127.0.0.1), 为了避免端口冲突, 必须使暴露的端口号不一致.
version: '2' 
services:
  mysql-master: 
    build:
      context: ./                      # 声明构建的文件夹
      dockerfile: master/Dockerfile    # 声明 Docker 文件目录
    environment: # 环境变量, 支持数组或列表方式
      - "MYSQL_ROOT_PASSWORD=root"
      - "MYSQL_DATABASE=db0" # 初始创建的数据库
    links:
      - mysql-slave01
      - mysql-slave02
    ports:
      - "33065:3306" 
    restart: always
    hostname: mysql-master

  mysql-slave01:
    build:
      context: ./
      dockerfile: slave/Dockerfile
    environment:
      - "MYSQL_ROOT_PASSWORD=6954D5F0"
      - "MYSQL_DATABASE=db0"
    ports:
      - "33066:3306"
    restart: always
    hostname: mysql-slave01

  mysql-slave02:
    build:
      context: ./
      dockerfile: slave02/Dockerfile
    environment:
      - "MYSQL_ROOT_PASSWORD=6954D5F0"
      - "MYSQL_DATABASE=db0"
    ports:
      - "33067:3306"
    restart: always
    hostname: mysql-slave02

1.3 Dockerfile 文件及解释

  • FROM指定了基础镜像, 可以根据需求更改 MySQL 镜像版本
  • COPY
    将源文件复制到目标容器, 从服务器相应地创建 Dockerfile, 修改源文件位置. 也可以使用 ADD 这个更高级的复制命令, 但没必要.
FROM mysql:5.7.17
COPY ./master/my.cnf /etc/mysql/my.cnf

二. MySQL 配置文件准备

2.1 Master 节点配置

# master/my.cnf
[mysqld]
## 设置server_id,注意要唯一
server_id=100  
## 复制过滤:也就是指定哪个数据库不用同步(mysql库一般不同步)
binlog-ignore-db=mysql  
## 开启二进制日志功能,可以随便取,最好有含义
log-bin=replicas-mysql-bin  
## 为每个session分配的内存,在事务过程中用来存储二进制日志的缓存
binlog_cache_size=1M  
## 主从复制的格式(mixed,statement,row,默认格式是statement)
binlog_format=mixed  
## 二进制日志自动删除/过期的天数。默认值为0,表示不自动删除。
expire_logs_days=7  
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062

2.2 Slave 节点配置

Slave 节点的配置与 Master 相似, 但每个节点的 server_id 必须不同, 此外增加了 relay_log 中继日志的配置以及只读的设置

[mysqld]
## 设置server_id,注意要唯一
server_id=101 
# ... 省略配置
## relay_log配置中继日志
relay_log=replicas-mysql-relay-bin  
## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1  
## 防止改变数据(除了特殊的线程)
read_only=1 

三. 构建容器并运行

进入有 docker-compose.yml 的目录, 执行以下命令
该命令十分强大,它将尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作, -d 表示后台运行镜像.

docker-compose up -d

之后执行docker ps 查看正在运行的镜像, 如果是一主一从, 可以看到至少两个正在运行的镜像

$ docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                     NAMES
ef799b7d8cf8        mstest_mysql-master   "docker-entrypoint.s…"   4 minutes ago       Up 4 minutes        0.0.0.0:33065->3306/tcp   mstest_mysql-master_1
9d7ea93b7a85        mstest_mysql-slave    "docker-entrypoint.s…"   4 minutes ago       Up 4 minutes        0.0.0.0:33066->3306/tcp   mstest_mysql-slave_1

键入 docker exec -it [name/id] /bin/bash 进入容器, 可以是容器名称也可以是容器 id, 如下方示例:

docker exec -it mysql-master_1 /bin/bash

四. 配置主从

可以直接进入容器再进入 mysql 配置, 也可以不进入, 直接在终端键入下方命令, port 就是 docker-compose.xml 设置的端口号, 例如前面 master33065

mysql -uroot -p -P[port] -h127.0.0.1

4.1 获取主节点状态

键入 show master status; 记住当前 File 的名称和 Position, 这是从节点进行 binlog 复制找点用的.

mysql> show master status
    -> ;
+---------------------------+----------+--------------+------------------+-------------------+
| File                      | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------------------+----------+--------------+------------------+-------------------+
| replicas-mysql-bin.000003 |      154 |              | mysql            |                   |
+---------------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec

4.2 开启从节点复制

这里设置复制主节点的相关信息, 在前面文件用的是 root 密码,因此这里也是 root 用户, 将MASTER_LOG_FILEMASTER_LOG_POS 填上相应信息

CHANGE MASTER TO MASTER_HOST='mysql-master', MASTER_USER='root', MASTER_PASSWORD='root', MASTER_LOG_FILE='replicas-mysql-bin.000003', MASTER_LOG_POS=154;

接着启动复制.

  • 键入start slave;
  • 键入show slave status\\G;查看是否启用成功, 关注Slave_IO_RunningSlave_SQL_Running 是否为 Yes
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

mysql> show slave status\\G;
            ...
            Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
            ...

同样地, 如果有多个 Slave 节点, 就这一步多做几次.

4.3 验证是否成功

回到 Master 节点, 创建一个数据库 或者 往已经创建好的 db0 写入数据,

mysql> create database db1;

回到 Slave 节点, 查看两边是否同步.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| db0                |
| db1                |

五. 后话——另一种主从复制 GTID

GTID 自 MySQL 5.6.MySQL 5.6.5 便引入了,中文叫全局事务 ID(Global Transaction ID)

在本文的基于二进制日志复制中,从库需要告知主库要从哪个偏移量(就是 Log File 的 Position)进行增量同步,如果指定错误会造成数据的遗漏,从而造成数据的不一致。

但有了 GTID,发生主备切换时,MySQL 的其它从库可以自动在新主库上找到正确的复制位置,这大大简化了复杂复制拓扑下集群的维护,也减少了人为设置复制位置发生误操作的风险。另外,基于 GTID 的复制还可以忽略已经执行过的事务

参考

  1. Docker Compose搭建MySQL主从复制集群
  2. GTID Concept - MySQL
  3. Docker 从入门到实践 - Compose 命令说明

公众号:程序员的碎碎念
Github:github.com/FesonX

以上是关于利用 Docker 快速实现 MySQL binlog 主从备份的主要内容,如果未能解决你的问题,请参考以下文章

如何利用 docker 快速部署 Mysql 服务

如何利用docker快速构建MySQL主从复制环境

利用Docker-Compose快速搭建个人博客(5分钟简单操作)

利用docker-compose快速部署测试用数据库服务器

docker环境安装mysqlcanalelasticsearch,基于binlog利用canal实现mysql的数据同步到elasticsearch中

多容器配合实现开发环境(nginx+php+memcached+mysql)