redis+keepalived实现高可用
Posted 飞雪流星的博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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相关文件
[[email protected] keepalived-1.2.15]# cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/keepalived
[[email protected] keepalived-1.2.15]#cp /usr/local/keepalived/sbin/keepalived /usr/sbin/keepalived
[[email protected] keepalived-1.2.15]# cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/keepalived
[[email protected] keepalived-1.2.15]# mkdir /etc/keepalived
[[email protected]]#cp /usr/local/keepalived/etc/keepalived/samples/keepalived.conf.virtualhost /etc/keepalived/keepalived.conf
[[email protected] keepalived-1.2.15]#
2、设置开机自启动
chkconfig –add keepalived
chkconfig keepalived on
chkconfig –list keepalived
三、 通过Keepalived实现Redis Failover自动故障切换
1、修改Master和Slave的/etc/hosts文件
[[email protected] rc.d]#cat /etc/hosts (Master)
192.168.1.151 redis01
192.168.1.152 redis02
[[email protected] rc.d]#cat /etc/sysconfig/network
NETWORKING=yes
HOSTNAME=redis01
[[email protected] rc.d]#cat /etc/hosts (slaves)
192.168.1.151 redis01
192.168.1.152 redis02
[[email protected] linux]# cat /etc/sysconfig/network
NETWORKING=yes
HOSTNAME=redis02
修改完主机名重启机器生效
2、默认安装完成keepalived之后是没有配置文件的,因此我们需要手动创建:
首先,在Master上创建如下配置文件:
[[email protected] linux]# vim /etc/keepalived/keepalived.conf
global_defs {
notification_email {
test@163.com
}
notification_email_from [email protected]
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上创建如下配置文件:
[[email protected] linux]# vim /etc/keepalived/keepalived.conf
global_defs {
notification_email {
test@163.com
}
notification_email_from [email protected]
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
[[email protected] bin]# service redis start
2.启动Slave上的Redis
[[email protected] bin]# service redis start
3.启动Master上的Keepalived
service keepalived start
4.启动Slave上的Keepalived
service keepalived start
5.尝试通过VIP连接Redis:
[[email protected] bin]#pwd
/opt/redis-3.0.6/src
[[email protected] bin]# ./redis-cli -h 192.168.100.150 info
role:master
slave0:192.168.100.152,6379,online
连接成功,Slave也连接上来了
6.尝试插入一些数据:
[[email protected] bin]# ./redis-cli -h 192.168.100.150 SET Hello Redis
从VIP读取数据
[[email protected] bin]# ./redis-cli -h 192.168.100.150 GET Hello
"Redis"
从Master读取数据
[[email protected] bin]# ./redis-cli -h 192.168.100.151 GET Hello
"Redis"
从Slave读取数据
[[email protected] bin]# ./redis-cli -h 192.168.100.152 GET Hello
"Redis"
下面,模拟故障产生:
将Master上的Redis进程杀死:
[[email protected] bin]# ./redis-cli shutdown
查看Master上的Keepalived日志
[[email protected] scripts]# tail /var/log/keepalived-redis-state.log
[fault]
Thu Sep 27 08:29:01 CST 2016
同时Slave上的日志显示:
[[email protected] 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是备
自动切换成功!
以上是关于redis+keepalived实现高可用的主要内容,如果未能解决你的问题,请参考以下文章
利用redis-sentinel+keepalived实现redis高可用