前面文章介绍了MySQL的读写分离及分库分表过程。对于分库和分表,实现策略有好多种,需要根据业务来确定最适合的分库分表架构,文章中还有好多未涉及到的,读者可以自己找资料学习。分库分表完成之后,数据容量及性能增加了,但是紧接着会面临着可用性的问题。从本篇文章开始,将会介绍MySQL的高可用实现方案!

一、基本概念

1、什么是高可用

"高可用性"(High Availability),简称HA,通常来描述一个系统经过专门的设计,从而减少停工时间,而保持其服务的高度可用性。 --来自"百度百科"

2、高可用架构的工作方式

(1)主从
服务同时部署在主从服务器上。初始,主服务器上的服务正常运行,从服务器通过心跳等方式实时监测主服务器的运行状态,一旦出现主服务器宕机或者主服务器上的服务异常终止等故障,从服务器会自动接管主服务器的工作,对外提供服务。

(2)双主
服务同时部署在两台主服务器上。起初,只有一台主服务器对外提供服务,另外一台服务器只处于实时监听状态,当其中的一台主服务器宕机或者服务不可用时,另外一台主服务器会立刻接管出故障的主服务器,对外提供服务,一般通过VIP自动切换来实现。

(3)集群
服务同时部署在多台服务器上。多台服务器共同工作,每一个服务器都有一台或者多台备机。起初,多台服务器可以通过反向代理共同对外提供服务,当某一台服务器出现故障或者其上的服务不可用时,其他服务可以立刻进行接管,对外提供服务,通常可以使用Nginx,HaProxy,LVS等代理实现服务的高可用。但是,Nginx,HaProxy,LVS本身也是单点,需要实现高可用,后面介绍Web应用高可用时会详细介绍。

3、高可用的衡量指标-系统可用率

计算方法:可用率=系统无故障运行时间/(系统无故障运行时间+系统故障维护时间)
根据可用率估计系统可用性指标如下:
图片描述

二、实现方案

(1)KeepAlived+MySQL+MM复制
实现方法:通过双主复制,在每个节点上部署Keepalived,通过vip向外提供服务,当某个节点故障时,vip自动转移到可用的节点上。

(2)HeartBeat+DRBD+MySQL
实现方法:分布式复制块设备,类似于RAID1,当数据保存到一台服务器上的时候,会同时将数据冗余备份一份到另外一台服务器,通过HeartBeat向服务器发送心跳信息监听服务器的存活状态,当一台服务器故障时,服务会自动转移到另外一个服务器上。

(3)MySQL Cluster
实现方法:MySQL集群是由一组服务器组成,每个服务器上都运行着多个服务进程,MySQL的数据节点,MySQL的管理服务,以及转们的数据访问程序,搭建起来十分复杂。时间成本特别高,但是可以通过MySQL Cluster Manager来快速完成搭建,但是这个软件是收费的,所以这种方案使用的特别少。

(4)MySQL主从+读写分离+自定义脚本
实现方法:插入数据的时候,通过MySQL的主从复制将数据分别保存到两个服务器上,当其中某一台服务器出现故障时,会自动将其中的一台从库提升为主库,对外提供服务器。

三、双主+KeepAlived实现MySQL的高可用

1、环境准备

(1)服务器:CenterOS6.9

(2)MySQL环境
版本:mysql-5.6.39
节点一:192.168.0.4(mysql-master01)
节点二:192.168.0.5(mysql-master02)

2、搭建过程

  • 搭建双主复制

(1)建立复制用户,在节点一上建立一个复制用户'repl'@'192.168.0.%'

#登陆mysql
[root@mysql-master01 ~]# mysql -uroot -proot -h127.0.0.1 -P3306

#建立复制用户,注意主机权限是'192.168.0.%',因为等会需要导入数据到节点二上
mysql> grant all on *.* to 'repl'@'192.168.0.%' identified by 'repl';

(2)全备节点一的所有数据,然后发送到节点二上

[root@mysql-master01 ~]# mysqldump -uroot -proot -h127.0.0.1 -P3306 --all-databases --flush-logs --single-transaction --triggers --routines --master-data=2 --events --hex-blob > /tmp/mysql_all_data.sql
[root@mysql-master01 ~]# scp /tmp/mysql_all_data.sql 192.168.0.5:/tmp/

(3)在节点二所在的服务器上导入节点一备份的数据

[root@mysql-master02 ~]# mysql -uroot -proot -h127.0.0.1 -P3306 < /tmp/mysql_all_data.sql 

(4)修改节点一的配置文件,添加如下内容

[mysqld]
server_id = 4
log_bin=/mysql_data/mysql-bin
log_bin_index=/mysql_data/mysql-bin.index
#让主节点同时作为其他节点的从节点
log_slave_updates = 1
binlog_format = mixed
relay_log = /mysql_data/mysql-relay
relay_log_index = /mysql_data/mysql-relay.index

(5)修改节点二的配置文件,添加如下内容

[mysqld]
server_id = 5
log_bin = /mysql_data/mysql-bin
log_bin_index = /mysql_data/mysql-bin.index
log_slave_updates = 1
relay_log = /mysql_data/mysql-relay
relay_log_index = /mysql_data/mysql-relay.index

(6)重启节点一和节点二
(7)登陆节点一中,然后查看当前二进制日志的位置点及日志文件

root@127.0.0.1 (none)> show master status \G
*************************** 1. row ***************************
             File: mysql-bin.000075
         Position: 120
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 
1 row in set (0.10 sec)

(8)登陆节点二中,执行"change master"命令,将节点二配置为节点一的从库,然后启动复制

mysql> change master to master_host='192.168.0.4',master_port=3306,master_user='repl',master_password='repl',master_log_file='mysql-bin.000075',master_log_pos=120;
mysql> start slave;
#查看复制状态
mysql> show slave status \G

#看到输出结果中如下两个参数的值为Yes,表示节点二到节点一的复制配置成功
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

(9)在节点二中查看当前二进制日志的位置点及日志文件

root@127.0.0.1 (none)> show master status \G
*************************** 1. row ***************************
             File: mysql-bin.000050
         Position: 160
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 
1 row in set (0.00 sec)

(10)在节点一中执行"change master"命令,将节点一配置为节点二的从库,然后启动复制

mysql> change master to master_host='192.168.0.5',master_port=3306,master_user='repl',master_password='repl',master_log_file='mysql-bin.000050',master_log_pos=160;
mysql> start slave;
#查看略,同上

(11)验证,在节点一上创建一张表,然后登陆节点二查看。然后在节点二上创建一张表,然后登陆节点一查看,正常的话,会相互复制,验证过程省略。

至此,MySQL的双主复制搭建完成。

  • 安装及配置keepalived

(1)在节点一上,挂载CentOS6.9的镜像,然后使用yum方式安装keepalived,对于镜像的挂载,可以参考之前的博客:https://segmentfault.com/a/11... 此处不再赘述。安装过程如下:

[root@mysql-master01 ~]# yum install -y keepalived

#安装完成之后,使用该命令查看是否安装成功
[root@mysql-master01 ~]# rpm -qa | grep keep
  keepalived-1.2.13-5.el6_6.x86_64

(2)在节点二上,同样挂载CentOS6.9的镜像,然后安装keepalived。此处略。
(3)keepalived安装完成之后,配置文件默认在/etc/keepalived目录下,首先配置节点一上的keepalived,如下:

[root@mysql-master01 ~]# cd /etc/keepalived/
#备份配置文件,需要养成习惯
[root@mysql-master01 keepalived]# cp keepalived.conf keepalived.conf.bak

写入如下内容:

! Configuration File for keepalived
global_defs {
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 192.168.200.1
   smtp_connect_timeout 30
   !负载均衡器标识,在同一网段内,可以相同 
   router_id LVS_DEVEL
}
!定义VRR实例
vrrp_instance VI_1 {
    state BACKUP   !指定主节点和备节点,此处都是用BACKUP备机
    interface eth0 !虚拟IP绑定的网卡,根据自己的情况而定
    virtual_router_id 51  !同一个VRR实例下virtual_router_id必须相同
    priority 100   !节点的优先级(范围为:1-254之间),备用节点必须比主节点优先级低
    advert_int 1   !组播信息发送间隔,两个节点设置必须一样
    nopreempt  !表示不抢占的模式,只需要在优先级高的机器上设置即可,优先级低的机器可不设置
    !设置验证信息,两个节点必须一致,不一致会失败
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    !配置VIP,可以随意取,但是需要和数据库所在服务器在同一个IP端内,两个节点必须相同
    virtual_ipaddress {
        192.168.0.100
    }
}
!配置监听的VIP及端口
virtual_server 192.168.0.100 3306 {
    delay_loop 2  !健康检查时间间隔,单位为s
    lb_algo wrr  !调度算法权重轮训Weight Round robin
    lb_kind DR  !LVS实现负载均衡的机制,可以有NAT、TUN和DR三个模式可以选择
    nat_mask 255.255.255.0
    persistence_timeout 60 !回话保持时间
    protocol TCP !转发协议类型,有tcp和udp两种 

    real_server 192.168.0.4 3306 {
        weight 1  #权重,此处和第二个节点设置的相同,表示均衡轮训
        notify_down /server/scripts/shutdown.sh !检测到服务故障之后执行的脚本
        TCP_CHECK {
                connect_timeout 10    !连接超时时间
                nb_get_retry 3        !重连次数
                delay_before_retry 3  !重连间隔时间
                connect_port 3306     !健康检查端口
        }
    }
}

shutdown.sh的内容请继续往下看。

(4)配置节点二上的keepalived配置文件

[root@mysql-master02 ~]# cd /etc/keepalived/
[root@mysql-master02 keepalived]# cp keepalived.conf keepalived.conf.bak

写入如下内容:

! Configuration File for keepalived
!注意,global_defs可以完全不用动
global_defs {
   notification_email {
     acassen@firewall.loc
     failover@firewall.loc
     sysadmin@firewall.loc
   }
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 192.168.200.1
   smtp_connect_timeout 30
   router_id LVS_DEVEL
}
vrrp_instance VI_1 {
    state BACKUP 
    interface eth0
    virtual_router_id 51
    priority 90   
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.0.100
    }
}
! 配置VIP及监听的端口
virtual_server 192.168.0.100 3306 {
    delay_loop 2
    lb_algo wrr
    lb_kind DR
    nat_mask 255.255.255.0
    persistence_timeout 60
    protocol TCP

    real_server 192.168.0.5 3306 {
        weight 1
        notify_down /server/scripts/shutdown.sh
        TCP_CHECK {
                connect_timeout 10
                nb_get_retry 3
                delay_before_retry 3
                connect_port 3306
        }
    }
}

shutdown.sh的内容如下,主要是用来关闭keepalived进程的:

[root@mysql-master01 keepalived]# cat /server/scripts/shutdown.sh 
    #!/bin/bash
    #
    killall keepalived

#注意,编辑完成之后,需要授权,否则不能执行,节点二上的脚本与此相同
[root@mysql-master01 keepalived]# chmod +x /server/scripts/shutdown.sh 

(5)keepalived安装完成之后,默认会生成Sysv脚本,使用service命令启动节点一上的keepalived,并监控试试日志,如下:

[root@mysql-master01 keepalived]# service keepalived start
[root@mysql-master01 keepalived]# tail -f /var/log/messages
#如果未看到错误消息,就是好消息。正常的话,可以在启动日志中看到VIP的启动信息。

#查看进程
[root@mysql-master01 keepalived]# ps -ef | grep keep
root       8258      1  0 May20 ?        00:00:02 /usr/sbin/keepalived -D
root       8260   8258  0 May20 ?        00:00:07 /usr/sbin/keepalived -D
root       8261   8258  0 May20 ?        00:00:12 /usr/sbin/keepalived -D
root       9434   8463  1 04:08 pts/0    00:00:00 grep keep

(6)启动节点二上的keepalived

[root@mysql-master02 keepalived]# service keepalived start

(7)验证主从功能是否正常,验证方法为在节点一上创建数据库,观察节点二上是否同步;然后在节点二上创建数据库,观察节点一上是否同步。验证过程此处略。
(8)两个节点都启动之后,在先启动的节点上查看VIP,如下:

[root@mysql-master01 keepalived]# ip addr | grep "0.100"
    inet 192.168.0.100/32 scope global eth0

(9)验证高可用
在另一个客户端上使用VIP连接数据库,比如windows上(VIP需要和windows宿主机在同一个ip段内,否则无法连接),然后查看当前的主机名称,如下:

C:\Users\wangbin>mysql -uroot -proot -h192.168.0.100 -P3306
#查看主机名
mysql> show variables like 'hostname';
+---------------+----------------+
| Variable_name | Value          |
+---------------+----------------+
| hostname      | mysql-master01 |
+---------------+----------------+
1 row in set (0.00 sec)

关闭节点一上的数据库服务:

[root@mysql-master01 keepalived]# service mysqld stop
#过5秒左右,查看VIP,可以发现,ip已经不在了
[root@mysql-master01 keepalived]# ip addr | grep "0.100"

此时再查看主机名称,如下:

mysql> show variables like 'hostname';
+---------------+----------------+
| Variable_name | Value          |
+---------------+----------------+
| hostname      | mysql-master02 |
+---------------+----------------+
1 row in set (0.00 sec)
#发现已经变成server02了,VIP已经可以自动切换了

创建一个数据库,然后重新启动节点一上的mysql服务和keepalived服务,登陆节点一查看创建的数据库是否复制。

[root@mysql-master01 keepalived]# service keepalived start
[root@mysql-master01 keepalived]# service mysqld start

经过查看,发现已经复制,在数据库节点重新启动之后,会开始同步节点二上的数据。

后续更多文章将更新在个人小站上,欢迎查看。

另外提供一些优秀的IT视频资料,可免费下载!如需要请查看https://www.592xuexi.com

至此,MySQL的高可用概念及使用(Keepalived+MySQL)实现的MySQL高可用已经搭建验证完毕,篇幅较长,难免有笔误,欢迎评论转发!


夏日寒冰
318 声望86 粉丝

忠实的技术爱好者,追求极致,喜欢总结一些自己用过的技术点,与他人交流分享。