利用 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"
    ]
  }

一. 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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343