# MySql 复制功能介绍

MySql 的复制功能提供分担读负载,对的,只是读负载而不是写负载,而且 MySql 的复制为高可用、灾难恢复、备份提供更多的选择。

MySql 的复制是基于主库的二进制日志。复制是异步的,所以同一时间点上,主从可能不一致,这也是不可控的。

复制解决了什么问题

  1. 实现在不同服务器上的数据分布,复制利用了二进制日志增量来进行的。通常情况下基于语句的复制不需要太多的带宽,但是使用基于行的复制在进行大批量的更改时会对带宽带来一定的压力,特别是在跨 IDC 环境下进行复制。无论如何对于大批量数据的修改都应该通过分批方式来进行的。
  2. 实现数据读取的负载均衡。可以利用 DNS 轮询的方式把程序的读连接到不同的备份数据库。或者使用 LVS,haproxy 这样的代理方式实现读取负载均衡。
  3. MySql 的复制是非共享架构,同样的数据分布在多台服务器上,所以增加了数据的安全性。我们可以利用备库的备份来减少主库负载。但是我们要注意,复制不能代替备份。
  4. 实现数据高可用和故障切换
  5. 实现数据库在线升级。

# MySql 二进制日志

之前的文章中我提到了重做日志和回滚日志,这些都是 MySql 存储引擎层的日志,对于 MySql 服务层的日志有二进制日志,慢查询日志,通用日志。所以我们这里将的二进制日志属于 MySql 服务层的日志和存储引擎无关。

二进制日志记录了所有对 MySql 数据库的修改事件,包括增删改查事件和对表结构的修改事件。二进制日志文件记录的是成功执行了的操作,对于失败的操作不会记录。我们可以通过 MySql 提供的 binlog 工具来查看二进制日志。 在记录二进制日志时,MySql 提供了 3 种格式进行存储,可以通过 binlog_format 来控制使用哪种格式进行记录。

# 基于段的格式

binlog_format=STATEMENT

优点:

日志记录量相对较小,节约复制时的磁盘及网络(只对一条记录修改或者插入时,row 格式所产生的日志量小于段产生的日志量)

缺点:

1.必须要记录上下文信息,保证语句从服务器上执行结果和在主服务器上相同。

2.对于特定函数如 UUID(),user()这样非确定性函数还是无法复制,所以可能造成 MySql 复制的主备服务器数据不一致。

我们通过实战来看一下段格式的日志。连接到我们的 MySql 上,如下图所示,我们使用了 MySql8.0 的版本,刚开始看到 binlog_format 是 row 格式的,我们把它切换到 STATEMENT 格式:

img

为了方便我们的演示,我们刷新一下 binlog:

img

接下来的操作都会记录到 binlog.000025 中去。我们开始创建数据库然后插入修改记录,如下图所示:

img

记录完后,我们看一下我们的 binlog 存在哪个盘:

img

查看下 binlog 怎么记录的:

img

img

# 基于行的日志格式

binlog_format=ROW

Row 格式可以避免 MySql 复制中出现的主从不一致问题。相比于段格式,如果同一 SQL 语句修改了 10000 条数据的情况下,基于段的日志格式只会记录这个 SQL 语句,基于行的日志会有 10000 条记录分别记录每一行的数据修改。

优点:

使 MySql 主从复制更加安全;

对每一行数据的修改比基于段的复制高效;

另外对于误操作而修改了数据库中的数据,同时又没有备份可以恢复时,我们就可以通过分析二进制日志,对日志中记录的数据修改操作做反向处理的方式来达到恢复数据的目的。

缺点:

记录日志量较大。MySql 考虑到由于其记录日志量太大,所以使用 binlog_row_image 来做一些相关配置。binlog_row_image=[FULL|MINIMAL|NOBLOB]。FULL 表示每个字段都记录下来,比如我们一行数据有 20 个列,update 只更新了一个列,FULL 会把所有的列都记录下来,但是 MINIMAL 就只会记录修改的这一列,NOBLOB 的意思就是说如果修改的列不涉及 TEXT 或者 BLOB 类型,那么这种列就不会记录。

OK,我们还是来实战看一下,如下图所示,我们把 binlog 的格式改成下面的样子,然后在看看当前我们的 row_image 是 full:

img

还是基于刚才的表,为了看到 NOBLOB 的效果,这时我把刚才的表添加一列,然后做下面的一些操作:

img

这个时候我们来看一下 binlog 中的信息,不过和刚才的命令有些不同,我们要加一个-vv 参数,否则 binlog 展示的信息不是我们能看得懂的东东:

img

接下来我们看一下 minimal 模式的记录情况:

img

然后看看 binlog,如下图所示,我们发现只记录了第三列的值,没有所有的列都记录

img

基于 NOBLOB 的格式我们就不再演示了,有兴趣的同学可以自己动手看一下。

# 混合日志格式

binlog_format=MIXED

特点:可以根据 SQL 语句由系统决定在基于段和基于行的日志格式中进行选择;数据量的大小由所执行的 SQL 语句决定

讲了这三种日志格式,那么我们应该如何选择二进制格式呢?抛开业务场景的话,个人建议还是使用 Binlog_format=mixed 或者是 binlog_format=row 且 binlog_row_image=minimal 的方式

# MySql 二进制日志格式对复制的影响

# MySql 的复制有以下几种方式:

# 基于 SQL 语名的复制(SBR)

二进制日志格式使用的是 statement 格式。 优点:生成的日志量少,节约网络传输 I/O;并不强制要求主从数据库的表定义完全相同;相比于基于行的复制方式更为灵活。 缺点:对于非确定性事件,无法保证主从复制数据的一致性;对于存储过程,触发器,自定义函数进行的修改也可能造成数据不一致;相比于基于行的复制方式在从服务器上执行时需要更多的行锁

# 基于行的复制(RBR)

二进制日志格式使用的是基于行的日志格式 优点:可以应用于任何 SQL 的复制包括非确定函数,存储过程等;可以减少数据库锁的使用。 缺点:要求主从数据库的表结构相同,否能可能会中断复制。无法在从服务器上单独执行触发器。 所以基于行的复制对主从数据的一致性更加有保证。

# 混合模式

根据实际内容在以上两者间切换

# MySql 的复制工作方式:

数据库写二进制日志不一定是打开的,所以一定要确保打开。虽然可以上线后打开,但是这样要重新启动数据库,对业务影响很大,所以建议一开始就把这个给打开。 复制分为 3 步走,如下图所示:

img

其中第二步主库启动二进制转储线程,称之为 binlogdump,从库的 IO 线程通过这个 dump 线程读取二进制日志中的事件。

# 基于日志点的复制配置步骤

1.在主 DB 服务器上建立复制账号,并且授权给这个账号,如下图所示:

img

2.配置主数据库服务器

img

3.配置从数据库服务器

img

一般情况下 slave 不会把从 master 接收到的 binlog 记录写入自己的 binlog,log_slave_update 参数会使 slave 通过 SQL 线程把从 master 接受到的 binlog 写进自己的 binlog,但是前提是 slave 一定要开启自己的 binlog,此参数一般用于级联复制,例如需要 A 复制到 B,B 复制到 C,那么 B 就要开启此参数。

4.备份主数据库中的数据,对从库进行初始化

img

5.启动服务链路

img

这样看可能很抽象,接下来我们实战一把!

第一步建立用户:

img

第二步配置文件:

在 MySql 配置文件中配置 server_id 唯一:

img

配置文件中配置配置 binlog

img

第三步配置从数据库:

img

server_id 和主库的不一样,而且还配置了 relay_log,并且也配置了 binlog 如下图所示:

img

第四步:

在主服务器上执行以下命令,备份数据:

img

把备份好的 sql 复制到从库上面去:

img

然后到从库上,把这个 all.sql 导入到数据库中去:

img

第五步,非常复杂的一步:

在从服务器上执行以下命令:

img

其中 MASTER_LOG_FILE 和 MASTER_LOG_POS 这两个参数怎么来的呢?

我们在 all.sql 中会看到这么一句话:

img

执行这句话后,接下来继续在从服务器上执行 show slave status \G 命令:

img

发现还没启动链路,我们使用 start slave 命令进行启动。

img

看下从服务器上,有另两个线程已经启动了:

img

接下来看一下主服务器上的信息:

我们看到了 binlog Dump 线程已经启动了,它就是读取 binlog 的线程

img

基于日志点的复制优点:

是 MySql 最早支持的复制技术,Bug 相对较少;对 SQL 查询没有任何限制;故障处理比较容易

缺点:故障转移时重新获取新主的日志点信息比较困难

# 基于 GTID 的复制

什么是 GTID,GTID 是全局事务 ID,其保证为每一个在主服务器上提交的事务在复制集群中可以生成一个唯一的 ID

GTID=source_id:transaction_id

在刚才我们讲解了基于日志的复制,但是基于日志的复制会有以下缺点:

img

基于 GTID 复制的原理如下:

img

从库会告诉主库已经执行事务的 GTID 值,主库会发送从库没有执行事务的 GTID 值,同一个事务只在指定的从库执行一次。

基于 GTID 进行复制的步骤如下:

第一步:

和基于日志的复制一样

img

第二步: 相比于基于日志的复制多了一个 gtid_mode=on 的步骤

img

第三步:

配置 enforce-gtid-consistency 和 log-slave-updates=on 这两个参数,但是 MySql5.7 版本之后 log-slave-updates 这个参数已经不用再配置了。同时要注意的是 enforce-gtid-consistency 开启后,就不能在使用 create table ... select 这种语句了。

第四步:

配置从数据库服务器:

server_id=101

relay_log=/usr/local/MySql/log/relay_log

gtid_mode=on

enforce-gtid-consistency

log-slave-updates=on

read_only=on[建议]

master_info_repository=TABLE[建议] 默认连接 master 的信息是存储在文件中的,这样可以存储在表中

relay_log_info_repository=TABLE[建议] 存储日志的信息默认是在文件中的,这样可以存储在表中

第五步:

初始化从服务器数据 MySqldump --master-data=2 -single-transaction xtarbackup --slave-info 记录备份时最后的事务的 GTID 值 第六步:

img

接下来,我们通过实战的方式看看:

第一步刚才我们已经做过了,这里就省去了。

第 2-3 步:

在主库的配置文件中加入配置项

img

第 4 步在从服务器上:

img

然后重启主从数据库,让配置生效

第五步:

主库上先备份

img

然后复制到从库

img

在从库上导入数据

img

第六步:

在从库上执行以下操作:

img

基于 GTID 复制的优缺点:

优点:可以很方便的进行故障转移;从库不会丢失主库上的任何修改

缺点:故障处理比较复杂;对执行的 SQL 有一定的限制

那么介绍了这两种复制模式,我们应该选择哪种复制模式呢?

首先我们要考虑 MySql 的版本问题,不是任何版本都支持 GTID 的;其次复制架构及主从切换的方式,使用 GTID 更方便些;还有所使用的高可用管理组件;对应用的支持程度。

# MySql 复制拓扑

img

# 1.一主多从的拓扑

img

一主多从的复制拓扑

img

一主多从的用途

# 2.主-主复制拓扑

2.1 主备模式的主主复制,同一时刻只有一个主库在提供服务,如下图所示

img

主备模式的主主复制

一台服务器处于只读状态并且只作为热备使用。在对外提供服务的主库出现故障或是计划性的维护时才会进行切换,使原来的备库成为主库,而原来的主库会成为新的备库并处理只读或是下线状态,待维护完成后重新上线。这种模式下,要确保两台服务器上的初始数据相同,确保两台服务器上已经启动 binlog 并且有不同的 server_id。在两台服务器上弃用 log_slave_updates 参数。在初始的备库上启用 read_only。

2.2 主主模式的主主复制,同一时刻两个主库都在提供服务,但是千万不要认为这种模式可以分担主库的写负载,如下图所示:

img

主主模式的主主复制

主主模式下,很容易产生数据冲突而造成复制链路的中断,而且极易造成数据丢失,耗费大量的时间。所以最好两个主中所操作的表最好能够分开或者使用 auto_increment_increment=2 以及 auto_increment_offset=1|2 参数控制自增 ID 的生产。这种模式很不建议使用!

# 3.拥有备库的主-主复制拓扑

img

4.级联复制

img

级联复制

这种模式下,需要让分发主库(其实也是一个从库)启动 log_slave_updates 参数。

# MySql 复制性能优化

在优化之前,我们先想一想 MySql 复制影响主从延迟的因素有哪一些?

  • 主库写入二进制日志的时间 为了解决这个因素,我们可以尝试控制主库的事务大小,把大事务分割成小事务。
  • 二进制日志传输时间 可以使用 MIXED 日志格式或者设置 set binlog_row_image=minimal;
  • 默认情况下从数据库只有一个 SQL 线程,主上并发的修改在从上变成了串行 我们可以使用多线程进行复制,但是要注意的是,一个线程针对的是一个数据库,如果说我们的应用只是对一个库进行读写,那没必要开启多线程,开启了多个线程反而还会降低性能。在 MySql5.7 中可以按照逻辑时钟的方式来分配 SQL 线程。 如何配置多线程复制: 1.stop slave 停止链路复制 2.set global slave_parallel_type='logical_clock'表示是使用逻辑时钟的方式分配 SQL 线程 3.set global slave_parallel_workers=4 表示分配 4 个线程 4.start slave;开始链路复制

# 复制常见问题处理

  • 主库或从库意外宕机引起的错误 可以使用跳过二进制日志事件的方式或者注入空事务先回复中断的复制链路,再使用其他方法来对比主从服务器上的数据。
  • 主库上的二进制日志损坏 可以通过 change master 命令来重新制定。但是这样丢失部分数据
  • 备库上的中继日志损坏 这个影响还好,可以重新同步一下主库上的日志就可以了
  • 在从库上进行数据修改造成的主从复制错误 引起这个错误的原因往往是没有把从库设置为 read_only
  • 不唯一的 server_id 或者 server_uuid server_uuid 是记录在数据目录中的 auto.cnf 文件中的
  • max_allow_packet 设置引起的主从复制错误 MySql 复制虽然帮助我们解决了很多问题,也提供了很好的读性能,但是它始终无法解决以下问题:
  • 分担主数据库的写负载,分担写负载只能通过分库分表的方式来进行
  • 自动进行故障转移及主从切换。很可惜始终需要人为来控制
  • 提供读写分离功能。 既然还有这么多问题没有解决,接下来就进入到我们本篇文章中的核心,高可用架构设计。写了这么一大堆,终于到这里了,我知道很多人想吐槽我了。。

# 高可用架构

# 1.什么是高可用

高可用性 H.A.(High Availability)指的是通过尽量缩短因日常维护操作(计划)和突发的系统崩溃(非计划)所导致的停机时间,以提高系统和应用的可用性 有人为可不可以保证数据库 100%的高可用。那是当然不可以的,因为严重的主从延迟,主从复制中断和锁引起的大量阻塞都不可能保证 100%的可用。一般来说我们用正常可用时间和全年时间百分比两个维度来衡量数据库的高可用性。假设我们要达到 1 年 5 个 9 的高可用性,那么 3652460*(1-0.99999)=5.256,一年就只允许不可用 5.256 分钟,难度贼大。

# 2.不可用的因素

2.1 服务器磁盘空间耗尽 部分人觉得有的是钱,磁盘不贵,怎么可能出现这种情况。其实备份或者各种查询日志突增都可能导致磁盘空间被占满。MySql 由于无法记录二进制日志,无法处理新的请求而产生的系统不可用的故障。 2.2 性能糟糕的 SQL 2.3 表结构和索引没有优化 2.4 主从数据不一致 2.5 人为的操作失误

# 3.如何避免系统的不可用的因素,减少系统不可用的时间

3.1 建立完善的监控及报警系统 报警太多大家会松懈,报警太少职业生涯可能要报销 3.2 对备份数据进行恢复测试 3.3 正确配置数据库环境 比如从库只能 read_only 3.4 对不需要的数据进行归档和清理 这样可以加快查询,节省空间 3.5 增加系统冗余,保证发生系统不可用时可以尽快回复 单纯的增加从服务器只能避免从节点单点故障,但是主节点依然是单点!一定要注意。 主从切换及故障转移是系统冗余的一个难点。 大致了解了后,接下来我们就来看怎么解决这些问题

# 4.单点故障

单点故障是指在一个系统中提供相同功能的组件只有一个,如果这个组件失效了,就会影响整个系统功能的正常使用。组成应用系统的各个组件都有可能成为单点

# 4.1 如何避免 MySql 单点故障

# 4.1.1 利用 SUN 共享存储或 DRDB 磁盘复制解决 MySql 单点故障

SUN 共享存储是几个服务器共享一个磁盘,同一时刻只有一个服务器对外提供服务,如果其中一个服务宕机了,就由另外一个服务器对外提供服务。如下图所示:

img

问题在于磁盘是单点的,所以共享存储并不是一种好的解决单点故障的方式 DRDB 的方式如下图所示:

img

DRDB

# 4.1.2 利用多写集群或 NDB 集群来解决 MySql 单点故障

多写集群目前用的最多的是 Percona 公司提供的 pxc 架构,如下图所示:

img

所有的服务器上的事务都必须提交成功了,才能算成功,否则全部回滚,所以这种架构写性能受集群中性能最差的服务器的影响。也并不常用。 在 NDB 集群中,所有的节点进行主主复制,可以对每个节点进行写入,但是问题就在于如果内存不足,NDB 集群的性能就会非常的差,所以 NDB 很少被使用到生产环境中

# 4.1.3 利用 MySql 主从复制来解决 MySql 单点故障

刚才我们也说了,主要的是解决主节点的单点故障问题。主服务器切换后如何通知应用新的主服务器的 IP 地址;另外如何检查 MySql 主服务器是否可用;如何处理从服务器和新主服务器之间的那种复制关系,都是亟待解决的问题

# MMM 架构

MMM 架构全程 Multi-Master Replication Manager。它主要是监控和管理 MySql 的主主复制拓扑,并在当前的主服务器失效时,进行主和主备服务器之间的主从切换和故障转移等工作。主主复制有主动主动模式和主动被动模式两种,MMM 用于主动被动模式的主主复制。它可以监控 MySql 主从复制健康情况,在主库出现宕机时进行故障转移并自动配置其他从服务器对新主服务器的复制。MMM 要解决的问题是如何找到从库对应的新的主库日志同步点以及多个从库出现数据不一致的情况。MMM 提供了主,写虚拟 IP,在主从服务器出现问题时可以自动迁移虚拟 IP。MMM 架构如下图所示:

img

MMM 架构

建立 MMM 架构需要的资源如下:

img

MMM 架构资源

# 1.MMM 架构实例演示

1.1MMM 安装大致步骤

  • 配置主主复制及主从同步集群

  • 安装主从节点所需要的支持包

  • 安装及配置 MMM 工具集

  • 运行 MMM 监控服务

  • 测试

    1.2 top 图结构 我们这里提供两个主服务器,一个从服务器,MMM 安装在从服务器上

img

1.3 真实实战 1.3.1 在 100 的主服务器上备份数据

img

备份

1.3.2 复制到另外一个主服务器上面

img

复制

1.3.3 在 101 上导入 100 上的数据

img

image.png

1.3.4 在 101 上启动复制

img

在 101 上我们看到主是 100

img

1.3.5 由于现在是主主,所以我们还要回到 100 机器上,去同步 101 上的数据

img

在 100 上我们看到主是 101

img

1.3.6 到 102 从服务器上进行配置

先导入数据

img

开始复制

img

我们的 top 搭建好了,重头戏开始:

1.3.7 在 102 上安装 MMM yum install MySql-mmm-agent.noarch -y(在 101 服务器上也执行这个命令) yum -y install MySql-mmm* 1.3.8 在 100 上添加监控用户用于检查数据库服务器的健康状况

img

1.3.9 在上添加代理用户账号,这个账号的权限很大,主要是故障转移的时候把 readonly 抹掉等等等

img

1.3.10 建立复制用户,也就是我们之前的 repl 用户,不用再建立了

1.3.11MMM 配置

先到 100 服务器上,配置 mmm_common.conf

img

100 目前是热主,所以 role 必须是 writer,另外把我们刚才分配的用户,写到配置文件中去:

img

img

img

把我们的 mmm_common.conf 复制到另外两台节点当中去:

img

配置 mmm_agent.conf 这个文件,只有 1 行,非常的简单

100 服务器这样配置:

img

其他服务器各取所需:

img

1.3.12MMM 监控配置

我们的 102 上安装了监控,所以到 102 上做相关配置,进入到 mmm_common.conf 文件中:

img

配置 ping_ips

img

配置监控用户

1.3.13 所有的节点配置好了,开始启动吧!在启动之前,必须要先把各个节点的 agent 启动起来。

img

然后回到 102 节点上启动监控:

img

看一下当前 MMM 的情况

img

1.3.14 测试一下我们的搭建是否成功

我们到 100 服务器上,把数据库关掉:

img

从图中可以看到 100 没了,然后我们的 101 有 writer 角色了(关键)

img

接下来我们要确认 db3 的主从复制是不是和 db2 在做,因为 db1 已经没了。我们到 102 服务器上看一下 slave 的状态,发现 master_host 指向了 101,非常完美。

img

1.4MMM 的优缺点

优点:1.使用 perl 脚本语言开发及完全开源 2.提供了读写 VIP,使服务器角色的变更对前端应用透明,在从服务器出现大量的主从延迟,主从链路中断时可以把这台从服务器上的读的虚拟 IP,漂移到集群中其他正常的服务器上 3.提供了从服务器的监控延迟 4.MMM 提供了主数据库故障转移后从服务器对新主的重新同步功能,很容易对发生故障的主数据库重新上线。

缺点:1.MMM 发布时间比较早不支持 MySql 新的复制功能,对于 MySql5.6 所提供的多线程复制技术也不支持 2.不支持 MySql 新的复制功能,没有读负载均衡功能,需要通过 LVS 和 F5 来做负载均衡 3.在进行主从切换时,容易造成数据丢失 4.MMM 监控服务存在单点故障

# MHA 架构

接下来我们将会讲解本篇文章中的核心中的核心 MHA(Master High Availability)。也是目前非常流行的一种架构。MHA 也是用 Perl 脚本开发的,它可以在主服务器宕机的情况下,30s 内完成主从切换,并且保证数据的一致性,达到真正意义上的高可用。如下图所示:

img

# 1.MHA 提供了什么功能

  • 监控主数据库服务器是否可用
  • 当主 DB 不可用时,从多个从服务器中选举出新的主数据库服务器,这也是和 3M 不同的地方
  • 提供了主从切换和故障转移功能。MHA 可以与半同步复制结合。MySql 半同步复制是介于异步和全同步之间,主库只需要等待至少一个从节点,收到并且 flush binlog 到 relay log 文件即可,主库不需要等待所有从库给主库反馈,这里只是一个收到的反馈,而并不是从库已经完成并提交的反馈,即从库只应用完成 io_thread 内容即可无需等到 sql_thread 的执行完成。

# 2.MHA 主从切换过程

1.MHA 尝试从出现故障的主数据库保存二进制日志 2.从多个备选从服务器中选举出新的备选主服务器(当然可以人为的设置一些服务器不参与选举) 3.在备选主服务器和其他从服务器之间同步差异二进制数据 4.新选出来的主从原主 DB 服务器上保存二进制日志。这里要注意重复的主键等会使 MHA 停止进行故障转移 5.提升备选主 DB 服务器为新的主 DB 服务器 6.迁移集群中的其他从 DB 作为新的主 DB 的从服务器

# 3.演示前准备

讲的理论很空洞还是演示最重要。先看看我们这次的 MHA 演示架构:

img

3.1MHA 配置步骤: 3.1.1 配置集群内所有主机的 SSH 免认证登录,为什么要免认证登录呢?是因为故障转移过程中需要保存原主服务器二进制日志,配置虚拟 IP 地址等等 3.1.2 安装 MHA-node 软件包和 MHA-manager 软件包 3.1.3MHA 配置步骤 使用 masterha_check_ssh 和 masterha_check_repl 对配置进行校验 3.1.4 启动并测试 MHA 服务

# 4.激动人心的演示

1.确认 100-1023 台机器的 gtid 已经启动

img

2.创建 repl 用户,并且在每个 101-102 上备份数据,MMM 架构中已经演示了,这里就不再演示了 3.在 101-102 启动复制链路

img

4.MHA 配置是基于 ssh 的所以需要在 100 上生成 ssh 密钥

img

5.把 100 的密钥复制到 100,101,102 3 台机器上去

img

步骤 5 在 101,102 的机器上也要做相关操作

6.拷贝 MHA 安装包

从 102 上把相应的安装包拷贝到 3 台机器上,如下图所示:

img

7.安装 perl 的支持包,在 100,101,102 上执行以下命令:

img

img

8.单独在 102 上安装监控服务,执行以下命令

img

img

9.MHA 与 MMM 不一样的地方是,只需要在 102 上配置即可,所以我们建立一个/etc/mha 的目录用于存放 MHA 的配置文件。另外 MHA 需要保存二进制文件所以我们创建一个 MySql_mha 目录用于存放配置文件。

img

10.在 102 目录的配置文件目录建立一个配置文件,存放主存管理的用户信息:

img

在 100 服务器上创建此用户

img

11.在 102 的配置文件中继续添加以下信息--管理目录,并且在 100 和 101 两台机器上建立 remote_workdir 目录

img

12.分别配置 ssh_user 信息,repl_user 用户名和用户名密码。另外 MHA 通过 ping 的方式检查主库是否存活,所以 ping_interval 我们设置为 1s 中去检查一次。master_binlog_dir 表示从 master 的哪个目录获取二进制文件。master_ip_failover_script(可选)是自己提供的一个脚本,当我们完成主从切换之后,可以把虚 IP 绑定在新主上面,如果不提供,MHA 是无法提供虚拟 IP 漂移的。secondary_check_script 是 MHA 提供的一个脚本,默认情况下,MHA 只是通过 manager 服务器进行检测 master 是否可用,通过这个脚本我们可以让多个网络路径检测 master 是否可用,这样就可以避免网络抖动问题造成误报。最后就是配置服务器信息,我们让 100 和 101 成为 master 的候选人,102 只能是个弟弟,所以 no_master=1。

img

13.配置完毕后,接下来在 102 上检查我们的配置,先是看 ssh 通不通:

img

然后检查主从复制的结构

img

img

14.检查通过后,接下来就是启动 MHA 了

img

15.在 100 服务器上配置 VIP

img

16.主从切换验证

在 100 上停掉 MySql,然后我们会发现刚才配置的 192.168.3.90 这个 VIP 不见了,如下图所示:

img

这是因为漂移到我们的 101 服务器上面去了,如下图所示:

img

接下来我们到 102 这个从库上,看看主从链路是不是切换了,有没有认识到它的新 master,不出意外 master 变成 101 了:

img

image.png

# 5.MHA 的优缺点

优点:同样是 perl 脚本开发的开源工具;相比于 MMM 支持基于 GTID 的复制;进行故障转移时更不易产生数据丢失;同一个监控节点可以监控多个集群 缺点:需要编写脚本或利用第三方工具(keep-alive)来实现 VIP 的配置,加强了使用难度,而且 MHA 不能自动剔除有问题的从节点;MHA 启动后只会对主数据库进行监控;MHA 需要基于 SSH 免认证登录,存在一定的安全隐患;没有提供从服务器的读负载均衡功能

# 读写分离和负载均衡介绍

首先要说明一点,读写分离和读负责均衡是两个完全不同的概念,进行 MySql 主从复制配置的一个主要目的主要是分担主库的读负载。我们要记住一点的是,写负载是不能被分担的,只能在主上进行写操作,读操作主从上都可以进行。    读写分离有两种方式:

  • 程序实现读写分离 优点:由开发人员控制什么样查询在从库中执行,因此很灵活。程序直接链接数据库,所以性能损耗比较少 缺点:增加了开发的工作量,使程序代码更加复杂,而且人为控制,容易出现错误
  • 中间件实现读写分离 目前的中间件有元老级别的 MySql-proxy,还有就是 MariaDB 公司提供的 maxScale MySql-proxy 性能和稳定都有一定的问题,高并发情况下容易死掉。但是它可以实现读写分离,而且还能实现读负载均衡。目前许多数据库中间件都可以完成数据分离的读写功能,根据我们使用的软件的不同,其性能和功能特点也会有不一样的地方。 优点:中间件根据查询语法分析,自动完成读写分离;对程序透明,对已有程序不用做任何调整 缺点:由于增加了中间层,所以对查询效率有损耗,因为 proxy 要做语法分析,鉴权等等,传说中经过测试会吃掉 50%-70%的性能。另外对于延迟敏感业务无法自动在主库执行,有人说可以通过配置来满足需求,但这样对程序透明的优点就没了。。 我们在上面讲了 MaxScale 和 MySql-proxy 都可以实现读负载均衡,这些都是属于软件上的读负载均衡,还有 LVS,Haproxy 做到读负载均衡。硬件上我们可以使用 F5 来完成。在这里我们将以 MaxScale 的讲解来完成本篇文章。

# MaxScale

img

image.png

  • Authentication 认证插件 该插件会去读取 MySql 服务器中的 user 表,并把用户信息缓存到 MaxScale 中,这样来连接的时候,会先看这个用户是否存在,如果不存在 MaxScale 还会到后端去更新用户信息,然后再鉴权
  • Protocal 协议插件 负责 maxScale 和外部接口的协议。主要是负责客户端到 maxscale 的接口以及 maxscale 到后端数据库的接口这两个方面,所以目前提供了两个协议插件,一个 MySql 客户端协议插件,另一个是 MySql 服务端协议插件。客户端协议插件主要是用于客户端应用程序通过 maxScale 连接到后端的 MySql,因此客户端完全可以把 maxscale 当做 MySql 来使用。服务端协议插件主要是用于 maxScale 连接后端的 MySql。
  • Router 插件 是 MaxScale 比较重要的一个插件,读写分离和读负载均衡全部依靠这个模块。目前 router 插件有两个,一个是 readconnroute 用于读负载均衡还有一个是 readwritesplit 用于读写分离。
  • Monitor 监控插件 监控后台那些 MySql 可用
  • Filter&logging 日志和过滤插件 可以做到 sql 语句的改写和容错,也可以做数据库防火墙的一些功能。

# 1.MaxScale 的演示

# 1.1MaxScale 的安装,在 102 上安装

img

image.png

# 1.2 这次我们的 101 是主,100 和 102 是从,我们可以通过以下语句看到目前 MySql 集群的情况。

img

image.png

# 1.3 在 101 上创建监控模块需要使用的账号

img

# 1.4 建立路由模块需要的账号

img

# 1.5 修改 MaxScale 的配置文件

img

# 1.5.1 配置 MySql server 信息

img

# 1.5.2 配置监控模块的信息

把我们的 server 全部加上,还有刚才配置的用户也配置上,监控时间是以毫秒为单位的。

img

# 1.5.3 配置读写分离

max_slave_connections=100%表示所有的从服务器都参与读,max_slave_replication_lag 表示从服务器延迟了 60s 以上,maxScale 就不要去读它了。

img

# 1.5.4 配置读写分离的端口和 maxScale 的管理端口

img

# 1.5.5 启动 maxScale

img

# 1.5.6 登录 MaxScale,查看服务器信息

img

然后大家可以直接连接 MaxScale 做相关操作了。 到此 MySql 高可用架构设计就全部讲完了,我们的最终架构图如下图所示:

img