MySQL高可用架构设计
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格式:
为了方便我们的演示,我们刷新一下binlog:
接下来的操作都会记录到binlog.000025中去。我们开始创建数据库然后插入修改记录,如下图所示:
记录完后,我们看一下我们的binlog存在哪个盘:
查看下binlog怎么记录的:
-
基于行的日志格式
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:
还是基于刚才的表,为了看到NOBLOB的效果,这时我把刚才的表添加一列,然后做下面的一些操作:
这个时候我们来看一下binlog中的信息,不过和刚才的命令有些不同,我们要加一个-vv参数,否则binlog展示的信息不是我们能看得懂的东东:
接下来我们看一下minimal模式的记录情况:
然后看看binlog,如下图所示,我们发现只记录了第三列的值,没有所有的列都记录
基于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步走,如下图所示:
其中第二步主库启动二进制转储线程,称之为binlogdump,从库的IO线程通过这个dump线程读取二进制日志中的事件。
-
基于日志点的复制配置步骤
1.在主DB服务器上建立复制账号,并且授权给这个账号,如下图所示:
2.配置主数据库服务器
3.配置从数据库服务器
一般情况下slave不会把从master接收到的binlog记录写入自己的binlog,log_slave_update参数会使slave通过SQL线程把从master接受到的binlog写进自己的binlog,但是前提是slave一定要开启自己的binlog,此参数一般用于级联复制,例如需要A复制到B,B复制到C,那么B就要开启此参数。
4.备份主数据库中的数据,对从库进行初始化
5.启动服务链路
这样看可能很抽象,接下来我们实战一把!
第一步建立用户:
第二步配置文件:
在mysql配置文件中配置server_id唯一:
配置文件中配置配置binlog
第三步配置从数据库:
server_id和主库的不一样,而且还配置了relay_log,并且也配置了binlog如下图所示:
第四步:
在主服务器上执行以下命令,备份数据:
把备份好的sql复制到从库上面去:
然后到从库上,把这个all.sql导入到数据库中去:
第五步,非常复杂的一步:
在从服务器上执行以下命令:
其中MASTER_LOG_FILE和MASTER_LOG_POS这两个参数怎么来的呢?
我们在all.sql中会看到这么一句话:
执行这句话后,接下来继续在从服务器上执行show slave status \G命令:
发现还没启动链路,我们使用start slave命令进行启动。
看下从服务器上,有另两个线程已经启动了:
接下来看一下主服务器上的信息:
我们看到了binlog Dump线程已经启动了,它就是读取binlog的线程
基于日志点的复制优点:
是Mysql最早支持的复制技术,Bug相对较少;对SQL查询没有任何限制;故障处理比较容易
缺点:故障转移时重新获取新主的日志点信息比较困难 -
基于GTID的复制
什么是GTID,GTID是全局事务ID,其保证为每一个在主服务器上提交的事务在复制集群中可以生成一个唯一的ID
GTID=source_id:transaction_id
在刚才我们讲解了基于日志的复制,但是基于日志的复制会有以下缺点:
基于GTID复制的原理如下:
从库会告诉主库已经执行事务的GTID值,主库会发送从库没有执行事务的GTID值,同一个事务只在指定的从库执行一次。
基于GTID进行复制的步骤如下:
第一步:
和基于日志的复制一样
第二步:
相比于基于日志的复制多了一个gtid_mode=on的步骤
第三步:
配置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值
第六步:
接下来,我们通过实战的方式看看:
第一步刚才我们已经做过了,这里就省去了。
第2-3步:
在主库的配置文件中加入配置项
第4步在从服务器上:
然后重启主从数据库,让配置生效
第五步:
主库上先备份
然后复制到从库
在从库上导入数据
第六步:
在从库上执行以下操作:
基于GTID复制的优缺点:
优点:可以很方便的进行故障转移;从库不会丢失主库上的任何修改
缺点:故障处理比较复杂;对执行的SQL有一定的限制
那么介绍了这两种复制模式,我们应该选择哪种复制模式呢?
首先我们要考虑Mysql的版本问题,不是任何版本都支持GTID的;其次复制架构及主从切换的方式,使用GTID更方便些;还有所使用的高可用管理组件;对应用的支持程度。
Mysql复制拓扑
1.一主多从的拓扑
一主多从的复制拓扑
一主多从的用途
2.主-主复制拓扑
2.1主备模式的主主复制,同一时刻只有一个主库在提供服务,如下图所示
主备模式的主主复制
一台服务器处于只读状态并且只作为热备使用。在对外提供服务的主库出现故障或是计划性的维护时才会进行切换,使原来的备库成为主库,而原来的主库会成为新的备库并处理只读或是下线状态,待维护完成后重新上线。这种模式下,要确保两台服务器上的初始数据相同,确保两台服务器上已经启动binlog并且有不同的server_id。在两台服务器上弃用log_slave_updates参数。在初始的备库上启用read_only。
2.2主主模式的主主复制,同一时刻两个主库都在提供服务,但是千万不要认为这种模式可以分担主库的写负载,如下图所示:
主主模式的主主复制
主主模式下,很容易产生数据冲突而造成复制链路的中断,而且极易造成数据丢失,耗费大量的时间。所以最好两个主中所操作的表最好能够分开或者使用auto_increment_increment=2以及auto_increment_offset=1|2参数控制自增ID的生产。这种模式很不建议使用!
3.拥有备库的主-主复制拓扑
4.级联复制
级联复制
这种模式下,需要让分发主库(其实也是一个从库)启动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共享存储是几个服务器共享一个磁盘,同一时刻只有一个服务器对外提供服务,如果其中一个服务宕机了,就由另外一个服务器对外提供服务。如下图所示:
问题在于磁盘是单点的,所以共享存储并不是一种好的解决单点故障的方式
DRDB的方式如下图所示:
DRDB
4.1.2利用多写集群或NDB集群来解决Mysql单点故障
多写集群目前用的最多的是Percona公司提供的pxc架构,如下图所示:
所有的服务器上的事务都必须提交成功了,才能算成功,否则全部回滚,所以这种架构写性能受集群中性能最差的服务器的影响。也并不常用。
在NDB集群中,所有的节点进行主主复制,可以对每个节点进行写入,但是问题就在于如果内存不足,NDB集群的性能就会非常的差,所以NDB很少被使用到生产环境中
4.1.3利用Mysql主从复制来解决Mysql单点故障
刚才我们也说了,主要的是解决主节点的单点故障问题。主服务器切换后如何通知应用新的主服务器的IP地址;另外如何检查Mysql主服务器是否可用;如何处理从服务器和新主服务器之间的那种复制关系,都是亟待解决的问题
MMM架构
MMM架构全程Multi-Master Replication Manager。它主要是监控和管理Mysql的主主复制拓扑,并在当前的主服务器失效时,进行主和主备服务器之间的主从切换和故障转移等工作。主主复制有主动主动模式和主动被动模式两种,MMM用于主动被动模式的主主复制。它可以监控Mysql主从复制健康情况,在主库出现宕机时进行故障转移并自动配置其他从服务器对新主服务器的复制。MMM要解决的问题是如何找到从库对应的新的主库日志同步点以及多个从库出现数据不一致的情况。MMM提供了主,写虚拟IP,在主从服务器出现问题时可以自动迁移虚拟IP。MMM架构如下图所示:
MMM架构
建立MMM架构需要的资源如下:
MMM架构资源
1.MMM架构实例演示
1.1MMM安装大致步骤
- 配置主主复制及主从同步集群
- 安装主从节点所需要的支持包
- 安装及配置MMM工具集
- 运行MMM监控服务
- 测试
1.2 top图结构
我们这里提供两个主服务器,一个从服务器,MMM安装在从服务器上
1.3真实实战
1.3.1在100的主服务器上备份数据
备份
1.3.2复制到另外一个主服务器上面
复制
1.3.3在101上导入100上的数据
image.png
1.3.4在101上启动复制
在101上我们看到主是100
1.3.5由于现在是主主,所以我们还要回到100机器上,去同步101上的数据
在100上我们看到主是101
1.3.6到102从服务器上进行配置
先导入数据
开始复制
我们的top搭建好了,重头戏开始:
1.3.7在102上安装MMM
yum install mysql-mmm-agent.noarch -y(在101服务器上也执行这个命令)
yum -y install mysql-mmm*
1.3.8在100上添加监控用户用于检查数据库服务器的健康状况
1.3.9在上添加代理用户账号,这个账号的权限很大,主要是故障转移的时候把readonly抹掉等等等
1.3.10建立复制用户,也就是我们之前的repl用户,不用再建立了
1.3.11MMM配置
先到100服务器上,配置mmm_common.conf
100目前是热主,所以role必须是writer,另外把我们刚才分配的用户,写到配置文件中去:
把我们的mmm_common.conf复制到另外两台节点当中去:
配置mmm_agent.conf这个文件,只有1行,非常的简单
100服务器这样配置:
其他服务器各取所需:
1.3.12MMM监控配置
我们的102上安装了监控,所以到102上做相关配置,进入到mmm_common.conf文件中:
配置ping_ips
配置监控用户
1.3.13所有的节点配置好了,开始启动吧!在启动之前,必须要先把各个节点的agent启动起来。
然后回到102节点上启动监控:
看一下当前MMM的情况
1.3.14测试一下我们的搭建是否成功
我们到100服务器上,把数据库关掉:
从图中可以看到100没了,然后我们的101有writer角色了(关键)
接下来我们要确认db3的主从复制是不是和db2在做,因为db1已经没了。我们到102服务器上看一下slave的状态,发现master_host指向了101,非常完美。
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内完成主从切换,并且保证数据的一致性,达到真正意义上的高可用。如下图所示:
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演示架构:
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已经启动
2.创建repl用户,并且在每个101-102上备份数据,MMM架构中已经演示了,这里就不再演示了
3.在101-102启动复制链路
4.MHA配置是基于ssh的所以需要在100上生成ssh密钥
5.把100的密钥复制到100,101,102 3台机器上去
步骤5在101,102的机器上也要做相关操作
6.拷贝MHA安装包
从102上把相应的安装包拷贝到3台机器上,如下图所示:
7.安装perl的支持包,在100,101,102上执行以下命令:
8.单独在102上安装监控服务,执行以下命令
9.MHA与MMM不一样的地方是,只需要在102上配置即可,所以我们建立一个/etc/mha的目录用于存放MHA的配置文件。另外MHA需要保存二进制文件所以我们创建一个mysql_mha目录用于存放配置文件。
10.在102目录的配置文件目录建立一个配置文件,存放主存管理的用户信息:
在100服务器上创建此用户
11.在102的配置文件中继续添加以下信息--管理目录,并且在100和101两台机器上建立remote_workdir目录
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。
13.配置完毕后,接下来在102上检查我们的配置,先是看ssh通不通:
然后检查主从复制的结构
14.检查通过后,接下来就是启动MHA了
15.在100服务器上配置VIP
16.主从切换验证
在100上停掉mysql,然后我们会发现刚才配置的192.168.3.90这个VIP不见了,如下图所示:
这是因为漂移到我们的101服务器上面去了,如下图所示:
接下来我们到102这个从库上,看看主从链路是不是切换了,有没有认识到它的新master,不出意外master变成101了:
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
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上安装
image.png1.2 这次我们的101是主,100和102是从,我们可以通过以下语句看到目前mysql集群的情况。
image.png1.3 在101上创建监控模块需要使用的账号
1.4 建立路由模块需要的账号
1.5 修改MaxScale的配置文件
1.5.1配置mysql server信息
1.5.2配置监控模块的信息
把我们的server全部加上,还有刚才配置的用户也配置上,监控时间是以毫秒为单位的。
1.5.3配置读写分离
max_slave_connections=100%表示所有的从服务器都参与读,max_slave_replication_lag表示从服务器延迟了60s以上,maxScale就不要去读它了。
1.5.4 配置读写分离的端口和maxScale的管理端口
1.5.5启动maxScale
1.5.6登录MaxScale,查看服务器信息
然后大家可以直接连接MaxScale做相关操作了。
到此Mysql高可用架构设计就全部讲完了,我们的最终架构图如下图所示:
高可用架构设计就讲到这里,欢迎大家讨论和交流