redis+keepalived实现高可用

redis+keepalived实现高可用

Redis简介:

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

设计思路:
redis 主和 redis从  正常同步;

redis主keepalived 启动,执行redis_master.sh脚本,vip在自己身上;

redis 从keepalived 启动,执行redis_slave.sh脚本;

redis主服务关闭,则redis主执行redis_fault.sh脚本,vip落在redis 从上,redis从执行redis_master.sh脚本,变成主;

redis主服务开启,则redis主执行redis_slave.sh脚本变成从,vip还在redis 从上,还是主;

redis从服务关闭,则redis从执行redis_fault.sh脚本,vip落在redis主上,redis主执行redis_master.sh脚本,变成主;

redis从服务开启,则redis从执行redis_slave.sh脚本变成从,vip还在redis主上,redis主继续做主,此时为redis初试主从状态;

 

通过keepalived的自定义脚本功能监控本机的redis服务状态,当监控脚本检测到redis服务出现异常时,则改变本机keepalived的优先级,同时这会导致master/backup角色的变化,而keepalived在角色变化时也会触发一些机制执行相关脚本,这就为我们改变redis的master/slave状态提供了机会,这样做的目的是为了是redis的master/slave直接的数据保持一致。

在keepalived+redis的使用过程中有四种情况:

 1 一种是keepalived挂了,同时redis也挂了,这样的话直接VIP飘走之后,是不需要进行redis数据同步的,因为redis挂了,你也无法去master上同步,不过会损失已经写在master上却还没同步到slave上面的这部分数据。

 2 另一种是keepalived挂了,redis没挂,这时候VIP飘走后,redis的master/slave还是老的对应关系,如果不变化的话会把数据写入redis slave中,从而不会同步到master上去,这就要借助监控脚本反转redis的master/slave关系。这时候就要预留一点时间进行数据同步,然后反转master/slave。

 3 还有一种是keepalived没挂,redis挂了,这时候根据监控脚本会检测到redis挂了,并且降低keepalived master的优先级,同样会导致VIP飘走,情况和第二种一样,也是需要进行数据同步,然后反转当前redis的master/slave关系的。

 4 随后一种是keepalived没挂,redis也没挂,大吉大利啊,什么都不用操作。

搭建环境:

1、 操作系统

Oracle Linux Server release 6.6

2、 Keepalived

keepalived-1.2.15

3、 Redis

redis-3.0.6

4、 IP规划

192.168.100.151  redis01

192.168.100.152  redis02

192.168.100.150  VIP

一、    安装redis(master和slaves安装步骤相同,只是配置稍有不同)

1、安装步骤:

cd /opt

tar –zxvf redis-3.0.6.tar.gz

cd redis-3.0.6

cd src

make && make install

2、修改配置:

# vi /opt/redis-3.0.6/redis.conf (master)

把daemonize no 修改为daemonize yes

目的是可以在后台执行redis-server

# vi /opt/redis-3.0.6/redis.conf  (slaves)

把daemonize no 修改为daemonize yes

增加:

slaveof 192.168.100.151 6379

3、设置开机启动

#vi /etc/rc.d/init.d/redis

#!/bin/sh 

#chkconfig: 345 86 14 

#description: Startup and shutdown script for Redis 

PROGDIR=/opt/redis-3.0.6/src #安装路径 

PROGNAME=redis-server 

DAEMON=$PROGDIR/$PROGNAME 

CONFIG=/opt/redis-3.0.6/redis.conf 

PIDFILE=/var/run/redis.pid 

DESC="redis daemon" 

SCRIPTNAME=/etc/rc.d/init.d/redis    

start() 

         if test -x $DAEMON 

         then 

        echo -e "Starting $DESC: $PROGNAME" 

                   if $DAEMON $CONFIG 

                   then 

                            echo -e "OK" 

                   else 

                            echo -e "failed" 

                   fi 

         else 

                   echo -e "Couldn't find Redis Server ($DAEMON)" 

         fi 

stop() 

         if test -e $PIDFILE 

         then 

                   echo -e "Stopping $DESC: $PROGNAME" 

                   if kill `cat $PIDFILE` 

                   then 

                            echo -e "OK" 

                   else 

                            echo -e "failed" 

                   fi 

         else 

                   echo -e "No Redis Server ($DAEMON) running" 

         fi 

}     

restart() 

    echo -e "Restarting $DESC: $PROGNAME" 

    stop 

         start 

}     

list() 

         ps aux | grep $PROGNAME 

}   

case $1 in 

         start) 

                   start 

        ;; 

         stop) 

        stop 

        ;; 

         restart) 

        restart 

        ;; 

         list) 

        list 

        ;; 

  

         *) 

        echo "Usage: $SCRIPTNAME {start|stop|restart|list}" >&2 

        exit 1 

        ;; 

esac 

exit 0

#chmod 744 /etc/rc.d/init.d/redis

#chkconfig --add redis  

#chkconfig --level 345 redis on  

#chkconfig --list redis 

4、redis主从测试

#主服务器

redis-cli -p 6379 set hello world

#从服务器

redis-cli -p 6379 get hello

“world”

#主服务器

redis-cli -p 6379 set hello2 world2

#从服务器

redis-cli -p 6379 get hello2

“world2”

redis-cli -p 6379 set hello world

(error) READONLY You can’t write against a read only slave.

成功配置主从redis服务器,由于配置中有一条从服务器是只读的,所以从服务器没法设置数据,只可以读取数据。

二、    安装keepalived

1、安装keepalived步骤

cd /opt

tar –zxvf keepalived-1.2.15.tar.gz

cd keepalived-1.2.15

ln -s /usr/src/kernels/3.8.13-44.1.1.el6uek.x86_64 /usr/src/linux

3.8.13-44.1.1.el6uek.x86_64可以由uname –a 查询得到

./configure --prefix=/usr/local/keepalived --with-kernel-dir=/usr/src/linux -enable-sha1

出现报错:

解决:

yum install openssl-devel

重新执行

./configure --prefix=/usr/local/keepalived --with-kernel-dir=/usr/src/linux -enable-sha1

make && make install

复制keepalived相关文件

[root@redis01 keepalived-1.2.15]# cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/keepalived

[root@redis01 keepalived-1.2.15]#cp /usr/local/keepalived/sbin/keepalived /usr/sbin/keepalived

[root@redis01 keepalived-1.2.15]# cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/keepalived

[root@redis01 keepalived-1.2.15]# mkdir /etc/keepalived

[root@redis01keepalived-1.2.15]#cp /usr/local/keepalived/etc/keepalived/samples/keepalived.conf.virtualhost /etc/keepalived/keepalived.conf

[root@redis01 keepalived-1.2.15]#

2、设置开机自启动

chkconfig –add keepalived

chkconfig keepalived on

chkconfig –list keepalived

三、    通过Keepalived实现Redis Failover自动故障切换

1、修改Master和Slave的/etc/hosts文件

[root@redis rc.d]#cat /etc/hosts   (Master)

192.168.1.151 redis01

192.168.1.152 redis02

[root@redis rc.d]#cat /etc/sysconfig/network

NETWORKING=yes

HOSTNAME=redis01

[root@redis rc.d]#cat /etc/hosts   (slaves)

192.168.1.151 redis01

192.168.1.152 redis02

[root@redis-slave linux]# cat /etc/sysconfig/network

NETWORKING=yes

HOSTNAME=redis02

修改完主机名重启机器生效

2、默认安装完成keepalived之后是没有配置文件的,因此我们需要手动创建:

首先,在Master上创建如下配置文件:

[root@redis  linux]# vim /etc/keepalived/keepalived.conf

global_defs {

   notification_email {

     test@163.com

   }

   notification_email_from keepalived@redis01

   router_id redis01

}

vrrp_script chk_redis {

    script "/etc/keepalived/scripts/redis_check.sh"

    interval 1

}

vrrp_instance mes_Redis {

    state MASTER

    interface eth0

    garp_master_delay 10

    smtp_alert

    virtual_router_id 3

    priority 100

    nopreempt

    advert_int 1

    authentication {

        auth_type PASS

        auth_pass 1111

    }

    virtual_ipaddress {

        192.168.100.150

    }

    track_script {

        chk_redis

    }

    notify_master /etc/keepalived/scripts/redis_master.sh

    notify_backup /etc/keepalived/scripts/redis_slave.sh

    notify_fault  /etc/keepalived/scripts/redis_fault.sh

    notify_stop   /etc/keepalived/scripts/redis_stop.sh

}

然后,在Slave上创建如下配置文件:

[root@redis-slave linux]# vim /etc/keepalived/keepalived.conf

global_defs {

   notification_email {

     test@163.com

   }

   notification_email_from keepalived@redis02

   router_id redis02

}

vrrp_script chk_redis {

    script "/etc/keepalived/scripts/redis_check.sh"

    interval 1

}

vrrp_instance mes_Redis {

    state BACKUP

    interface eth0

    garp_master_delay 10

    smtp_alert

    virtual_router_id 3

    priority 90

    nopreempt

    advert_int 1

    authentication {

        auth_type PASS

        auth_pass 1111

    }

    virtual_ipaddress {

        192.168.100.150

    }

    track_script {

        chk_redis

    }

    notify_master /etc/keepalived/scripts/redis_master.sh

    notify_backup /etc/keepalived/scripts/redis_slave.sh

    notify_fault  /etc/keepalived/scripts/redis_fault.sh

    notify_stop   /etc/keepalived/scripts/redis_stop.sh

}

注:修改M,B服务器的  state BACKUP 都为【备】类型,同时设置 nopreempt  设置为不抢夺VIP,然后先启动M服务器,M服务器会成为【主】,然后启动B服务器,由于M的优先级高【priority 100】 所以B不会抢夺VIP,这时M宕机,B成为【主】,接着M恢复正常,由于设置了nopreempt 所以M不会抢夺VIP,B继续为【主】而M为【备】。想要M宕机恢复后继续为【主】,注释nopreempt即可。

3、在Master和Slave上创建监控Redis的脚本

mkdir /etc/keepalived/scripts

vim /etc/keepalived/scripts/redis_check.sh

#!/bin/bash

ALIVE=`/opt/redis-3.0.6/src/redis-cli PING`

if [ "$ALIVE" == "PONG" ]; then

  echo $ALIVE

  exit 0

else

  echo $ALIVE

  exit 1

fi

4、编写以下负责运作的关键脚本:

 notify_master /etc/keepalived/scripts/redis_master.sh

 notify_backup /etc/keepalived/scripts/redis_slave.sh

 notify_fault /etc/keepalived/scripts/redis_fault.sh

 notify_stop /etc/keepalived/scripts/redis_stop.sh 

因为Keepalived在转换状态时会依照状态来呼叫:

 当进入Master状态时会呼叫notify_master

 当进入Backup状态时会呼叫notify_backup

 当发现异常情况时进入Fault状态呼叫notify_fault

 当Keepalived程序终止时则呼叫notify_stop

首先,在Redis Master上创建notity_master与notify_backup脚本:

vim /etc/keepalived/scripts/redis_master.sh

#!/bin/bash

REDISCLI="/opt/redis-3.0.6/src/redis-cli"

LOGFILE="/var/log/keepalived-redis-state.log"

echo "[master]" >> $LOGFILE

date >> $LOGFILE

echo "Being master...." >> $LOGFILE 2>&1

echo "Run SLAVEOF cmd ..." >> $LOGFILE

$REDISCLI SLAVEOF 192.168.100.152 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_slave.sh

#!/bin/bash

REDISCLI="/opt/redis-3.0.6/src/redis-cli"

LOGFILE="/var/log/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.100.152 6379 >> $LOGFILE  2>&1

 

接着,在Redis Slave上创建notity_master与notify_backup脚本:

vim /etc/keepalived/scripts/redis_master.sh

#!/bin/bash

REDISCLI="/opt/redis-3.0.6/src/redis-cli"

LOGFILE="/var/log/keepalived-redis-state.log"

echo "[master]" >> $LOGFILE

date >> $LOGFILE

echo "Being master...." >> $LOGFILE 2>&1

echo "Run SLAVEOF cmd ..." >> $LOGFILE

$REDISCLI SLAVEOF 192.168.100.151 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_slave.sh

#!/bin/bash

REDISCLI="/opt/redis-3.0.6/src/redis-cli"

LOGFILE="/var/log/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.10.151 6379 >> $LOGFILE  2>&1

 

然后在Master与Slave创建如下相同的脚本:

vim /etc/keepalived/scripts/redis_fault.sh

#!/bin/bash

LOGFILE=/var/log/keepalived-redis-state.log

echo "[fault]" >> $LOGFILE

date >> $LOGFILE

 

vim /etc/keepalived/scripts/redis_stop.sh

#!/bin/bash

LOGFILE=/var/log/keepalived-redis-state.log

echo "[stop]" >> $LOGFILE

date >> $LOGFILE

 

在Master与Slave给脚本都加上可执行权限:

chmod +x /etc/keepalived/scripts/*.sh

四、    脚本创建完成以后,我们开始按照如下流程进行测试:

 1.启动Master上的Redis

[root@redis bin]# service redis start

2.启动Slave上的Redis

[root@redis bin]# service redis start

3.启动Master上的Keepalived

service keepalived start

4.启动Slave上的Keepalived

service keepalived start 

5.尝试通过VIP连接Redis:

[root@redis bin]#pwd

/opt/redis-3.0.6/src

[root@redis bin]# ./redis-cli -h 192.168.100.150 info

role:master

slave0:192.168.100.152,6379,online

连接成功,Slave也连接上来了

6.尝试插入一些数据:

[root@redis bin]# ./redis-cli -h 192.168.100.150 SET Hello Redis 

从VIP读取数据

[root@redis bin]# ./redis-cli -h 192.168.100.150 GET Hello

"Redis"

从Master读取数据

[root@redis bin]# ./redis-cli -h 192.168.100.151  GET Hello

"Redis"

从Slave读取数据

[root@redis-slave bin]# ./redis-cli -h 192.168.100.152  GET Hello

"Redis"

下面,模拟故障产生:

将Master上的Redis进程杀死:

[root@redis bin]# ./redis-cli shutdown

查看Master上的Keepalived日志

[root@redis01 scripts]# tail /var/log/keepalived-redis-state.log

[fault]

Thu Sep 27 08:29:01 CST 2016

同时Slave上的日志显示:

[root@redis02 scripts]# tail /var/log/keepalived-redis-state.log

[master]

Thu Nov 15 12:06:04 CST 2016

Being master....

Run SLAVEOF cmd ...

OK

Run SLAVEOF NO ONE cmd ...

OK

然后我们可以发现,Slave已经接管服务,并且担任Master的角色了。

./redis-cli -h 192.168.100.150 info

./redis-cli -h 192.168.100.152 info

 role:master

然后我们恢复Master的Redis进程

主变成slave

然后把152redis停掉

151恢复主的角色,在把152redis开启

恢复151是主,152是备

自动切换成功!

原文地址:https://www.cnblogs.com/chenjunjie/p/6187983.html