实例拓扑图:

复制其最终目的是让一台服务器的数据和另外的服务器的数据保持同步,已达到数据冗余或者服务的负载均衡。一台主服务器可以连接多台从服务器,并且从服务器也可以反过来作为主服务器。主从服务器可以位于不同的网络拓扑中,由于mysql的强大复制功能,其复制目标可以是所有的数据库,也可以是某些数据库,甚至是某个数据库中的某些表进行复制。

keepalived+MySQL双主搭建过程

图片 1

1. keepalived 介绍

keepalived主要有三个模块,分别是core、check和vrrp。

  • core模块为keepalived的核心,负责主进程的启动、维护以及全局配置文件的加载和解析
  • check负责健康检查,包括常见的各种检查方式
  • vrrp模块是来实现VRRP协议的

keepalived实现的功能主要有三个:

  1. 将IP地址飘移到其他节点上
  2. 在另一个主机上生成ipvs规则
  3. 健康状况检查

keepalived通过软件的方式在其内部模拟实现VRRP协议,然后借助于VRRP协议实现IP地址漂移。

图片 2

MySQL支持的两种复制方案:基于语句复制,基于行复制
基于语句复制基于行复制,这两种复制方式都是通过记录主服务器的二进制日志中任何有可能导致数据库内数据发生改变的SQL语句到中继日志,并且在从服务器上执行以下中继日志内的SQL语句,而达到与主服务器的数据同步。不同的是,当主服务器上执行了一个基于变量的数据并将其更新到数据库中,如now()函数,而此时基于语句复制时记录的就是该SQL语句的整个语法,而基于行复制就是将now()更新到数据库的数值记录下来。
例如:在主服务器上执行以下语句:
mysql>update user set createtime=now() where sid=16;
假如此时now()返回的值是:2012-04-16 20:46:35
基于语句的复制就会将其记录为:update user set createtime=now() where
sid=16;
基于行复制的就会将其记录为:update user set createtime=’2012-04-16
20:46:35′ where sid=16;

首先要简单了解一下keepalived:

此章节讲述主从架构

主从架构  — 目前已经不建议使用,推荐使用复制集

主从配置可以在配置文件中配置
从节点可以在启动之后使用命令追加主节点,db.source.insert({“host”:”IP+端口”})

连接节点:mongo 127.0.0.1:29991,主节点允许读写
a、从节点可以连接,但是不允许读写,如果想读 可以设置
 db.getMongo().setSlaveOk()

b、在主节点运行 db.getMongo().setSlaveOk()

1、设置文件夹目录

图片 3

2、每个目录的层级 均为 DB目录,日志目录,配置文件3个

图片 4

3、配置文件内容

架构:
a、主节点配置文件
dbpath=D:\MS\Master\DB 
logpath=D:\MS\Master\LOG\s.log 
logappend=true 
port=29991 
master=true

b、从节点配置文件
节点1
dbpath=D:\MS\Slave2\DB 
logpath=D:\MS\Slave2\LOG\s.log 
logappend=true 
port=29993 
slave=true
source=127.0.0.1:29991

节点2
dbpath=D:\MS\Slave2\DB 
logpath=D:\MS\Slave2\LOG\s.log 
logappend=true 
port=29993 
slave=true
source=127.0.0.1:29991

4、配置文件处理好之后,使用CMD命令行形式,mongod –config 配置文件路径
 启动4个实例。启动成功的界面如下,需要依次打开多个命令shell启动。

图片 5

5、使用mongo 127.0.0.1:29991
 链接到主节点的实例,然后在实例里面创建集合和记录,将直接同步到其他3个从节点上面。

图片 6

到达此步骤 将是成功搭建最简单的测试
主从架构。(因为里面并没有使用auth登录认证等,使用配置文件也是老的版本写法,YAML版本配置文件写法如下:)

# Where and how to store data.
storage:
  dbPath: D:\MS\Master\DB
  journal:
    enabled: true

# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path: D:\MS\Master\LOG\m.log

# network interfaces
net:
  port: 29991

#processManagement:

#security:

#operationProfiling:

#replication:

#sharding:

## Enterprise-Only Options:

#auditLog:

#snmp:

项目文件

2. keepalived 用途

Keepalived是基于VRRP协议的高级应用,作用于网络层、传输层和应用层交换机制的处理高可用的软件。

主要用作RealServer的健康状态检查以及LoadBalance主机和BackUP主机之间failover的实现。

Keepalived起初是为LVS设计的,专门用来监控集群系统中各个服务节点的状态。它根据layer3,
4 &
5交换机制检测每个服务节点的状态,如果某个服务节点出现异常,或工作出现故障,Keepalived将检测到,并将出现故障的服务节点从集群系统中剔除,而在故障节点恢复正常后,Keepalived又可以自动将此服务节点重新加入到服务器集群中,这些工作全部自动完成,不需要人工干涉,需要人工完成的只是修复出现故障的服务节点。

Keepalived后来又加入了VRRP的功能,VRRP是Virtual Router Redundancy
Protocol(虚拟路由器冗余协议)的缩写,它出现的目的是为了解决静态路由出现的单点故障问题,通过VRRP可以实现网络不间断地、稳定地运行。因此,Keepalived一方面具有服务器状态检测和故障隔离功能,另一方面也具有HA
cluster功能。

keepalived可以实现轻量级的高可用,一般用于前端高可用,且不需要共享存储,一般常用于两个节点的高可用(常见的前端高可用组合有LVS+Keepalived、Nginx+Keepalived、HAproxy+Keepalived)。

DR1和DR2部署keepalived和lvs作主从架构或主主架构,RS1和RS2部署nginx搭建web站点。

进行主从复制启动的三个线程
Binlog dump线程:将二进制日志的内容发送给从服务器
I/O从线程:将接受的的数据写入到中继日志
SQL线程:一次从中继日志中读出一句SQL语句在从服务器上执行

Keepalived是Linux下一个轻量级别的高可用解决方案。高可用(High
Avalilability,HA),其实两种不同的含义:广义来讲,是指整个系统的高可用行,狭义的来讲就是之主机的冗余和接管,

3. Keepalived 工作原理

Keepalived作为一个高性能集群软件,它还能实现对集群中服务器运行状态的监控及故障隔离。接下来介绍下Keepalived对服务器运行状态监控和检测的工作原理。
Keepalived工作在TCP/IP参考模型的第三、第四和第五层,也就是网络层、传输层和应用层。根据TCP/IP参考模型各层所能实现的功能,Keepalived运行机制如下:

  1. 在网络层,运行着四个重要的协议:互连网协议IP、互连网控制报文协议ICMP、地址转换协议ARP以及反向地址转换协议RARP。Keepalived在网络层采用的最常见的工作方式是通过ICMP协议向服务器集群中的每个节点发送一个ICMP的数据包(类似于ping实现的功能),如果某个节点没有返回响应数据包,那么就认为此节点发生了故障,Keepalived将报告此节点失效,并从服务器集群中剔除故障节点。
  2. 在传输层,提供了两个主要的协议:传输控制协议TCP和用户数据协议UDP。传输控制协议TCP可以提供可靠的数据传输服务,IP地址和端口,代表一个TCP连接的一个连接端。要获得TCP服务,须在发送机的一个端口上和接收机的一个端口上建立连接,而Keepalived在传输层就是利用TCP协议的端口连接和扫描技术来判断集群节点是否正常的。比如,对于常见的Web服务默认的80端口、SSH服务默认的22端口等,Keepalived一旦在传输层探测到这些端口没有响应数据返回,就认为这些端口发生异常,然后强制将此端口对应的节点从服务器集群组中移除。
  3. 在应用层,可以运行FTP、TELNET、SMTP、DNS等各种不同类型的高层协议,Keepalived的运行方式也更加全面化和复杂化,用户可以通过自定义Keepalived的工作方式,例如用户可以通过编写程序来运行Keepalived,而Keepalived将根据用户的设定检测各种程序或服务是否允许正常,如果Keepalived的检测结果与用户设定不一致时,Keepalived将把对应的服务从服务器中移除。

  4. 安装


在线安装:

# yum -y install keepalived ipvsadm

或者源码安装:

# wget http://www.keepalived.org/software/keepalived-1.2.15.tar.gz
# tar -xf keepalived-1.2.15.tar.gz && cd keepalived-1.2.15
# ./configure && make && make install
# wget http://www.linuxvirtualserver.org/software/kernel-2.6/ipvsadm-1.26.tar.gz
# tar -xf ipvsadm-1.26.tar.gz && cd ipvsadm-1.26/
# make && make install

关闭SELinux(改完需重启服务器):

# sed -i 's#^SELINUX=.*#SELINUX=disabled#' /etc/sysconfig/selinux   

注意:各节点的时间需要同步(ntpdate
ntp1.aliyun.com);关闭firewalld(systemctl stop
firewalld.service,systemctl disable
firewalld.service),设置selinux为permissive(setenforce
0);同时确保各网卡支持MULTICAST(多播)通信。

一、主从复制:
准备工作:
1.修改配置文件(server_id一定要修改)
2.建立复制用户
3.启动从服务器的从服务进程

它与HeartBeat RoseHA
实现相同类似的功能,都可以实现服务或者网络的高可用,但是又有差别,HeartBeat是一个专业的、功能完善的高可用软件,它提供了HA
软件所需的基本功能,比如:心跳检测、资源接管,检测集群中的服务,在集群节点转移共享IP地址的所有者等等。HeartBeat功能强大,但是部署和使用相对比较麻烦,

5. 配置服务

本文搭建、测试Keepalived高可用架构。测试环境使用两台真实服务器,如下介绍:

虚拟ip     : 192.168.14.166,默认指向Master(192.168.14.8)
真实服务器1 : Master,192.168.14.8 该机器上运行Apache Httpd服务(端口80)8000);
真实服务器2 : Backup,192.168.14.14 该机器上同时运行Apache Httpd服务(端口80)
系统部署结构如下所示:  

                   +-------------+
                   |    router   |
                   +-------------+
                          |
                          +
    Master            keepalived           Backup
  192.168.14.8      192.168.14.166     192.168.14.14
+-------------+    +-------------+    +-------------+
|  httpd_01   |----| virtual IP  |----|  httpd_01   |
+-------------+    +-------------+    +-------------+   

在Master和Backup的运行的两个测试服务单独运行效果如下:

Master(192.168.14.8):可以访问

Backup(192.168.14.14):可以访问

此时 虚拟ip(192.168.14.166)是不存在的,也即无法访问。

通过命令ifconfig可以查看到是否开启了MULTICAST:

规划:
Master:IP地址:172.16.4.11    版本:mysql-5.5.20
Slave:IP地址:172.16.4.12    版本:mysql-5.5.20
这里需注意,mysql复制大部分都是后向兼容,所以,从服务器的版本一定要高于或等于主服务器的版本。
1、Master
修改配置文件,将其设为mysql主服务器
#vim /etc/my.cnf
server_id=11                #修改server_id=11
log_bin=mysql-bin            #开启二进制日志
sync_binlog=1              
#任何一个事务提交之后就立即写入到磁盘中的二进制文件
innodb_flush_logs_at_trx_commit=1      
#任何一个事物提交之后就立即写入到磁盘中的日志文件

与HeartBeat相比,Keepalived主要是通过虚拟路由冗余来实现高可用功能,虽然它没有HeartBeat功能强大,但是Keepalived部署和使用非常的简单,所有配置只需要一个配置文件即可以完成。

5.1 创建keepalived配置文件

keepalived只有一个配置文件keepalived.conf,里面主要包括以下几个配置区域,分别是global_defs、vrrp_script、vrrp_instance和virtual_server。

其中vrrp_instance区域用来定义对外提供服务的VIP区域及其相关属性,
而virtual_server和real_server区域是用来配合lvs使用的,本次暂时用不到。

在Master(192.168.14.8)上:

# cat /etc/keepalived/keepalived.conf
global_defs {
    notification_email {
        #mr@mruse.cn       # 指定keepalived在发生切换时需要发送email到的对象,一行一个
        #sysadmin@firewall.loc
    }
    notification_email_from xxx@163.com   # 指定发件人
    smtp_server smtp@163.com              # smtp 服务器地址
    smtp_connect_timeout 30               # smtp 服务器连接超时时间
    router_id LVS_1 # 标识本节点的字符串,通常为hostname,但不一定非得是hostname,故障发生时,邮件通知会用到
}

vrrp_instance VI_1 {  # 实例名称
    state MASTER      # 可以是MASTER或BACKUP,不过当其他节点keepalived启动时会将priority比较大的节点选举为MASTER
    interface eth0    # 节点固有IP(非VIP)的网卡,用来发VRRP包做心跳检测
    virtual_router_id 51 # 虚拟路由ID,取值在0-255之间,用来区分多个instance的VRRP组播,同一网段内ID不能重复;主备必须为一样;
    priority 100      # 用来选举master的,要成为master那么这个选项的值最好高于其他机器50个点,该项取值范围是1-255(在此范围之外会被识别成默认值100)
    advert_int 1      # 检查间隔默认为1秒,即1秒进行一次master选举(可以认为是健康查检时间间隔)
    authentication {  # 认证区域,认证类型有PASS和HA(IPSEC),推荐使用PASS(密码只识别前8位)
        auth_type PASS  # 默认是PASS认证
        auth_pass MrUse # PASS认证密码
    }
    virtual_ipaddress {
        192.168.14.166    # 虚拟VIP地址,允许多个
    }
}

在Backup(192.168.14.14)上keepalived.conf文件和Master上的基本一致,拷贝过来,并修改其中的以下几项即可:

state BACKUP     # 此值可设置或不设置,只要保证下面的priority不一致即可
interface eth0   # 根据实际情况选择网卡
priority 40      # 此值要一定小于Master机器上的值,最好相差不少于50

注意:在配置keepalived.conf时,需要特别注意配置文件的语法格式以及出现重复的VIP,因为keepalived在启动时并不检测配置文件的正确性,即使没有配置文件,keepalived也能照样启动,所以一定要保证配置文件的正确性。

启动Keepalived并加入开机启动:

/etc/init.d/keepalived restart
chkconfig keepalived on

启动Keepalived:

# service keepalived start  # 此时会尝试读取/etc/keepalived/keepalived.conf配置文件
如果配置文件位于其他地方,则:
# keepalived -f /xxx/path/keepalived.conf

启动之后,keepalived会运行三个进程:

# ps -ef | grep keepalived
root      2030     1  0 08:59 ?        00:00:01 keepalived -f /etc/keepalived/keepalived.conf
root      2041  2030  0 08:59 ?        00:00:01 keepalived -f /etc/keepalived/keepalived.conf
root      2042  2030  0 08:59 ?        00:00:03 keepalived -f /etc/keepalived/keepalived.conf

通过以下命令可以查看VIP当前绑定在哪个机器上:

# ip addr 
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 08:00:27:8e:b8:31 brd ff:ff:ff:ff:ff:ff
    inet 192.168.14.8/16 brd 192.168.255.255 scope global eth0
    inet 192.168.14.166/32 scope global eth0            ## 注意此行

     
 图片 7

保存退出
#service mysql reload             #重新载入mysql的配置文件

keepalived的工作原理如下:

5.2 测试正常情况

在Master和Backup上分别启动keepalived

此时VIP(192.168.14.166)是可访问的,也可以ping通,通过虚拟ip(192.168.14.166)访问测试服务,会发现此时VIP(192.168.14.166)指向了Master(192.168.14.8)上的服务。如果从另一台机器上通过ssh连接VIP(192.168.14.166),可以登陆成功且登陆的主机即是Master(192.168.14.8)。

此时在Master(192.168.14.8)上运行以下命令,会发现VIP绑定在了Master上:

# ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:8e:b8:31 brd ff:ff:ff:ff:ff:ff
inet 192.168.14.8/16 brd 192.168.255.255 scope global eth0

keepalived的主从架构

2、Master上创建用户,授予复制权限
mysql>grant replication client,replication slave on *.* to
repl@172.16.4.12 identified by ‘135246’;
mysql>flush privileges;

Keepalived工作在TCP/IP 参考模型的
三层、四层、五层,也就是分别为:网络层,

5.3 测试Master宕掉的情况

现在停掉Master(192.168.14.8)上的keepalived用来模拟Master机器宕掉或者网络不通,此时再通过虚拟ip(192.168.14.166)访问两个测试服务会发现所有服务都已指向了Backup(192.168.14.14):

此时在Backup(192.168.14.14)上运行以下命令,会发现VIP绑定在了Backup上:

# ip addr show eth0 
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:76:6c:46 brd ff:ff:ff:ff:ff:ff
inet 192.168.14.14/16 brd 192.168.255.255 scope global eth0
inet 192.168.14.166/32 scope global eth0 而Master上已经没有了该VIP(192.168.14.166)。

搭建RS1:

[root@RS1 ~]# yum -y install nginx   #安装nginx
[root@RS1 ~]# vim /usr/share/nginx/html/index.html   #修改主页
    <h1> 192.168.4.118 RS1 server </h1>
[root@RS1 ~]# systemctl start nginx.service   #启动nginx服务
[root@RS1 ~]# vim RS.sh   #配置lvs-dr的脚本文件
    #!/bin/bash
    #
    vip=192.168.4.120
    mask=255.255.255.255
    case $1 in
    start)
        echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
        echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
        echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
        echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
        ifconfig lo:0 $vip netmask $mask broadcast $vip up
        route add -host $vip dev lo:0
        ;;
    stop)
        ifconfig lo:0 down
        echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
        echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
        echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
        echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
        ;;
    *) 
        echo "Usage $(basename $0) start|stop"
        exit 1
        ;;
    esac
[root@RS1 ~]# bash RS.sh start

3、Slave
修改配置文件,将其设置为一个mysql从服务器
#vim /etc/my.cnf
server_id=12                #修改server_id=12
#log-bin               
#注释掉log-bin,从服务器不需要二进制日志,因此将其关闭
relay-log=mysql-relay               
#定义中继日志名,开启从服务器中继日志
relay-log-index=mysql-relay.index    
#定义中继日志索引名,开启从服务器中继索引
read_only=1                   
#设定从服务器只能进行读操作,不能进行写操作

传输层和应用层,根据TCP、IP参数模型隔层所能实现的功能,Keepalived运行机制如下:

5.4 测试Master宕掉又恢复的情况

接上一测试,此时再重新启动Master(192.168.14.8)上的keepalived,模拟Master机器已开机或网络已修复,,此时再通过虚拟ip(192.168.14.166)访问两个测试服务会发现所有服务又都重新指向了Master(192.168.14.8)。

参考RS1的配置搭建RS2。

保存退出
#service mysql reload             #重新载入mysql的配置文件

在网络层:我们知道运行这4个重要的协议,互联网络IP协议,互联网络可控制报文协议ICMP、地址转换协议ARP、反向地址转换协议RARP,在网络层Keepalived在网络层采用最常见的工作方式是通过ICMP协议向服务器集群中的每一个节点发送一个ICMP数据包(有点类似与Ping的功能),如果某个节点没有返回响应数据包,那么认为该节点发生了故障,Keepalived将报告这个节点失效,并从服务器集群中剔除故障节点。

6 解决Master存在但服务宕掉的问题

如果解决上面VIP指向Master,但是Master上服务宕掉的问题呢?其实也简单,我们在keepalived.conf中增加对Httpd服务的检测(完整配置文件):

# cat /etc/keepalived/keepalived.conf 
global_defs {
   notification_email {
   #  acassen@firewall.loc   # 指定keepalived在发生切换时需要发送email到的对象,一行一个
   #  sysadmin@firewall.loc
   }
   #notification_email_from Alexandre.Cassen@firewall.loc  # 指定发件人
   #smtp_server 192.168.200.1     # smtp 服务器地址 
   #smtp_connect_timeout 30       # smtp 服务器连接超时时间
   router_id LVS_DEVEL            # 标识本节点的字符串,通常为hostname,但不一定非得是hostname,故障发生时,邮件通知会用到
}
### 新增 ###
vrrp_script chk_httpd {
    script "/etc/keepalived/check_and_start_httpd.sh"   # apache httpd 服务检测并试图重启
    interval 2                    # 每2s检查一次
    weight -5                     # 检测失败(脚本返回非0)则优先级减少5个值
    fall 3                        # 如果连续失败次数达到此值,则认为服务器已down
    rise 2                        # 如果连续成功次数达到此值,则认为服务器已up,但不修改优先级
}

vrrp_instance VI_1 {              # 实例名称
    state MASTER                  # 可以是MASTER或BACKUP,不过当其他节点keepalived启动时会自动将priority比较大的节点选举为MASTER
    interface eth0                # 节点固有IP(非VIP)的网卡,用来发VRRP包做心跳检测
    virtual_router_id 51          # 虚拟路由ID,取值在0-255之间,用来区分多个instance的VRRP组播,同一网段内ID不能重复;主备必须为一样
    priority 100                  # 用来选举master的,要成为master那么这个选项的值最好高于其他机器50个点,该项取值范围是1-255(在此范围之外会被识别成默认值100)
    advert_int 1                  # 检查间隔默认为1秒,即1秒进行一次master选举(可以认为是健康查检时间间隔)
    authentication {              # 认证区域,认证类型有PASS和HA(IPSEC),推荐使用PASS(密码只识别前8位)
        auth_type PASS            # 默认是PASS认证
        auth_pass 1111            # PASS认证密码
    }
    virtual_ipaddress {
        192.168.14.166            # 虚拟VIP地址,允许多个,一行一个
    #    192.168.200.17
    }
    ### 新增 ###
    track_script {                # 引用VRRP脚本,即在 vrrp_script 部分指定的名字。定期运行它们来改变优先级,并最终引发主备切换。
        chk_httpd          
    }                
}

再写一个脚本:

# cat /etc/keepalived/check_and_start_httpd.sh 
#!/bin/bash
counter=$(ps -C httpd --no-heading|wc -l)
if [ "${counter}" = "0" ]; then
    service httpd start
    sleep 2
    counter=$(ps -C httpd --no-heading|wc -l)
    if [ "${counter}" = "0" ]; then
        /etc/rc.d/init.d/keepalived stop
    fi
fi 该脚本的目的是用来检测httpd服务是否存在,如果不存在就重启,重启失败就关闭本机keepalived以便VIP切换到Backup机器上。该脚本由keepalived进行调用。

此时停掉Apache Httpd服务:

# date && service httpd status
2016年 09月 13日 星期二 11:32:07 CST
httpd (pid  20374) 正在运行...
# date && service httpd stop  
2016年 09月 13日 星期二 11:32:13 CST
停止 httpd:                                               [确定]
# date && service httpd status
2016年 09月 13日 星期二 11:32:14 CST
httpd (pid  21623) 正在运行...

可以发现Httpd停掉之后就进行自动重启了(前后pid不一样),而且重启速度也比较快(从date显示的时间可以看到)。当然这也不能保证所有的Http请求都不丢弃(事实上很可能有部分请求是失败的)。

搭建DR1:

[root@DR1 ~]# yum -y install ipvsadm keepalived   #安装ipvsadm和keepalived
[root@DR1 ~]# vim /etc/keepalived/keepalived.conf   #修改keepalived.conf配置文件
    global_defs {
       notification_email {
         root@localhost
       }
       notification_email_from keepalived@localhost
       smtp_server 127.0.0.1
       smtp_connect_timeout 30
       router_id 192.168.4.116
       vrrp_skip_check_adv_addr
       vrrp_mcast_group4 224.0.0.10
    }

    vrrp_instance VIP_1 {
        state MASTER
        interface eno16777736
        virtual_router_id 1
        priority 100
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass %&hhjj99
        }
        virtual_ipaddress {
          192.168.4.120/24 dev eno16777736 label eno16777736:0
        }
    }

    virtual_server 192.168.4.120 80 {
        delay_loop 6
        lb_algo rr
        lb_kind DR
        protocol TCP

        real_server 192.168.4.118 80 {
            weight 1
            HTTP_GET {
                url {
                  path /index.html
                  status_code 200
                }
                connect_timeout 3
                nb_get_retry 3
                delay_before_retry 3
            }
        }
        real_server 192.168.4.119 80 {
            weight 1
            HTTP_GET {
                url {
                  path /index.html
                  status_code 200
                }
                connect_timeout 3
                nb_get_retry 3
                delay_before_retry 3
            }
         }
    }
[root@DR1 ~]# systemctl start keepalived
[root@DR1 ~]# ifconfig
    eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 192.168.4.116  netmask 255.255.255.0  broadcast 192.168.4.255
            inet6 fe80::20c:29ff:fe93:270f  prefixlen 64  scopeid 0x20<link>
            ether 00:0c:29:93:27:0f  txqueuelen 1000  (Ethernet)
            RX packets 14604  bytes 1376647 (1.3 MiB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 6722  bytes 653961 (638.6 KiB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

    eno16777736:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 192.168.4.120  netmask 255.255.255.0  broadcast 0.0.0.0
            ether 00:0c:29:93:27:0f  txqueuelen 1000  (Ethernet)
[root@DR1 ~]# ipvsadm -ln
    IP Virtual Server version 1.2.1 (size=4096)
    Prot LocalAddress:Port Scheduler Flags
      -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
    TCP  192.168.4.120:80 rr
      -> 192.168.4.118:80             Route   1      0          0         
      -> 192.168.4.119:80             Route   1      0          0

4、验证Slave上中继日志以及server_id是否均生效
mysql>show variables like ‘relay%’;
+———————–+—————–+
| Variable_name         | Value           |
+———————–+—————–+
| relay_log             | relay-bin       |
| relay_log_index       | relay-bin.index |
| relay_log_info_file   | relay-log.info  |
| relay_log_purge       | ON              |
| relay_log_recovery    | OFF             |
| relay_log_space_limit | 0               |
+———————–+—————–+
mysql>show variables like ‘server_id’;
+—————+——-+
| Variable_name | Value |
+—————+——-+
| server_id     | 12    |
+—————+——-+

在传输层:提供了两个主要的协议:传输控制协议TCP和用户数据协议UDP,传输控制协议TCP可以提供可靠的数据输出服务、IP地址和端口,代表TCP的一个连接端,要获得TCP服务,需要在发送机的一个端口和接收机的一个端口上建立连接,而Keepalived在传输层里利用了TCP协议的端口连接和扫描技术来判断集群节点的端口是否正常,比如对于常见的WEB服务器80端口。或者SSH服务22端口,Keepalived一旦在传输层探测到这些端口号没有数据响应和数据返回,就认为这些端口发生异常,然后强制将这些端口所对应的节点从服务器集群中剔除掉。

vrrp_script

告诉 keepalived 在什么情况下切换,所以尤为重要。可以有多个 vrrp_script

  • script : 自己写的检测脚本。也可以是一行命令如killall -0 nginx
  • interval 2 : 每2s检测一次
  • weight -5 : 检测失败(脚本返回非0)则优先级 -5
  • fall 2 : 检测连续 2
    次失败才算确定是真失败。会用weight减少优先级(1-255之间)
  • rise 1 : 检测 1 次成功就算成功。但不修改优先级

这里要提示一下script一般有2种写法:

  1. 通过脚本执行的返回结果,改变优先级,keepalived继续发送通告消息,backup比较优先级再决定
  2. 脚本里面检测到异常,直接关闭keepalived进程,backup机器接收不到advertisement会抢占IP

上文 vrrp_script
配置部分/etc/keepalived/check_and_start_httpd.sh属于第2种情况(脚本中关闭keepalived)。个人更倾向于通过shell脚本判断,但有异常时exit
1,正常退出exit 0,然后keepalived根据动态调整的 vrrp_instance
优先级选举决定是否抢占VIP:

  • 如果脚本执行结果为0,并且weight配置的值大于0,则优先级相应的增加
  • 如果脚本执行结果非0,并且weight配置的值小于0,则优先级相应的减少
  • 其他情况,原本配置的优先级不变,即配置文件中priority对应的值

提示:

  • 优先级不会不断的提高或者降低
  • 可以编写多个检测脚本并为每个检测脚本设置不同的weight(在配置中列出就行)
  • 不管提高优先级还是降低优先级,最终优先级的范围是在[1,254],不会出现优先级小于等于0或者优先级大于等于255的情况
  • 在MASTER节点的 vrrp_instance 中 配置 nopreempt
    ,当它异常恢复后,即使它 prio
    更高也不会抢占,这样可以避免正常情况下做无谓的切换

以上可以做到利用脚本检测业务进程的状态,并动态调整优先级从而实现主备切换。

上面写的check_and_start_httpd.sh脚本在发现httpd关闭时会试图重启httpd,如果重启失败则停掉本机的keepalived,以触发主备切换。事实上,脚本内容可以根据自己的业务灵活定义,比如使用curl命令连续获取2次主页,如果3s内没有响应则触发切换:

#!/bin/bash
count=0
for (( k=0; k<2; k++ ))
do
    check_code=$( curl --connect-timeout 3 -sL -w "%{http_code}\\n" http://localhost/index.html -o /dev/null )
    if [ "$check_code" != "200" ]; then
        count=$(expr $count + 1)
        sleep 3
        continue
    else
        count=0
        break
    fi
done
if [ "$count" != "0" ]; then
#   /etc/init.d/keepalived stop
    exit 1
else
    exit 0
fi

DR2的搭建基本同DR1,主要修改一下配置文件中/etc/keepalived/keepalived.conf的state和priority:state BACKUP、priority 90. 同时我们发现作为backup的DR2没有启用eno16777736:0的网口:

图片 8

5、启动从服务器的从服务进程
场景一、如果主服务器和从服务器都是新建立的,并没有新增其他数据,则执行以下命令:
mysql>change master to \
master_host=’172.16.4.11′,
master_user=’repl’,
master_password=’135246′;
mysql>show slave status\G
*************************** 1. row
***************************
Slave_IO_State:
Master_Host: 172.16.4.11
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 107
Relay_Log_File: relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: No
Slave_SQL_Running: No
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: 25520
Relay_Log_Space: 2565465
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: NULL
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: 0
mysql>start slave;
mysql>show slave status\G
*************************** 1. row
***************************
Slave_IO_State: Queueing master event to the relay log
Master_Host: 172.16.4.11
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 107
Relay_Log_File: relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000001
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: 360
Relay_Log_Space: 300
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: 11

在应用层:可以运行FTP,TELNET,SMTP,DNS等各种不同类型的高层协议,Keepalived的运行方式也更加全面化和复杂化,用户可以通过自定义Keepalived工作方式,例如:可以通过编写程序或者脚本来运行Keepalived,而Keepalived将根据用户的设定参数检测各种程序或者服务是否允许正常,如果Keepalived的检测结果和用户设定的不一致时,Keepalived将把对应的服务器从服务器集群中剔除

7. 其他

以上演示中,主要以Apache
Httpd作为测试服务,其实这里使用Nginx也是可以的,这样就相当于Nginx是前端,做到高可用,然后Nginx上部署反向代理、负载均衡,将业务请求转发到真实的业务服务器上,一套主备切换+负载均衡的高可用架构就形成了

客户端进行测试:

[root@client ~]# for i in {1..20};do curl http://192.168.4.120;done   #客户端正常访问
<h1> 192.168.4.119 RS2 server</h1>
<h1> 192.168.4.118 RS1 server </h1>
<h1> 192.168.4.119 RS2 server</h1>
<h1> 192.168.4.118 RS1 server </h1>
<h1> 192.168.4.119 RS2 server</h1>
<h1> 192.168.4.118 RS1 server </h1>
<h1> 192.168.4.119 RS2 server</h1>
<h1> 192.168.4.118 RS1 server </h1>
<h1> 192.168.4.119 RS2 server</h1>
<h1> 192.168.4.118 RS1 server </h1>
<h1> 192.168.4.119 RS2 server</h1>
<h1> 192.168.4.118 RS1 server </h1>
<h1> 192.168.4.119 RS2 server</h1>
<h1> 192.168.4.118 RS1 server </h1>
<h1> 192.168.4.119 RS2 server</h1>
<h1> 192.168.4.118 RS1 server </h1>
<h1> 192.168.4.119 RS2 server</h1>
<h1> 192.168.4.118 RS1 server </h1>
<h1> 192.168.4.119 RS2 server</h1>
<h1> 192.168.4.118 RS1 server </h1>

[root@DR1 ~]# systemctl stop keepalived.service   #关闭DR1的keepalived服务

[root@DR2 ~]# systemctl status keepalived.service   #观察DR2,可以看到DR2已经进入MASTER状态
● keepalived.service - LVS and VRRP High Availability Monitor
   Loaded: loaded (/usr/lib/systemd/system/keepalived.service; disabled; vendor preset: disabled)
   Active: active (running) since Tue 2018-09-04 11:33:04 CST; 7min ago
  Process: 12983 ExecStart=/usr/sbin/keepalived $KEEPALIVED_OPTIONS (code=exited, status=0/SUCCESS)
 Main PID: 12985 (keepalived)
   CGroup: /system.slice/keepalived.service
           ├─12985 /usr/sbin/keepalived -D
           ├─12988 /usr/sbin/keepalived -D
           └─12989 /usr/sbin/keepalived -D

Sep 04 11:37:41 happiness Keepalived_healthcheckers[12988]: SMTP alert successfully sent.
Sep 04 11:40:22 happiness Keepalived_vrrp[12989]: VRRP_Instance(VIP_1) Transition to MASTER STATE
Sep 04 11:40:23 happiness Keepalived_vrrp[12989]: VRRP_Instance(VIP_1) Entering MASTER STATE
Sep 04 11:40:23 happiness Keepalived_vrrp[12989]: VRRP_Instance(VIP_1) setting protocol VIPs.
Sep 04 11:40:23 happiness Keepalived_vrrp[12989]: Sending gratuitous ARP on eno16777736 for 192.168.4.120
Sep 04 11:40:23 happiness Keepalived_vrrp[12989]: VRRP_Instance(VIP_1) Sending/queueing gratuitous ARPs on eno16777736 for 192.168.4.120
Sep 04 11:40:23 happiness Keepalived_vrrp[12989]: Sending gratuitous ARP on eno16777736 for 192.168.4.120
Sep 04 11:40:23 happiness Keepalived_vrrp[12989]: Sending gratuitous ARP on eno16777736 for 192.168.4.120
Sep 04 11:40:23 happiness Keepalived_vrrp[12989]: Sending gratuitous ARP on eno16777736 for 192.168.4.120
Sep 04 11:40:23 happiness Keepalived_vrrp[12989]: Sending gratuitous ARP on eno16777736 for 192.168.4.120

[root@client ~]# for i in {1..20};do curl http://192.168.4.120;done   #可以看到客户端正常访问
<h1> 192.168.4.119 RS2 server</h1>
<h1> 192.168.4.118 RS1 server </h1>
<h1> 192.168.4.119 RS2 server</h1>
<h1> 192.168.4.118 RS1 server </h1>
<h1> 192.168.4.119 RS2 server</h1>
<h1> 192.168.4.118 RS1 server </h1>
<h1> 192.168.4.119 RS2 server</h1>
<h1> 192.168.4.118 RS1 server </h1>
<h1> 192.168.4.119 RS2 server</h1>
<h1> 192.168.4.118 RS1 server </h1>
<h1> 192.168.4.119 RS2 server</h1>
<h1> 192.168.4.118 RS1 server </h1>
<h1> 192.168.4.119 RS2 server</h1>
<h1> 192.168.4.118 RS1 server </h1>
<h1> 192.168.4.119 RS2 server</h1>
<h1> 192.168.4.118 RS1 server </h1>
<h1> 192.168.4.119 RS2 server</h1>
<h1> 192.168.4.118 RS1 server </h1>
<h1> 192.168.4.119 RS2 server</h1>
<h1> 192.168.4.118 RS1 server </h1>

场景二、如果主服务器已经运行过一段了,从服务器是新添加的,则需要将主服务器之前的数据导入到从服务器中:
Master:
#mysqldump -uroot -hlocalhost -p123456 –all-databases
–lock-all-tables –flush-logs –master-data=2 >
/backup/alldatabase.sql
mysql>flush tables with read lock;
mysql>show master status;
+——————+———-+————–+——————+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+——————+———-+————–+——————+
| mysql-bin.000004 |      360 |              |                  |
+——————+———-+————–+——————+
mysql>unlock tables;
#scp /backup/alldatabase.sql 172.16.4.12:/tmp

看一下基本环境

keepalived的主主架构

Slave:
#mysql -uroot -p123456 < /tmp/alldatabase.sql
mysql>change master to \
master_host=’172.16.4.11′,
master_user=’repl’,
master_password=’135246′,
master_log_file=’mysql-bin.000004′,
master_log_pos=360;
mysql>show slave status\G
*************************** 1. row
***************************
Slave_IO_State:
Master_Host: 172.16.4.11
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 360
Relay_Log_File: relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000004
Slave_IO_Running: No
Slave_SQL_Running: No
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: 360
Relay_Log_Space: 107
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: NULL
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: 0
mysql>start slave;

server1:MySQL5.7.14+keepalived1.2+172.16.16.34
server2:MySQL5.7.14+keepalived1.2+172.16.16.35
VIP:172.16.16.20

 修改RS1和RS2,添加新的VIP:

[root@RS1 ~]# cp RS.sh RS_bak.sh
[root@RS1 ~]# vim RS_bak.sh   #添加新的VIP
    #!/bin/bash
    #
    vip=192.168.4.121
    mask=255.255.255.255
    case $1 in
    start)
        echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
        echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
        echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
        echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
        ifconfig lo:1 $vip netmask $mask broadcast $vip up
        route add -host $vip dev lo:1
        ;;
    stop)
        ifconfig lo:1 down
        echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
        echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
        echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
        echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce
        ;;
    *)
        echo "Usage $(basename $0) start|stop"
        exit 1
        ;;
    esac
[root@RS1 ~]# bash RS_bak.sh start
[root@RS1 ~]# ifconfig
    ...
    lo:0: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
            inet 192.168.4.120  netmask 255.255.255.255
            loop  txqueuelen 0  (Local Loopback)

    lo:1: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
            inet 192.168.4.121  netmask 255.255.255.255
            loop  txqueuelen 0  (Local Loopback) 
[root@RS1 ~]# scp RS_bak.sh root@192.168.4.119:~
root@192.168.4.119's password: 
RS_bak.sh                100%  693     0.7KB/s   00:00

[root@RS2 ~]# bash RS_bak.sh   #直接运行脚本添加新的VIP 
[root@RS2 ~]# ifconfig
    ...
    lo:0: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
            inet 192.168.4.120  netmask 255.255.255.255
            loop  txqueuelen 0  (Local Loopback)

    lo:1: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
            inet 192.168.4.121  netmask 255.255.255.255
            loop  txqueuelen 0  (Local Loopback)

mysql>show slave status\G
*************************** 1. row
***************************
Slave_IO_State: Queueing master event to the relay log
Master_Host: 172.16.4.11
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 360
Relay_Log_File: relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000004
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: 360
Relay_Log_Space: 300
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: 11

我们两台机器是搭建的MySQL双主,我们平时只会通过VIP对MySQL进行读写,我们要实现的是,当VIP所在的主机的MySQLDOWN掉以后,VIP能够切换到另外一台机器上并且继续提供服务。

修改DR1和DR2:

[root@DR1 ~]# vim /etc/keepalived/keepalived.conf   #修改DR1的配置文件,添加新的实例,配置服务器组
    ...
    vrrp_instance VIP_2 {
        state BACKUP
        interface eno16777736
        virtual_router_id 2
        priority 90
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass UU**99^^
        }
        virtual_ipaddress {
            192.168.4.121/24 dev eno16777736 label eno16777736:1
        }
    }

    virtual_server_group ngxsrvs {
        192.168.4.120 80
        192.168.4.121 80
    }
    virtual_server group ngxsrvs {
        ...
    }
[root@DR1 ~]# systemctl restart keepalived.service   #重启服务
[root@DR1 ~]# ifconfig   #此时可以看到eno16777736:1,因为DR2还未配置
    eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 192.168.4.116  netmask 255.255.255.0  broadcast 192.168.4.255
            inet6 fe80::20c:29ff:fe93:270f  prefixlen 64  scopeid 0x20<link>
            ether 00:0c:29:93:27:0f  txqueuelen 1000  (Ethernet)
            RX packets 54318  bytes 5480463 (5.2 MiB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 38301  bytes 3274990 (3.1 MiB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

    eno16777736:0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 192.168.4.120  netmask 255.255.255.0  broadcast 0.0.0.0
            ether 00:0c:29:93:27:0f  txqueuelen 1000  (Ethernet)

    eno16777736:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 192.168.4.121  netmask 255.255.255.0  broadcast 0.0.0.0
            ether 00:0c:29:93:27:0f  txqueuelen 1000  (Ethernet)
[root@DR1 ~]# ipvsadm -ln
    IP Virtual Server version 1.2.1 (size=4096)
    Prot LocalAddress:Port Scheduler Flags
      -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
    TCP  192.168.4.120:80 rr
      -> 192.168.4.118:80             Route   1      0          0         
      -> 192.168.4.119:80             Route   1      0          0         
    TCP  192.168.4.121:80 rr
      -> 192.168.4.118:80             Route   1      0          0         
      -> 192.168.4.119:80             Route   1      0          0

[root@DR2 ~]# vim /etc/keepalived/keepalived.conf   #修改DR2的配置文件,添加实例,配置服务器组
    ...
    vrrp_instance VIP_2 {
        state MASTER
        interface eno16777736
        virtual_router_id 2
        priority 100
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass UU**99^^
        }
        virtual_ipaddress {
            192.168.4.121/24 dev eno16777736 label eno16777736:1
        }
    }

    virtual_server_group ngxsrvs {
        192.168.4.120 80
        192.168.4.121 80
    }
    virtual_server group ngxsrvs {
        ...
    }
[root@DR2 ~]# systemctl restart keepalived.service   #重启服务
[root@DR2 ~]# ifconfig
    eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 192.168.4.117  netmask 255.255.255.0  broadcast 192.168.4.255
            inet6 fe80::20c:29ff:fe3d:a31b  prefixlen 64  scopeid 0x20<link>
            ether 00:0c:29:3d:a3:1b  txqueuelen 1000  (Ethernet)
            RX packets 67943  bytes 6314537 (6.0 MiB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 23250  bytes 2153847 (2.0 MiB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

    eno16777736:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 192.168.4.121  netmask 255.255.255.0  broadcast 0.0.0.0
            ether 00:0c:29:3d:a3:1b  txqueuelen 1000  (Ethernet)
[root@DR2 ~]# ipvsadm -ln
    IP Virtual Server version 1.2.1 (size=4096)
    Prot LocalAddress:Port Scheduler Flags
      -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
    TCP  192.168.4.120:80 rr
      -> 192.168.4.118:80             Route   1      0          0         
      -> 192.168.4.119:80             Route   1      0          0         
    TCP  192.168.4.121:80 rr
      -> 192.168.4.118:80             Route   1      0          0         
      -> 192.168.4.119:80             Route   1      0          0 

说明MySQL的主从复制架构成功

我们假设MySQL双主已经搭建成功了,如果还不会的话,可以看我的以前博客,MySQL二进制安装双主结构:

客户端测试:

[root@client ~]# for i in {1..20};do curl http://192.168.4.120;done
    <h1> 192.168.4.119 RS2 server</h1>
    <h1> 192.168.4.118 RS1 server </h1>
    <h1> 192.168.4.119 RS2 server</h1>
    <h1> 192.168.4.118 RS1 server </h1>
    <h1> 192.168.4.119 RS2 server</h1>
    <h1> 192.168.4.118 RS1 server </h1>
    <h1> 192.168.4.119 RS2 server</h1>
    <h1> 192.168.4.118 RS1 server </h1>
    <h1> 192.168.4.119 RS2 server</h1>
    <h1> 192.168.4.118 RS1 server </h1>
    <h1> 192.168.4.119 RS2 server</h1>
    <h1> 192.168.4.118 RS1 server </h1>
    <h1> 192.168.4.119 RS2 server</h1>
    <h1> 192.168.4.118 RS1 server </h1>
    <h1> 192.168.4.119 RS2 server</h1>
    <h1> 192.168.4.118 RS1 server </h1>
    <h1> 192.168.4.119 RS2 server</h1>
    <h1> 192.168.4.118 RS1 server </h1>
    <h1> 192.168.4.119 RS2 server</h1>
    <h1> 192.168.4.118 RS1 server </h1>
[root@client ~]# for i in {1..20};do curl http://192.168.4.121;done
    <h1> 192.168.4.119 RS2 server</h1>
    <h1> 192.168.4.118 RS1 server </h1>
    <h1> 192.168.4.119 RS2 server</h1>
    <h1> 192.168.4.118 RS1 server </h1>
    <h1> 192.168.4.119 RS2 server</h1>
    <h1> 192.168.4.118 RS1 server </h1>
    <h1> 192.168.4.119 RS2 server</h1>
    <h1> 192.168.4.118 RS1 server </h1>
    <h1> 192.168.4.119 RS2 server</h1>
    <h1> 192.168.4.118 RS1 server </h1>
    <h1> 192.168.4.119 RS2 server</h1>
    <h1> 192.168.4.118 RS1 server </h1>
    <h1> 192.168.4.119 RS2 server</h1>
    <h1> 192.168.4.118 RS1 server </h1>
    <h1> 192.168.4.119 RS2 server</h1>
    <h1> 192.168.4.118 RS1 server </h1>
    <h1> 192.168.4.119 RS2 server</h1>
    <h1> 192.168.4.118 RS1 server </h1>
    <h1> 192.168.4.119 RS2 server</h1>
    <h1> 192.168.4.118 RS1 server </h1>

 

注1:MySQL的复制可以基于某个数据库或库中的默写表进行复制,要想实现该功能,只需在其配置文件中添加以下配置:
Master:
binlog-do-db=db_name        只复制db_name数据库
binlog-ignore-db=db_name    不复制db_name数据库

下面开始搭建我们的环境

注2:在Master上定义过滤规则,意味着,任何不涉及到该数据库相关的写操作都不会被记录到二进制日志中,因此不建议在Master上定义过滤规则,并且不建议binlog-do-db与binlog-ignore-db同时定义。

1:安装以及简单配置keepalived

Slave:
replicate_do_db=db_name            只复制db_name数据库
replicate_ignore_db=db_name        不复制db_name数据库
replicate_do_table=tb_name        只复制tb_name表
replicate_ignore_table=tb_name        只复制tb_name表
replicate_wild_do_table=test%       
只复制以test为开头并且后面跟上任意字符的名字的表
replicate_wild_ignore_table=test_   
只复制以test为开头并且后面跟上任意单个字符的名字的表

yum install -y keepalived

注3:如果需要指定多个db或table时,则只需将命令多次写入

 

**

二、半同步复制**

由于Mysql的复制都是基于异步进行的,在特殊情况下不能保证数据的成功复制,因此在mysql
5.5之后使用了来自google补丁,可以将Mysql的复制实现半同步模式。所以需要为主服务器加载对应的插件。在Mysql的安装目录下的lib/plugin/目录中具有对应的插件semisync_master.so,semisync_slave.so

在Master和Slave的mysql命令行运行如下命令:

Master:
mysql> install plugin rpl_semi_sync_master soname
‘semisync_master.so’;
mysql> set global rpl_semi_sync_master_enabled = 1;
mysql> set global rpl_semi_sync_master_timeout = 1000;
mysql> show variables like ‘%semi%’;
+————————————+——-+
| Variable_name                      | Value |
+————————————+——-+
| rpl_semi_sync_master_enabled       | ON    |
| rpl_semi_sync_master_timeout       | 1000  |
| rpl_semi_sync_master_trace_level   | 32    |
| rpl_semi_sync_master_wait_no_slave | ON    |
+————————————+——-+

Slave:
mysql> install plugin rpl_semi_sync_slave soname
‘semisync_slave.so’;
mysql> set global rpl_semi_sync_slave_enabled = 1;
mysql> stop slave;
mysql> start slave;
mysql> show variables like ‘%semi%’;
+———————————+——-+
| Variable_name                   | Value |
+———————————+——-+
| rpl_semi_sync_slave_enabled     | ON    |
| rpl_semi_sync_slave_trace_level | 32    |
+———————————+——-+

检查半同步是否生效:
Master:
mysql> show global status like ‘rpl_semi%’;
+——————————————–+——-+
| Variable_name                              | Value |
+——————————————–+——-+
| Rpl_semi_sync_master_clients               | 1     |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 0     |
| Rpl_semi_sync_master_no_times              | 0     |
| Rpl_semi_sync_master_no_tx                 | 0     |
| Rpl_semi_sync_master_status                | ON    |
| Rpl_semi_sync_master_timefunc_failures     | 0     |
| Rpl_semi_sync_master_tx_avg_wait_time      | 0     |
| Rpl_semi_sync_master_tx_wait_time          | 0     |
| Rpl_semi_sync_master_tx_waits              | 0     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 0     |
+——————————————–+——-+
说明半同步成功。

让半同步功能在MySQL每次启动都自动生效,在Master和Slave的my.cnf中编辑:
Master:
[mysqld]
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000     #1秒

Slave:
[mysqld]
rpl_semi_sync_slave_enabled=1

也可通过设置全局变量的方式来设置是否启动半同步插件:
Master:
mysql> set global rpl_semi_sync_master_enabled=1
取消加载插件
mysql> uninstall plugin rpl_semi_sync_master;

Slave:
mysql> set global rpl_semi_sync_slave_enabled = 1;
mysql> uninstall plugin rpl_semi_sync_slave;

安装以后可以查看一下安装了那些文件:

**

三、主主复制架构 1、在两台服务器上各自建立一个具有复制权限的用户; Master:*
mysql>grant replication client,replication slave on \
.* to
repl@172.16.4.12 identified by ‘135246’;
mysql>flush privileges;

Slave:
mysql>grant replication client,replication slave on *.* to
repl@172.16.4.11 identified by ‘135246’;
mysql>flush privileges;

2、修改配置文件:
Master:
[mysqld]
server-id = 11
log-bin = mysql-bin
auto-increment-increment = 2
auto-increment-offset = 1
relay-log=mysql-relay
relay-log-index=mysql-relay.index

Slave:
[mysqld]
server-id = 12
log-bin = mysql-bin
auto-increment-increment = 2
auto-increment-offset = 2
relay-log=mysql-relay
relay-log-index=mysql-relay.index

3、如果此时两台服务器均为新建立,且无其它写入操作,各服务器只需记录当前自己二进制日志文件及事件位置,以之作为另外的服务器复制起始位置即可
Master:
mysql> show master status;
+——————+———-+————–+——————+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+——————+———-+————–+——————+
| mysql-bin.000004 |      360 |              |                  |
+——————+———-+————–+——————+

Slave:
mysql> show master status;
+——————+———-+————–+——————+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+——————+———-+————–+——————+
| mysql-bin.000005 |      107 |              |                  |
+——————+———-+————–+——————+

4、各服务器接下来指定对另一台服务器为自己的主服务器即可:
Master:
mysql>change master to \
master_host=’172.16.4.12′,
master_user=’repl’,
master_password=’135246′,
master_log_file=’mysql-bin.000005′,
master_log_pos=107;

Slave:
mysql>change master to \
master_host=’172.16.4.11′,
master_user=’repl’,
master_password=’135246′,
master_log_file=’mysql-bin.000004′,
master_log_pos=360;

5、启动从服务器线程:
Master:
mysql>start slave;

Slave:
mysql>start slave;

到此主主架构已经成功!

[root@localhost maxiangqian]# rpm -ql keepalived

 

然后配置一下最基本的配置文件:

[root@localhost maxiangqian]# vi /etc/keepalived/keepalived.conf
vrrp_instance VI_20 {
state BACKUP
nopreempt
interface eth0
virtual_router_id 20
priority 100
advert_int 5
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.16.16.20
}
}

 

此配置文件就是最简单的配置虚拟IP的文件了,接下来我们在172.16.16.34上启动keepalived

/etc/init.d/keepalived start

 

查看机器IP:

[root@localhost maxiangqian]# ip addr |grep 172.16
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
inet 172.16.16.34/24 brd 172.16.16.255 scope global eth0
inet 172.16.16.20/32 scope global eth0

 

可以看到,VIP已经添加到了server1上,接下来我们在server2安装启动keepalived,启动,所有步骤都一样,只不过server2的keepalived作为备机,并不会持有VIP。

我们在server1上执行

/etc/init.d/keepalived stop

 

执行以后在ip
addr看,VIP现在已经是server2持有了。所以最最基本的功能是已经完成了,但是离我们双主自动切换还是有很大的差距的,下面我们继续去对keepalived的文件进行改造,直到达到我们满意为止:

下面我们修改配置文件,达到我们需要的目的(下面以server2的kp文件为例,server1的和server2一样,只要替换掉相应IP为34就可以了):

vrrp_script checkmysql {
script "/etc/keepalived/checkmysql.sh"
interval 10 #监控脚本,每十秒运行一次
}

vrrp_instance VI_20 {
state BACKUP #状态只有MASTER和BACKUP两种,并且要大写,MASTER为工作状态,BACKUP是备用状态
nopreempt #非抢占模式
interface eth0
virtual_router_id 20
priority 100 #权重,同一个vrrp_instance的MASTER优先级必须比BACKUP高。我们使用非抢占模式,设置相同即可
advert_int 5 #MASTER 与BACKUP 负载均衡器之间同步检查的时间间隔,单位为秒
authentication {
auth_type PASS #验证authentication。包含验证类型和验证密码。类型主要有PASS、AH 两种,通常使用的类型为PASS
auth_pass 1111
}
track_script { #执行定义的监控脚本
checkmysql
}
virtual_ipaddress {
172.16.16.20/24
}
}

 

看一下checkmysql.sh这个脚本:

#!/bin/sh
#isok=$(sed -n ‘2p’ /etc/keepalived/result.txt)
isok=$(/usr/local/mysql/bin/mysql -uroot -p123456 -e ‘select 1’ |sed -n
‘2p’)
function error_query(){
service keepalived stop
echo “172.16.16.34 mysql down, keepalived 切换” | mail -s
“34MySQL+keepalived通知” ma.xiangqian@sf-express.com
}
echo “$isok”
if [ “$isok” != “1” ]
then
#echo ‘diaoyong error’
error_query
fi

 

现在我们执行以下语句,从新load以下keepalived的配置文件:

/etc/init.d/keepalived reload
server1和server2都要执行重新load一下新的配置文件,下面我们测试一下当server1 MySQL DOWN掉的话会发生什么:
server1:shutdown MySQL
server1和server2:tail -f /var/log/messages

server1信息:

May 15 15:35:34 localhost Keepalived_healthcheckers[22987]: TCP connection to [172.16.16.34]:3306 failed !!!
May 15 15:35:34 localhost Keepalived_healthcheckers[22987]: Removing service [172.16.16.34]:3306 from VS [172.16.16.20]:3306
May 15 15:35:34 localhost Keepalived_healthcheckers[22987]: IPVS : Virtual service [172.16.16.20]:3306 illegal timeout.
May 15 15:35:34 localhost Keepalived_healthcheckers[22987]: Executing [/etc/keepalived/shutdown.sh  #检测到服务down后执行的脚本] for service [172.16.16.34]:3306 in VS [172.16.16.20]:3306
May 15 15:35:34 localhost Keepalived_healthcheckers[22987]: Lost quorum 1-0=1 > 0 for VS [172.16.16.20]:3306
May 15 15:36:04 localhost Keepalived_vrrp[22988]: VRRP_Script(checkmysql) failed
May 15 15:36:06 localhost Keepalived_vrrp[22988]: VRRP_Instance(VI_20) Entering FAULT STATE
May 15 15:36:06 localhost Keepalived_vrrp[22988]: VRRP_Instance(VI_20) removing protocol VIPs.
May 15 15:36:06 localhost Keepalived_vrrp[22988]: VRRP_Instance(VI_20) Now in FAULT state
May 15 15:36:06 localhost Keepalived_healthcheckers[22987]: Netlink reflector reports IP 172.16.16.20 removed

server2信息:

May 15 15:24:58 mxqmongodb2 Keepalived_healthcheckers[3093]: IPVS : Virtual service [172.16.16.20]:3306 illegal timeout.
May 15 15:24:58 mxqmongodb2 Keepalived_healthcheckers[3093]: Using LinkWatch kernel netlink reflector...
May 15 15:24:58 mxqmongodb2 Keepalived_healthcheckers[3093]: Activating healthchecker for service [172.16.16.35]:3306
May 15 15:24:58 mxqmongodb2 Keepalived_vrrp[3094]: VRRP_Script(checkmysql) succeeded
May 15 15:36:04 mxqmongodb2 Keepalived_vrrp[3094]: VRRP_Instance(VI_20) Transition to MASTER STATE
May 15 15:36:09 mxqmongodb2 Keepalived_vrrp[3094]: VRRP_Instance(VI_20) Entering MASTER STATE
May 15 15:36:09 mxqmongodb2 Keepalived_vrrp[3094]: VRRP_Instance(VI_20) setting protocol VIPs.
May 15 15:36:09 mxqmongodb2 Keepalived_vrrp[3094]: VRRP_Instance(VI_20) Sending gratuitous ARPs on eth0 for 172.16.16.20
May 15 15:36:09 mxqmongodb2 Keepalived_healthcheckers[3093]: Netlink reflector reports IP 172.16.16.20 added
May 15 15:36:14 mxqmongodb2 Keepalived_vrrp[3094]: VRRP_Instance(VI_20) Sending gratuitous ARPs on eth0 for 172.16.16.20

我们可以看到虚IP链接已经切换了,我们从客户端两个时间点执行MySQL的操作也可以很明显看到切换:

mysql> select @@server_id;
+-------------+
| @@server_id |
+-------------+
| 343306 |
+-------------+
1 row in set

mysql> select @@server_id;
+-------------+
| @@server_id |
+-------------+
| 353306 |
+-------------+
1 row in set

中间VIP的切换是不会影响到客户端的操作的,但是在切换过程是有那么一段时间是不能访问的。

  

keepalived原理参考:

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图