阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

基于Docker实现MySQL主从复制

197次阅读
没有评论

共计 2954 个字符,预计需要花费 8 分钟才能阅读完成。

前言

MySQL的主从复制是实现应用的高性能,高可用的基础。对于数据库读操作较密集的应用,通过使数据库请求负载均衡分配到不同 MySQL 服务器,可有效减轻数据库压力。当遇到 MySQL 单点故障中,也能在短时间内实现故障切换。本文就 MySQL 的内建的复制功能进行阐述。

版本

  • MySQl5.7.17
  • CentOS7.4.1708
  • Docker1.13.1

概述

MySQL复制数据流程:

  1. 主库在数据更新提交事务之前,将事件异步记录到 binlog 二进制日志文件中,日志记录完成后存储引擎提交本次事务
  2. 从库启动一个 I / O 线程与主库建立连接,用来请求主库中要更新的 binlog。这时主库创建的 binlog dump 线程,这是二进制转储线程,如果有新更新的事件,就通知 I / O 线程;当该线程转储二进制日志完成,没有新的日志时,该线程进入 sleep 状态。
  3. 从库的 I / O 线程接收到新的事件日志后,保存到自己的 relay log(中继日志)中
  4. 从库的 SQL 线程读取中继日志中的事件,并执行更新保存。

基于 Docker 实现 MySQL 主从复制

配置主从库

主库 my.cnf 配置

在主库的 my.cnf 中打开二进制日志,并设置服务 Id。

log-bin = mysql-bin
server-id = 1

注意 server-id 必须是一个唯一的数字,必须主从不一致, 且主从库必须设置项。

从库 my.cnf 配置

log-bin = mysql-bin
server-id = 2
log-slave-updates = 1
read-only = 1

从库也开启 log-binlog-slave-updates 设置为从库重放中继日志时,记录到自己的二进制日志中,可以让从库作为其他服务器的主库,将二进制日志转发给其他从库,在做一主多从方案时可考虑该种方案。

Dockerfile 构建 MySQL 镜像

构建所需文件

这里 masterslave文件各自保存不共用,先创建文件夹 /usr/local/mysql 然后在目录创建 masterslave两个目录,再各自创建 data 文件夹

基于 Docker 实现 MySQL 主从复制

  • data 目录用来保存数据文件的目录
  • Dockerfile 保存 Dockerfile 内容
  • init.sql 初始化数据库的 SQL
  • my.cnf 数据库配置文件,配置方式上面已提到
  • start.sh Dockerfile 构建 MySQL 时的脚本

Dockerfile 内容

# 利用 mysql 镜像创建新的镜像
FROM mysql:5.7.17

ENV MYSQL_ROOT_PASSWORD ytao

COPY start.sh /mysql/start.sh
COPY my.cnf /etc/mysql/my.cnf  
COPY init.sql /mysql/init.sql

EXPOSE 3306
CMD ["sh", "/mysql/start.sh"]

这里的 masterslave都是基于同一个镜像构建,使用的存储引擎和其他的组件最好是同一中,不然在复制过程中可能会出现异常。

init.sql 初始化数据

-- 创建 data_copy 数据库
DROP DATABASE IF EXISTS `data_copy`;
CREATE DATABASE `data_copy` /*!40100 DEFAULT CHARACTER SET utf8mb4 collate utf8mb4_general_ci */;

-- 创建 person 表
USE `data_copy`;
DROP TABLE IF EXISTS `person`;
CREATE TABLE `person` (`id` int(32) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

创建 data_copy 数据库和 person 表。

start.sh 脚本

#!/bin/sh
echo '启动 mysql'
service mysql start
sleep 5

echo '初始化数据库'
mysql -uroot -pytao < /mysql/init.sql
echo '初始化完成!'
tail -f /dev/null

构建 masterslave镜像并运行容器

构建 master 镜像

docker build -t master/mysql .

构建 slave 镜像

docker build -t slave/mysql .

构建成功会返回 Successfuly,或通过 docker images 命令查看镜像

基于 Docker 实现 MySQL 主从复制

使用刚构建的镜像来运行容器

# master 容器
docker run --name master -p 3306:3306 -v /usr/local/mysql/master/data/:/var/lib/mysql -d master/mysql

# slave 容器
docker run --name slave -p 3307:3306 -v /usr/local/mysql/slave/data/:/var/lib/mysql -d slave/mysql

指定 master 端口为 3306,slave 端口为3307,挂载 data 目录为保存数据的目录。

连接到数据库后验证数据库是否初始化成功

基于 Docker 实现 MySQL 主从复制

查看 log-bin 是否开启

基于 Docker 实现 MySQL 主从复制

创建复制账号

前面有提到从库 I / O 线程要与主库建立连接,所以需要用到账号进行验证。账号除了要有连接权限(REPLICATION CLIENT),同时还要有复制权限(REPLICATION SLAVE)。

GRANT REPLICATION CLIENT, REPLICATION SLAVE ON *.* TO muser@'%' IDENTIFIED BY 'ytao';

这里设置的访问地址是开放的,实际使用过程中安全起见一定要指定访问地址。

从库启动复制

从库连接到主库,获取到二进制日志后重放。这里首先要配置上面创建的账号进行连接,使用命令进行相应的设置。

CHANGE MASTER TO 
MASTER_HOST = '47.107.xx.xxx',
MASTER_PORT = 3306,
MASTER_USER = 'muser',
MASTER_PASSWORD = 'ytao',
MASTER_LOG_FILE = 'mysql-bin.000006';

到这里复制还没有启动,需要再从库中启动

START SLAVE;

使用 SHOW SLAVE STATUS\G; 命令查看启动后的情况

基于 Docker 实现 MySQL 主从复制

上面标记的输出信息 Slave_IO_Running: YesSlave_SQL_Running: Yes可以看到 I / O 线程和 SQL 线程已启动运行中。

测试同步数据

如果在主库中添加,更新或删除一个数据,那么从库中应该也有与主库对应的数据变化。
向主库添加一条数据

INSERT INTO `data_copy`.`person` (`id`, `name`) VALUES ('1', 'ytao');

查询从库数据,数据已被同步过来。

基于 Docker 实现 MySQL 主从复制

总结

上述是最简单最基本的配置,但是理解上面的配置过程,就可以根据自身情况定制不同方案,实现一主多从,主主复制(主动 - 主动或主动 - 被动模式)等等来满足自身需求。
MySQL的复制虽然使用简单方便,但也伴随着一些问题需要我们在使用中进行解决,比如:不能从服务器异常停止中恢复,数据同步的延迟等等,还好现在遇到的大部分问题在行业中已得到相应的解决。对这方面感兴趣的可以去了解下现在解决这些问题的中间件实现方案。

正文完
星哥说事-微信公众号
post-qrcode
 
星锅
版权声明:本站原创文章,由 星锅 2022-01-22发表,共计2954字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中