文章转载自:http://www.mydlq.club/article/106/

系统环境:

  • Mysql 版本:8.0.23
  • Docker 版本:19.03.13

一、为什么需要 Mysql 主从复制

谈起为什么在大多数情况下部署 Mysql 常常使用 Mysql 主从模式进行部署这个问题,本来也去网上搜寻了一些答案,其中原因主要有以下几点:

  • 做数据的热备,主库宕机后备库能够及时替换主库,保证业务可用性,能一定程度避免数据丢失。
  • 实现读写分离,主库写,从库读,减小主库的读写压力。当主库执行写过程加锁时,不会堵塞从库读操作,从而提高了数据的查询效率。
  • 应对业务量越来越大,I/O 访问频率过高,单机无法满足的问题。增加多个从库做负载,能够降低整体 I/O 访问频率,提高单个机器 I/O 性能。

二、数据库常用的主从复制方式

基于 Binlog 复制模式

MySQL 主从复制默认是异步的模式。MySQL增删改操作会全部记录在 Binlog 中,当 slave 节点连接 master 时,会主动从 master 处获取最新的 Binlog 文件。并把 Binlog 存储到本地的 relay log 中,然后去执行 relay log 的更新内容。

GTID 复制模式

在传统的复制里面,当发生故障,需要主从切换,需要找到 Binlog 和 位点信息,恢复完成数据之后将主节点指向新的主节点。在 MySQL 5.6 里面,提供了新的数据恢复思路,只需要知道主节点的 IP、端口以及账号密码就行,因为复制是自动的,MySQL 会通过内部机制 GTID 自动找点同步。

接下来我们要部署的主从是基于GTID 复制模式。

三、GTID 概念相关介绍

GTID 是什么

GTID 指的是全局事务 ID,全程是 Global Transaction Identifier,在整个事务流程中每一个事务 ID 是全局唯一的,且在整个主从复制架构中该 ID 都不会相同。

GTID 主从复制方式

基于 GTID 的主从复制方式的出现,主要是用于替换传统的 日志点 复制方式。通过 GTID 可以保证每个主库提交的事务在集群中都有 唯一 的一个事务 ID。强化了数据库主从的一致性和故障恢复数据的容错能力,在 主库 宕机发生 主从切换 的情况下,GTID 方式可以让其他从库自动找到新主库复制的位置。而且 GTID 可以忽略已经执行过的事务,减少了数据发生错误的概率。

GTID 的组成

GTID 由 server_uuid + tid 组成,其中:

  • server_uuid: server_uuid 是在 Mysql 首次启动过程中自动生成的一个 uuid(128位) 随机值,生成后会将该值存储到数据目录的 auto.cnf 中。因为是随机值,所以不同服务器的 Mysql 的 server_uuid 都是不相同的。
  • tid: 代表了该实例上已经提交的事务数量,是一个整数,初始值是 1,每次提交事务的时候分配给这个事务并加 1。

其组成样式如下:

fb90fba5-60cf-11eb-b5fa-000c295fbc5f:21

GTID 复制工作原理

假设从库开启了 binlog,那么执行流程如下:

  • ① 主节点执行事务提交前会产生一个 GTID,其会随着事务一起记录到 binlog 日志中。
  • ② 从节点 I/O Thread 会读取主节点的 binlog 日志文件并存储在从节点的 relaylog 日志中。从节点将主节点的 GTID 这个值配置到 gtid_next 中,即下一个要读取的 GTID 值。
  • ③ 从节点读取 gtid_next 中的值,然后查找自己的 binlog 日志中是否有这个 GTID。
  • ④ 如果有这个记录,说明这个 GTID 的事务已经执行过了,就忽略掉。
  • ⑤ 如果没有这个记录,从节点就会执行该 GTID 事务,并记录到自己的 binlog 日志中。在读取执行事务前会先检查其他 session 中是否持有该 GTID,确保不被重复执行。
  • ⑥ 在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有就用全部扫描。

GTID 使用中的限制条件

GTID 复制是针对事务来说的,一个事务只对应一个 GTID,好多的限制就在于此。其中主要限制如下:

  • 不能使用 create table table_name select * from table_name。
  • 在一个事务中既包含事务表(使用 InnoDB 存储引擎的表)的操作又包含非事务表(使用 MyISAM 存储引擎的表)。
  • 不支持创建或删除临时表操作,如 CREATE TEMPORARY TABLE or DROP TEMPORARY TABLE 语句操作。
  • 使用 GTID 复制从库跳过错误时,不支持执行该 ql_slave_skip_counter 参数的语法。

如何开启 GTID 模式

需要在 Mysql 配置文件中添加下面几条配置:

## 开启 gtid 模式
gtid_mode=on ## 配置不允许任何事务违反 GTID 一致性,用于保证数据一致性
enforce_gtid_consistency=on ## 开启 Binlog 并指定名称(可选)
log_bin=binlog ## 从节点从主节点接收到更新且执行,是否将记录存到从节点的 binlog 日志中(可选)
log-slave-updates=1 ## 当从数据库启动的时候,从节点不会启动复制(可选)
skip-slave-start=1

四、准备部署环境

服务器IP 角色 配置文件目录 数据存储目录
192.168.2.11 主节点 /apps/mysql /apps/mysql/data
192.168.2.12 从节点 /apps/mysql /apps/mysql/data

五、Docker 部署主节点

创建挂外的数据存储目录

创建 Mysql 的 Docker 镜像的外挂数据存储目录:

这个目录是本人创建的数据存储目录,实际部署需要修改为需要部署应用的服务器的存储目录。

$ mkdir -p /apps/mysql/data

创建主节点配置文件

在目录 /apps/mysql 中创建 Mysql 主节点的配置文件 my.cnf,内容如下:

[mysqld]
port = 3306
max_connections = 2000
default-time_zone='+8:00' sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION #gtid:
server_id = 1 #服务器id
gtid_mode = on #开启gtid模式
enforce_gtid_consistency = on #强制gtid一致性,开启后对于特定create table不被支持 #binlog
log_bin = mysql-binlog
log_slave_updates = on
binlog_format = row #强烈建议,其他格式可能造成数据不一致 #relay log
skip_slave_start = 1 default_authentication_plugin = 'mysql_native_password' #更改加密方式

MySQL8.0 之前 mysql 密码加密方式为 mysql_native_password,而 MySQL8.0 版本默认新添加的用户密码默认使用的 caching_sha2_password,因此进行使用主从复制时可能会遇到错误,需要将加密方式改成 mysql_native_password。

部署 Mysql 主节点

部署 Mysql 的主节点,执行的 Docker 命令如下:

$ docker run --name mysql-a -d \
--restart=always \
--network=host \
-v /apps/mysql/my.cnf:/etc/mysql/conf.d/my.cnf \
-v /apps/mysql/data:/var/lib/mysql \
-v /etc/localtime:/etc/localtime \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:8.0.23
  • 配置 restart=always,设置容器挂掉后总是重启。
  • 配置 network=host,设置容器使用宿主机的网络。
  • 挂载 /apps/mysql/my.cnf 来配置 Mysql 配置文件。
  • 挂载 /apps/mysql/data 来配置 Mysql 数据存储。
  • 挂载 /etc/localtime 来配置 Docker 运行容器的时区。
  • 配置 MYSQL_ROOT_PASSWORD 环境变量,设置 Mysql 数据库的 root 密码。

创建鉴权用户

进入 MySQL 的 Master 容器中,使用客户端工具连接 MySQL Server:

$ docker exec -it mysql-a mysql -uroot -p123456

输入下面命令创建鉴权用户并赋与权限:

## 创建用户 repl 密码为 123456
$ create user 'repl'@'%' identified by '123456'; ## 赋予用户 repl 权限
$ grant replication slave,replication client on *.* to 'repl'@'%'; ## 刷新权限
$ flush privileges;

六、Docker 部署从节点

创建存储数据的目录

$ mkdir -p /apps/mysql/data

创建从节点配置文件

在目录 /apps/mysql 中创建 Mysql 从节点的配置文件,内容如下:

[mysqld]
port = 3306
max_connections = 2000
default-time_zone = '+8:00' sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION #GTID:
server_id = 2 #服务器id
gtid_mode = on #开启gtid模式
enforce_gtid_consistency = on #强制gtid一致性,开启后对于特定create table不被支持 #binlog
log_bin = mysql-binlog
log_slave_updates = on
binlog_format = row #强烈建议,其他格式可能造成数据不一致 #relay log
skip_slave_start = 1
default_authentication_plugin = 'mysql_native_password' #更改加密方式 read_only = on #设置只读

部署 Mysql 从节点

执行下面 Docker 命令,部署 Mysql 从节点:

$ docker run --name mysql-b -d \
--restart=always \
--network=host \
-e MYSQL_ROOT_PASSWORD=123456 \
-v /apps/mysql/my.cnf:/etc/mysql/conf.d/my.cnf \
-v /apps/mysql/data:/var/lib/mysql \
-v /etc/localtime:/etc/localtime \
mysql:8.0.23

从节点连接主节点

进入 Mysql Slave 镜像内部,使用客户端工具连接该 Msyql Server:

$ docker exec -it mysql-b mysql -uroot -p123456

配置从库连接主库:

$ CHANGE MASTER TO
master_host='192.168.2.11',
master_port=3306,
master_user='repl',
master_password='123456',
master_auto_position=1;

注:master_host 需要改为你的主节点 IP 地址,用户名密码要和上面创建的用户密码一致。

启动从库:

$ start slave;

查看连接状态:

$ show slave status\G

*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.2.11
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-binlog.000003
Read_Master_Log_Pos: 886
Relay_Log_File: node-02-relay-bin.000003
Relay_Log_Pos: 1107
Relay_Master_Log_File: mysql-binlog.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 886
Relay_Log_Space: 3129553
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_UUID: f5c69d56-694c-11eb-800e-000c29e6fc4e
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set: f5c69d56-694c-11eb-800e-000c29e6fc4e:1-8
Executed_Gtid_Set: 13f0092c-694d-11eb-aba6-000c29262359:1-5,
f5c69d56-694c-11eb-800e-000c29e6fc4e:1-8
Auto_Position: 1
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:

七、进行测试

主库创建测试库、表并插入数据

在主节点服务器上执行下面命令,进入 mysql 客户端:

$ docker exec -it mysql-master mysql -uroot -p123456

然后执行下面命令创建测试库、表并插入测试数据:

##创建名为 test 的数据库
$ CREATE DATABASE test; ##使用 test 数据库
$ USE test; ##创建 user 表
$ CREATE TABLE `user` (
`id` int(0) NOT NULL,
`name` varchar(20) NULL DEFAULT NULL
); ##插入测试数据
$ INSERT INTO `user` VALUES (1, 'mydlq');

从库查看是否存在库与表和对应数据

在从节点服务器上执行下面命令,进入 mysql 客户端:

$ docker exec -it mysql-slave mysql -uroot -p123456

然后执行下面命令

##查看全部数据库
$ SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+ ##使用 test 数据库
$ USE test; ##查看全部表
$ SHOW TABLES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+ ## 查看 user 表中数据
$ SELECT * FROM `user`;
+----+-------+
| id | name |
+----+-------+
| 1 | mydlq |
+----+-------+

如果从库中能正常执行上面命令且存在测试数据,则证明主从配置没有问题。

通过 Docker 部署 Mysql 8.0 主从模式的更多相关文章

  1. Docker:Docker部署mysql数据库

    docker部署mysql : 8.0 1.在宿主机创建mysql挂载目录 #创建目录 mkdir /home/mysql/conf mkdir /home/mysql/logs mkdir /hom ...

  2. springboot多数据源配合docker部署mysql主从实现读写分离

    本篇主要有两部分: 1.使用docker部署mysql主从 实现主从复制 2.springboot项目多数据源配置,实现读写分离 一.使用docker部署mysql主从 实现主从复制 此次使用的是wi ...

  3. Docker 部署 RocketMQ Dledger 集群模式( 版本v4.7.0)

    文章转载自:http://www.mydlq.club/article/97/ 系统环境: 系统版本:CentOS 7.8 RocketMQ 版本:4.7.0 Docker 版本:19.03.13 一 ...

  4. Docker 部署mysql

    目录 Docker 部署mysql 步骤 1.查找 Docker Hub 上的 MySQL 镜像 2.docker pull mysql 拉取镜像 3.运行容器 4.查看容器启动情况 使用命令备注 D ...

  5. docker(部署常见应用):docker部署mysql

    上节回顾:docker(部署常见应用):docker部署nginx docker部署mysql:5.7.26 # 下载镜像 docker pull mysql: # 查看镜像 docker image ...

  6. docker部署mysql Navicat远程连接

    docker部署mysql Navicat远程连接 docker search mysql   查看mysql镜像(是去dockerHub网站搜素镜像,遇到问题可以去该网站查看官方文档,纯英文文档估计 ...

  7. Docker部署mysql 5.7

    Docker部署mysql 5.7 准备工作 在CentOS或者Linux创建部署目录,用于存放容器的配置和MySQL数据:目的是当重装或者升级容器时,配置文件和数据不会丢失.执行以下命令: a.创建 ...

  8. docker 安装 MySQL 8.0

    1.查找镜像 查找Docker Hub上的mysql镜像 X230:~$ docker search mysql NAME DESCRIPTION STARS OFFICIAL AUTOMATED m ...

  9. docker 部署mysql tomcat时 在root@localhost~下——-——docker exec -it 容器名 /bin/bash 报错

    在docker部署mysql时 报错 找不到 容器不自动启动  , docker start 容器名  也没有效果 多次尝试发现 原因是创建容器时在 下面创建的 更改为下创建 问题解决

随机推荐

  1. github package的使用教程

    一.写在前面 上一次,笔者向大家介绍了把gitlab仓库作为npm私包的使用方法,具体的详见我的博文地址https://www.cnblogs.com/cnroadbridge/p/16406476. ...

  2. zip格式文件编码检测

    解压后文件名乱码 由于zip格式文件无编码存储的结构,因此解压时无法知道原先的编码. 当解压zip格式文件时使用的编码和原编码不一致时,就可能会出现解压后文件名乱码问题. 猜测编码 基于上述问题,需要 ...

  3. Code Runner for VS Code,下载量突破 4000 万!支持超过50种语言

    大家好! 我是韩老师.还记得 6 年前的夏天,我在巨硬写着世界上最好的语言,有时也需要带着游标卡尺写着另一门语言.然而,我对这两门语言都不熟悉,如果能在 VS Code 中方便快捷地运行各种语言,那岂 ...

  4. 多线程与高并发(一)—— 自顶向下理解Synchronized实现原理

    一. 什么是锁? 在多线程中,多个线程同时对某一个资源进行访问,容易出现数据不一致问题,为保证并发安全,通常会采取线程互斥的手段对线程进行访问限制,这个互斥的手段就可以称为锁.锁的本质是状态+指针,当 ...

  5. Java开发学习(十六)----AOP切入点表达式及五种通知类型解析

    一.AOP切入点表达式 对于AOP中切入点表达式,总共有三个大的方面,分别是语法格式.通配符和书写技巧. 1.1 语法格式 首先我们先要明确两个概念: 切入点:要进行增强的方法 切入点表达式:要进行增 ...

  6. React报错之无法在未挂载的组件上执行React状态更新

    正文从这开始~ 总览 为了解决"Warning: Can't perform a React state update on an unmounted component" ,可以 ...

  7. CSP AFO后可以公开的情报

    10.08 早上和下午准备初赛,晚上考了套题,然后就摸文化课去了. \(250/250\) 手动模拟确实效果好 经验是把双刃剑,读题细致才是王道 T3是分治,一看到1e5的数据就习惯性往数据结构想,一 ...

  8. MybatisPlus——全网配置最全的代码生成器

    MybatisPlus代码生成器 这里讲解的是新版 (mybatis-plus 3.5.1+版本),旧版不兼容 官方文档:https://baomidou.com/(建议多看看官方文档,每种功能里面都 ...

  9. tty的crash分析

    crash> btPID: 410629 TASK: ffff883fea379fa0 CPU: 10 COMMAND: "jupyter-lab"#0 [ffff8823c ...

  10. 快速掌握 Base 64 | 学 Java 密码系列

    Java 密码系列 - Java 和 JS Base 64 Base 64 不属于密码技术,仅是编码方式.但由于在 Java.JavaScript.区块链等出现的频率较高,故在本系列文章中首先分享 B ...