目录如下
MySQL主从集群原理+实战
背景
随着公司业务的发展,对数据库的要求越来越高,以前的单机MySQL肯定是玩不转了,亟需升级成MySQL集群,这是一个公司在业务发展时不得不面临的问题
就单机MySQL而言,自己玩玩可以,运用到实际项目中,那肯定要挨批的。一方面数据不安全,万一数据库的电脑磁盘坏了,就坑了。另一方面数据库的并发能力是有限的,一般并发数200~500就差不多了,当然你要继续往上增,也是可以的,那就影响整体Mysql的响应时间。
那么有哪些集群方案呢?
集群方案
在初期,由于MySQL官方提供的集群方案并不成熟,但由于业务的发展又需要集群技术,所以涌现了很多非官方的集群技术
主从复制
主从复制也叫MySQL Replication,是MySQL的原生功能,这也是最简单最有效的方式,既然单点MySQL扛不住,那多来几台不就完事了,主从复制说的就是这种方案,如下图,一主两从,主接收写请求后同步给从,这种方案天生就是读写分离的
[图片上传失败…(image-c3e579-1617976467926)]
那么同步的原理是什么呢?大致就是下面这个过程,Master在写数据时(DML命令)会产生一个bin log(Binary Log),Slave开一个IO线程从指定偏移处去读取bin log,读回来后生成Relay Log,再开一个SQL线程"重放"数据来完成同步。
不难看出,这种方式天生就是异步的,Master只需要写入Binary Log就不管了,不用等待Slave的确认。
优点:
- 读写分离,增加整体性能
- 部署简单,维护方便,需要资源少,成本低,最少两台即可搞
缺点:
- 无故障转移,Master挂了整个集群只能读取不能写入,需要引入其他的高可用机制
- 数据存在一致性问题,因为异步,所以Slave的数据一定不是最新的,需要等待一个时间窗后才能读取
- Slave过多时Slave对Master的负载以及网络带宽都会成为一个严重的问题
主从复制+Keepalived
既然简单主从复制无故障转移,那么加个Keepalived作为备用Master可以不?答案当然是可以滴,如下:
[图片上传失败…(image-da22dd-1617976467926)]
这样就没问题了吗?如果各种不可抗力的网络原因导致Keepalived两台主机不能通信,互相抢主,争着做VIP,那么肯定有问题的嘛,这种现象我们称之为脑裂,这也是这种模式下最严重的问题,所谓网络原因,比如下面这些
1.高可用服务器对之间心跳线链路发生故障,导致无法正常通信。 2.因心跳线坏了(包括断了,老化)。 3.因网卡及相关驱动坏了,ip配置及冲突问题(网卡直连)。 4.因心跳线间连接的设备故障(网卡及交换机)。 5.因仲裁的机器出问题(采用仲裁的方案)。 6.高可用服务器上开启了 iptables防火墙阻挡了心跳消息传输。 7.高可用服务器上心跳网卡地址等信息配置不正确,导致发送心跳失败。 8.其他服务配置不当等原因,如心跳方式不同,心跳广插冲突、软件Bug等。 9.Keepalived配置里同一 VRRP实例如果virtual_router_id两端参数配置不一致也会导致裂脑问题发生。
优点:
- 可以进行故障转移,当Master挂掉以后备用Master自动顶上来,充当VIP
缺点:
- 闹裂问题
- 数据一致性问题,两台Master都是异步复制的,无法保证完全的一致
- 多出一台Master备机,增加成本,这是不可避免的
对于脑裂问题,可以进行人工干预, 思路很简单,正常情况下keepalived的VIP地址是在主节点上的,如果在从节点上发现了VIP,就通过各种方式(短信,邮件)告警相关人员,核实现在是否是Master挂了,样例脚本如下,在备用Master上执行
vim split-brainc_check.sh
#!/bin/bash
# 检查脑裂的脚本,在备节点上进行部署
LB01_VIP=192.168.1.229
LB01_IP=192.168.1.129
LB02_IP=192.168.1.130
while true
do
ping -c 2 -W 3 $LB01_VIP &>/dev/null
if [ $? -eq 0 -a `ip add|grep "$LB01_VIP"|wc -l` -eq 1 ];then
echo "ha is brain."
else
echo "ha is ok"
fi
sleep 5
done
那么数据一致性问题怎么保证呢?Slave上的数据一致性暂且不论,但是备用Master上的呢?如果Master突然宕机来不及写bin log或者备用Master来不及同步bin log那么备用Master上的数据依然不是一致的,针对这个问题,半同步登上舞台
主从复制(半同步)+Keepalived
所谓半同步,指的是
主库只需要等待至少一个从库节点收到并且Flush Binlog到Relay Log文件即可,主库不需要等待所有从库给主库反馈。同时,这里只是一个收到的反馈,而不是已经完全完成并且提交的反馈,如此,节省了很多时间。
半同步的本质上牺牲数据写数据的性能来换取数据的一致性,但不能完全确保数据一致性,因为它认为Slave将数据Flush到Relay Log就算同步成功,如果此时Slave挂了,那么数据依然不能保持同步,算是一种折中,兼顾了数据一致性和性能。
半同步也会超时,由 rpl_semi_sync_master_timeout控制,默认是10s,也就是说10s后还收不到确认信息就退化成异步复制
所以只需要在Master与Master备机之间使用半同步,如下图
[图片上传失败…(image-bbd12f-1617976467925)]
要想使用半同步复制,必须满足以下几个条件:
- MySQL 5.5及以上版本,从MySQL5.5开始,MySQL以插件的形式支持半同步复制
- 变量have_dynamic_loading为YES
- 异步复制已经存在
半同步总结
在一主多从的架构中,如果要开启半同步复制,并不要求所有的从都是半同步复制。
MySQL 5.7极大的提升了半同步复制的性能。
5.6版本的半同步复制,dump thread 承担了两份不同且又十分频繁的任务:传送bin log 给Slave ,还需要等待Slave反馈信息,而且这两个任务是串行的,dump thread 必须等待Slave返回之后才会传送下一个events 事务。dump thread 已然成为整个半同步提高性能的瓶颈。在高并发业务场景下,这样的机制会影响数据库整体的TPS 。
5.7版本的半同步复制中,独立出一个 ack collector thread ,专门用于接收Slave的反馈信息。这样Master上有两个线程独立工作,可以同时发送bin log到Slave和接收Slave的反馈。
当然,主从复制还可以玩出花,比如主主复制、级联复制和多源复制
- 主主复制
两台MySQL互为主从,任何一方有变更,都会复制对方的数据到自己的数据库,这种双写模式下问题比较大, 假设在不同的库并发写一个表,就会造成数据混乱。一般不建议主主复制,如果真要用双写,建议从表级分开,比如某个节点只操作某张表
- 多源复制
所谓多源复制,即是多主一从,MySQL 5.7 开始支持多主一从的模式,将多个库的数据备份到一个库中存储。
- 级联复制
正好可以解决主从复制中Slave过多对Master的负载以及网络带宽造成的问题,将其他Salve挂载在在它上一级的Salve上,解决了多个Slave对Master的压力,但是缺点也是显而易见的,使得Slave的延迟更高,对于追求最终一致性的场景比较合适,结合主从复制+Keepalived方案,架构如下图
[图片上传失败…(image-cf8cae-1617976467925)]
当然集群方案还有很多,比如MMM(已淘汰)、MHA、PXC、MGR等,这些方案我们后面再讲
主从集群
编译安装MySQL
MySQL版本选择
MySQL版本较为混乱,目前业界的MySQL主流分支版本有Oracle官方版本的MySQL、Percona Server、MariaDB。
- 如果是自己搭建维护,建议使用MySQL官方分支【 MySQL Community Server】,推荐版本MySQL 5.7.30
- 如果是阿里云和腾讯云,建议选择云数据库 MySQL 5.7版
Oracle MySQL
目前官网最新的GA版就是MySQL 8.0.20,这个版本可能是MySQL数据库又一个时代的开始,迄今为止,MySQL 8.0无论在功能还是性能(整体上),都是目前最好的MySQL版本,但是为了支持大量的新功能特性,这个版本调整的太大了,稳定性、可靠性还需要一定周期才能保证。目前使用官方版求稳定仍然建议5.7系列,如果想尝鲜直接上车8.0.
另外从长期来看,官方版本的MySQL,目前在Oracle公司里有实力雄厚的开发团队支持,产品迭代速度稳定,基本是每三个月发布一个小版本,另外依赖早期Oracle数据库优秀的产品、开发经验,官方MySQL前景看好。
- 官网:https://www.mysql.com/
Percona Server
Percona Server是MySQL重要的分支之一,是由原MySQL性能测试团队Peter发起成立。它基于官方版本优化进行了性能提升以及管理增强,并集成