redis +keepalived 主从高可用


主机 master 192.168.2.47
主机 slave 192.168.2.48

一,redis 的安装配置 (1-6 主从主机都需要操作的,步骤7是slave 主机配置)

1 编译和安装所需的包:
yum install gcc tcl
2 解压Redis(此处须自行去官网下载Redis安装包,并上传到服务器)
tar -zxvf redis-3.2.8.tar.gz
3 进入Redis所在文件夹
cd redis-3.2.8
4 编译安装Redis

make && make install
5 更改配置文件,vi /etc/redis.conf
5.1 设置redis会后台启动.找到daemonize no 修改为 daemonize yes。
5.2 找到port 6379 修改为对应节点目录的端口号
5.3 找到bind这一行,bind后要修改为 当前机器的IP地址。
5.4 找到 dir 这一行 指定数据文件的存放路径。设置为各个节点下的目录。目录结构类似
为"/usr/local/las/redis-cluster/6379/"
5.5 开启持久化 appendonly yes
5.6 # 指定 AOF 文件名 appendfilename appendonly.aof
5.7 redis 支持三种不同的刷写模式 appendfsync everysec #每秒钟强制写入磁盘一次,在性能和
持久化方面做了很好的折中,是受推荐的方式。
6 采用默认配置文件方式启动Redis
./redis-server /usr/local/las/redis-cluster/6379/redis.conf &

7, slave 主机的 redis.conf 文件最后添加从复制 ,然后再启动redis
slaveof 192.168.2.47 6379

二,keepalived 安装配置

1,安装基础库
yum -y install openssl-devel libnl3-devel ipset-devel iptables-devel libnfnetlink-devel net-snmp-devel

2,源码安装keepalived

  1. tar zxf keepalived-1.3.5.tar.gz
  2. cd keepalived-1.3.5
  3. ./configure --prefix=/usr/local/keepalived/
  4. make
  5. make install 拷贝需要的文件: cp/usr/local/src/keepalived−1.3.5/keepalived/etc/init.d/keepalived/etc/init.d/keepalived cp /usr/local/keepalived/sbin/keepalived /usr/sbin/
    cp/usr/local/keepalived/etc/sysconfig/keepalived/etc/sysconfig/ mkdir -p /etc/keepalived/
    $ cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf
    /etc/keepalived/keepalived.conf是默认的配置文件

三,主从公共脚本 和keepalived 配置

3.2.1 Redis监控脚本
该脚本检测redis的运行状态,并在nginx进程不存在时尝试重新启动ngnix,如果启动失败则停止keepalived,准备让其它机器接管。
/etc/keepalived/scripts/check_redis.sh:

 
    #!/bin/bash
    CHECK=`/usr/local/bin/redis-cli PING`
    if [ "$CHECK" == "PONG" ] ;then
          echo $CHECK
          exit 0
    else
          echo $CHECK
          service keepalived stop #可确保让出MASTER
          exit 1
    fi

keepalived根据监控脚本的返回码调整优先级:
☉如果脚本返回码为0,并且weight配置的值大于0,则优先级相应的增加;
☉如果脚本返回码为非0,并且weight配置的值小于0,则优先级相应的减少;
☉其他情况,原本配置的优先级不变,即配置文件中priority对应的值。
提示:
优先级不会不断的提高或者降低;
可以编写多个检测脚本并为每个检测脚本设置不同的weight(在配置中列出就行);
不管提高优先级还是降低优先级,最终优先级的范围是在[1,254],不会出现优先级小于等于0或者优先级大于等于255的情况;
在MASTER节点的 vrrp_instance 中 配置 nopreempt ,当它异常恢复后,即使它 prio 更高也不会抢占,这样可以避免正常情况下做无谓的切换。
以上可以做到利用脚本检测业务进程的状态,并动态调整优先级从而实现主备切换。
3.2.2 redis_fault.sh
vim /etc/keepalived/scripts/redis_fault.sh

 
    # !/bin/bash
    LOGFILE=/usr/local/src/redis-2.8.19/keepalived-redis-state.log
    echo "[fault]" >> $LOGFILE
    date >> $LOGFILE
    3.2.3 redis_stop.sh
    # !/bin/bash
    LOGFILE=/usr/local/src/redis-2.8.19/keepalived-redis-state.log
    echo "[stop]" >> $LOGFILE
    date >> $LOGFILE

vim /etc/keepalived/scripts/redis_stop.sh

 
    # !/bin/bash
    LOGFILE=/usr/local/src/redis-2.8.19/keepalived-redis-state.log
    echo "[stop]" >> $LOGFILE
    date >> $LOGFILE

3.3 keepalived scripts for redis
为redis配置keepalived所需要的脚本。
3.3.1 Redis Master scripts
在redis master配置:
vim/etc/keepalived/scripts/redis_master.sh

 
    #!/bin/bash
    REDISCLI="/usr/local/bin/redis-cli"
    LOGFILE="/usr/local/src/redis-2.8.19/keepalived-redis-state.log"
    echo "[master]" >> $LOGFILE
    date >> $LOGFILE
    echo "Being master...." >> $LOGFILE 2>&1
    echo "Run SLAVEOF cmd ..." >> $LOGFILE
    $REDISCLI SLAVEOF 192.168.2.48 6379 >> $LOGFILE 2>&1
    sleep 10 #延迟10秒以后待数据同步完成后再取消同步状态
    echo "Run SLAVEOF NO ONE cmd ..." >> $LOGFILE
    $REDISCLI SLAVEOF NO ONE >> $LOGFILE 2>&1

vim /etc/keepalived/scripts/redis_backup.sh

 
    #!/bin/bash
    REDISCLI="/usr/local/bin/redis-cli"
    LOGFILE="/usr/local/src/redis-2.8.19/keepalived-redis-state.log"
    echo "[backup]" >> $LOGFILE
    date >> $LOGFILE
    echo "Being slave...." >> $LOGFILE 2>&1
    sleep 15 #延迟15秒待数据被对方同步完成之后再切换主从角色
    echo "Run SLAVEOF cmd ..." >> $LOGFILE
    $REDISCLI SLAVEOF 192.168.2.48 6379 >> $LOGFILE 2>&1

3.3.2 Redis Backup scripts
和3.3.1节的配置基本一样,只是脚本中redis的IP为原master主机的IP。
在redis backup配置:
vim/etc/keepalived/scripts/redis_master.sh

 
    #!/bin/bash
    REDISCLI="/usr/local/bin/redis-cli"
    LOGFILE="/usr/local/src/redis-2.8.19/keepalived-redis-state.log"
    echo "[master]" >> $LOGFILE
    date >> $LOGFILE
    echo "Being master...." >> $LOGFILE 2>&1
    echo "Run SLAVEOF cmd ..." >> $LOGFILE
    $REDISCLI SLAVEOF 192.168.2.47 6379 >> $LOGFILE 2>&1
    sleep 10 #延迟10秒以后待数据同步完成后再取消同步状态
    echo "Run SLAVEOF NO ONE cmd ..." >> $LOGFILE
    $REDISCLI SLAVEOF NO ONE >> $LOGFILE 2>&1

vim /etc/keepalived/scripts/redis_backup.sh

 
    #!/bin/bash
    REDISCLI="/usr/local/bin/redis-cli"
    LOGFILE="/usr/local/src/redis-2.8.19/keepalived-redis-state.log"
    echo "[backup]" >> $LOGFILE
    date >> $LOGFILE
    echo "Being slave...." >> $LOGFILE 2>&1
    sleep 15 #延迟15秒待数据被对方同步完成之后再切换主从角色
    echo "Run SLAVEOF cmd ..." >> $LOGFILE
    $REDISCLI SLAVEOF 192.168.2.47 6379 >> $LOGFILE 2>&1

3.4 配置keepalived.conf
keepalived.conf样例

 
    global_defs {
        router_id redis
    }
    vrrp_script chk_redis {
        script "/etc/keepalived/scripts/check_redis.sh"
        interval 4
        weight -5
        fall 3
        rise 2
    }
    vrrp_instance VI_REDIS {
        state MASTER
        interface eth1
        virtual_router_id 51
        priority 100
        advert_int 1
        nopreempt
        authentication {
            auth_type PASS
            auth_pass 1111
        }
        virtual_ipaddress {
            192.168.2.49
        }
        track_script {
            chk_redis
        }
        notify_master /etc/keepalived/scripts/redis_master.sh
        notify_backup /etc/keepalived/scripts/redis_backup.sh
        notify_fault /etc/keepalived/scripts/redis_fault.sh
        notify_stop /etc/keepalived/scripts/redsi_stop.sh
    }

注意,在同一个网段内的,若为不同的应用做高可用,不同应用使用不同的VIP,那么vrrp_instance的名字(这里是VI_REDIS)、virtual_router_id在不同的高可用实例必须设置不同的值区分开。否则keepalived会报如下错误:
Aug 11 11:28:36 localhostKeepalived_vrrp[16958]: (VI_1): received an invalid ip number count 1, expected2!
Aug 11 11:28:36 localhostKeepalived_vrrp[16958]: bogus VRRP packet received on eth1 !!!
Aug 11 11:28:36 localhostKeepalived_vrrp[16958]: VRRP_Instance(VI_1) Dropping received VRRP packet...
以上是keepalived MASTER节点配置文件/etc/keepalived/keepalived.conf的配置信息。在BACKUP节点,只需把vrrp_instance->state改为BACKUP,vrrp_instance->priority改为99即可。
在默认的keepalive.conf里面还有 virtual_server,real_server 这样的配置,我们这用不到,它是为lvs准备的。 notify 可以定义在切换成MASTER或BACKUP时执行的脚本,如有需求请自行google。
配置选项说明
global_defs
☉notification_email: keepalived在发生诸如切换操作时需要发送email通知地址,后面的 smtp_server 相比也都知道是邮件服务器地址。也可以通过其它方式报警,毕竟邮件不是实时通知的。
☉router_id: 机器标识,通常可设为hostname。故障发生时,邮件通知会用到
vrrp_instance
☉state : 指定instance(Initial)的初始状态,就是说在配置好后,这台服务器的初始状态就是这里指定的,但这里指定的不算,还是得要通过竞选通过优先级来确定。如果这里设置为MASTER,但如若他的优先级不及另外一台,那么这台在发送通告时,会发送自己的优先级,另外一台发现优先级不如自己的高,那么他会就回抢占为MASTER
☉interface: 实例绑定的网卡,因为在配置虚拟IP的时候必须是在已有的网卡上添加的,可以用ifconfig命令查看网卡。
☉mcast_src_ip: 发送多播数据包时的源IP地址,这里注意了,这里实际上就是在那个地址上发送VRRP通告,这个非常重要,一定要选择稳定的网卡端口来发送,这里相当于heartbeat的心跳端口,如果没有设置那么就用默认的绑定的网卡的IP,也就是interface指定的IP地址
☉virtual_router_id: 这里设置VRID,这里非常重要,相同的VRID为一个组,他将决定多播的MAC地址
☉priority: 设置本节点的优先级,优先级高的为master
☉advert_int: 检查间隔,默认为1秒。这就是VRRP的定时器,MASTER每隔这样一个时间间隔,就会发送一个advertisement报文以通知组内其他路由器自己工作正常
☉authentication: 定义认证方式和密码,主从必须一样,样例用的是密码方式。
☉virtual_ipaddress: 这里设置的就是VIP,也就是虚拟IP地址,他随着state的变化而增加删除,当state为master的时候就添加,当state为backup的时候删除,这里主要是有优先级来决定的,和state设置的值没有多大关系。这里可以设置多个虚拟IP地址,类似于一个域名可以解析对应多个IP地址。
☉track_script: 引用VRRP脚本,即在 vrrp_script 部分指定的名字。每隔vrrp_script->interval时间运行脚本,如果监控服务有异常则改变优先级,并最终引发主备切换。
vrrp_script
告诉 keepalived 在什么情况下切换,所以尤为重要。可以有多个 vrrp_script
☉script : 自己写的检测脚本。也可以是一行命令如killall-0 nginx
☉interval4 : 每4s检测一次,这里要大于监控脚本执行的时间,监控脚本会执行超时,☉keepalived会发送SIGTERM信号结束监控脚本的执行。
☉weight-5 : 检测失败(脚本返回非0)则优先级 -5
☉fall 2: 检测连续 2 次失败才算确定是真失败。会用weight减少优先级(1-255之间)
☉rise 1: 检测 1 次成功就算成功。但不修改优先级
4.1启动keepalived
在Redis Master和Redis Backup上将keepalived启动
启动keepalived:
service keepalived start
或者
/etc/init.d/keepalived start
或者
/usr/local/keepalived/sbin/keepalived -f/etc/keepalived/keepalived.conf -D
查看进程,正常会有三个进程
[root@localhost ~]# ps -ef | grepkeepalived
root 3870 1 0 14:46 ? 00:00:00 keepalived -D
root 3872 3870 0 14:46 ? 00:00:00 keepalived -D
root 3873 3870 0 14:46 ? 00:00:00 keepalived -D
root 3887 18774 0 14:46 pts/1 00:00:00 grep keepalived
[root@localhost ~]#
用ip命令查看VIP,ifconfig命令不能查看虚拟IP。
[root@localhost ~]# ip a | grep eth1
2: eth1: mtu 1500 qdisc pfifo_fast state UP qlen1000
inet 192.168.2.47/24 brd 172.30.1.255scope global eth1
inet 192.168.2.49/32 scope global eth1
[root@localhost ~]#
可以看到现在是192.168.2.47接管着VIP。
至此,Keppalived+Redis主从高可用环境已经搭建完成。客户端访问Redis使用VIP,或者将redis的域名解析指向VIP。
4 测试
测试时可以用命令tail -f /var/log/messages查看keepalived的日志,查看主从机器状态的变化,VIP的漂移等。
4.1 客户端用VIP访问Redis
在另一台客户端机器,比如192.168.2.44,用VIP登录redis,并使用get命令获取之前设置的[key,value].
[root@localhost redis-2.8.19]# redis-cli -h 192.168.2.49 -p 6379
192.168.2.49:6379> get nosql
"redis"
192.168.2.49:6379>
再设置一个新的[key,value].
192.168.2.49:6379> set movie ZhanLang2
OK
192.168.2.49:6379> get movie
"ZhanLang2"
192.168.2.49:6379>
测试结果正常。
4.2 测试VIP漂移
测试之前,先看下那台机器接管这VIP
在192.168.2.47机器查看
[root@localhost ~]# ip a | grep eth1
2: eth1: mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 192.168.2.47/24 brd 172.30.1.255 scope global eth1
inet 192.168.2.49/32 scope global eth1
[root@localhost ~]#
在192.168.2.48查看
[root@localhost ~]# ip a | grep eth1
2: eth1: mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 192.168.2.48/24 brd 172.30.1.255 scope global eth1
[root@localhost ~]#
可见,VIP被192.168.2.47机器接管着。
现在,把192.168.2.47机器上的redis-server干掉,再查看VIP是否还接管着:
[root@localhost ~]# pkill redis-server
[root@localhost ~]# ps -ef | grep redis-server | grep -v grep
root 7372 30964 0 13:57 pts/0 00:00:00 grep redis-server
[root@localhost ~]# ip a | grep eth1
2: eth1: mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 192.168.2.47/24 brd 172.30.1.255 scope global eth1
[root@localhost ~]#
可见,192.168.2.47已经没有接管VIP了。
在192.168.2.48查看下是否接管了VIP:
[root@localhost ~]# ip a | grep eth1
2: eth1: mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 192.168.2.48/24 brd 172.30.1.255 scope global eth1
inet 192.168.2.49/32 scope global eth1
[root@localhost ~]#
可见192.168.2.48已经接管了VIP,进入MASTER状态了。
继续测试在VIP下的redis读写:
还是在客户端192.168.2.44下执行
192.168.2.49:6379> get movie
"ZhanLang2"
192.168.2.49:6379> set director WuJing
OK
192.168.2.49:6379>
测试正常,注意,刚刚设置了一个新的[key,value],待会把192.168.2.47上的redis-server起来后,再查询这个新的[key,value]——[director,WuJing].
现在把192.168.2.47上的redis-server启动,keepalived也需要启动,以为检测脚本check_redis.sh检测到redis-server不在时,把keepalived也退出了,确保MASTER角色的让出。
[root@localhost redis-2.8.19]# cd /usr/local/src/redis-2.8.19
[root@localhost redis-2.8.19]# ./src/redis-server redis.conf
[root@localhost redis-2.8.19]# ps -ef | grep redis-server | grep -v grep
root 7841 1 0 14:25 ? 00:00:00 ./src/redis-server *:6379
[root@localhost redis-2.8.19]# service keepalived start
Starting keepalived: [ OK ]
[root@localhost redis-2.8.19]# ip a | grep eth1
2: eth1: mtu 1500 qdisc pfifo_fast state UP qlen 1000
inet 192.168.2.47/24 brd 172.30.1.255 scope global eth1
inet 192.168.2.49/32 scope global eth1
[root@localhost redis-2.8.19]#

可见,启动redis-server和keepalived后,192.168.2.47又重新接管了VIP,因为192.168.2.47设置的优先级是100比192.168.2.48的优先级99要高。
在客户端192.168.2.44下继续测试redis的读写
先查询刚刚设置的[director,WuJing]
192.168.2.49:6379> get director
"WuJing"
192.168.2.49:6379>
可以查询到,说明数据已经同步过来了
再测试下写数据
192.168.2.49:6379> set piaofang 4billion
OK
192.168.2.49:6379>
可见,写redis也是正常的。

猜你喜欢

转载自blog.csdn.net/saga_gallon/article/details/80943824