利用keepalive搭建高可用redis主从解决方案
Posted 祥云驿站之IT拾趣
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用keepalive搭建高可用redis主从解决方案相关的知识,希望对你有一定的参考价值。
目前比较主流的redis高可用方案有三种:redis cluster、codis、keepalive+redis主从
redis cluster,是在redis 3.0之后官方推出的一种基于sharding的解决方案,好处是易管理
codis是一种第三方(阿里)的解决方案,个人觉得codis在复杂web环境中是比较合理的,尤其是扩展性很好,但配置稍微复杂了一点。Twemproxy就不说了,感觉codis已经完胜它了!
keepalived是一种主、备的解决方案,好处是配置简单,如果您的系统对web的要求不是特别高,keepalived也是一种比较好的解决方案
下来我们就利用keepalived来搭建一套redis环境吧
1、环境介绍
redis01:192.168.150.129,安装redis、keepalived
redis02:192.168.150.130,安装redis、keepalived
VIP:192.168.150.131
首先两台redis实现:主、从的环境,keepalived提供VIP,作为统一访问入口
keepalived需要完成redis主从切换逻辑,包括:
A、正常情况下,redis主节点负责服务,Slave不参与业务(或者可以做为查询),redis主从自动同步数据
B、redis主节点异常down掉后,从节点接管服务,注意这时候主从同步是也必须停掉的
C、主节点恢复后,先利用主从(需要重新配置主从)从同步最新数据到主节点
2、环境安装
redis的安装见之前我发的《redis在redhat7下的安装》,安装完成后加入systemctl控制
[root@redis02 ~]# systemctl status redis
● redis.service - "Redis 3.2.8 (00000000/0) 64 bit" #描述信息
Loaded: loaded (/usr/lib/systemd/system/redis.service; disabled; vendor preset: disabled)
Active: active (running) since Mon 2017-04-24 21:42:29 CST; 5s ago
Main PID: 2901 (redis-server)
CGroup: /system.slice/redis.service
└─2901 /usr/local/bin/redis-server 127.0.0.1:6379
...
[root@redis02 ~]#
[root@redis01 ~]# systemctl status redis
● redis.service - "Redis 3.2.8 (00000000/0) 64 bit" #描述信息
Loaded: loaded (/usr/lib/systemd/system/redis.service; disabled; vendor preset: disabled)
Active: active (running) since Mon 2017-04-24 21:43:13 CST; 1s ago
Main PID: 2307 (redis-server)
CGroup: /system.slice/redis.service
└─2307 /usr/local/bin/redis-server 127.0.0.1:6379
...
[root@redis01 ~]
keepalived在系统安装光盘中已经有了,我们直接yum install 即可(记得两台机器都要安装)
[root@redis01 ~]# yum install keepalived
...
Installed:
keepalived.x86_64 0:1.2.13-7.el7
Dependency Installed:
net-snmp-agent-libs.x86_64 1:5.7.2-24.el7
Complete!
[root@redis01 ~]# systemctl enable keepalived
Created symlink from /etc/systemd/system/multi-user.target.wants/keepalived.service to /usr/lib/systemd/system/keepalived.service.
3、redis参数调整
在本示例中我修改了redis的如下参数(两台主机)
appendonly yes --开启AOF模式
appendfilename "appendonly.aof" --保存数据的AOF文件名称
appendfsync everysec --fsync模式,每秒钟保存一次
syslog-enabled on --日志输出到系统日志
slave-serve-stale-data no --salve和同步数据过程中,对外提供查询
protected-mode no --关闭本地保护模式
4、keepalived环境搭建
keepalived的配置文件在/etc/keepalive下,接下来主要是这个文件的配置
[root@redis01 ~]# ls /etc/keepalived/
keepalived.conf
[root@redis01 ~]#
A、redis01上的redis主配置文件
[root@redis01 ~]# ls /etc/keepalived/
config.d keepalived.conf
[root@redis01 ~]# cat /etc/keepalived/keepalived.conf |grep -v "#"
! Configuration File for keepalived
global_defs {
router_id LVS_DEV
}
vrrp_script status_check --状态检测的逻辑,每秒钟检查一次,每次2秒无法连接算超时,2次无法连接算节点down
{
script "/etc/keepalived/config.d/redis_check.sh 127.0.0.1 6379"
interval 1
timeout 2
fall 2
}
vrrp_instance VI_1 {
state BACKUP --确保主节点恢复后,HA不主动切回
interface eno16777736 --本地业务网卡
virtual_router_id 51
priority 100 --本节点优先级
nopreempt --确保主节点恢复后,HA不主动切回
advert_int 1 --间隔时间
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.150.131/24 --VIP
}
track_script {
status_check
}
notify_master "/etc/keepalived/config.d/redis_master.sh 192.168.150.129 192.168.150.130 6379"
notify_backup "/etc/keepalived/config.d/redis_backup.sh 192.168.150.129 192.168.150.130 6379"
notify_fault /etc/keepalived/config.d/redis_fault.sh
notify_stop "/etc/keepalived/config.d/redis_stop.sh 192.168.150.129 192.168.150.130 6379"
}
[root@redis01 ~]#
上边有4个脚本
I、notify_master:当切换到master状态时会执行的脚本
[root@redis01 ~]# cat /etc/keepalived/config.d/redis_master.sh
#!/bin/bash
REDISCLI1="/usr/local/bin/redis-cli -h $1 -p $3"
REDISCLI2="/usr/local/bin/redis-cli -h $2 -p $3"
LOGFILE="/var/log/keepalived-redis-state.log"
echo "[master]" >> $LOGFILE
date >> $LOGFILE
REDISCLI=`/usr/local/bin/redis-cli info|grep role|cut -d ":" -f 2`
if [ $REDISCLI == "master" ]
then
echo do nothing here
else
$REDISCLI1 SLAVEOF NO ONE >> $LOGFILE 2>&1
sleep 10
$REDISCLI2 SLAVEOF $1 $3 >> $LOGFILE 2>&1
fi
[root@redis01 ~]#
II、notify_backup:当切换到backup状态时会执行的脚本
[root@redis01 ~]# cat /etc/keepalived/config.d/redis_backup.sh
#!/bin/bash
REDISCLI="/usr/local/bin/redis-cli -h $1 -p $3"
REDISCLI1="/usr/local/bin/redis-cli -h $2 -p $3"
LOGFILE="/var/log/keepalived-redis-state.log"
echo "[backup]" >> $LOGFILE
date >> $LOGFILE
echo "Run SLAVEOF NO ONE cmd ..." >> $LOGFILE
$REDISCLI1 SLAVEOF NO ONE >> $LOGFILE 2>&1
sleep 15 #delay 15 s wait data async cancel sync
echo "Run SLAVEOF cmd ..." >> $LOGFILE
/usr/local/bin/redis-cli -h $1 -p $3 SLAVEOF $2 $3 >> $LOGFILE 2>&1
[root@redis01 ~]#
III、notify_fault:主备都发生故障时会执行的脚本
这种情况下,什么也做不了,记个日志算了吧
[root@redis01 ~]# cat /etc/keepalived/config.d/redis_fault.sh
#!/bin/bash
LOGFILE=/var/log/keepalived-redis-state.log
echo "[fault]" >> $LOGFILE
date >> $LOGFILE
IV、notify_stop:节点停止时会执行的脚本
[root@redis01 ~]# cat /etc/keepalived/config.d/redis_stop.sh
这里可以将redis 停止的逻辑加上,但个人觉得意义不大
#!/bin/bash
LOGFILE=/var/log/keepalived-redis-state.log
echo "[stop]" >> $LOGFILE
date >> $LOGFILE
REDISCLI=`/usr/local/bin/redis-cli info|grep role|cut -d ":" -f 2`
REDISCLI1="/usr/local/bin/redis-cli"
REDISCLI2="/usr/local/bin/redis-cli -h $2 -p $3"
if [ $REDISCLI == "slave" ]
then
echo need no change ... >> $LOGFILE
else
$REDISCLI2 SLAVEOF NO ONE >> $LOGFILE 2>&1
$REDISCLI1 SLAVEOF $2 $3 >> $LOGFILE 2>&1
fi
#killall -9 redis-server
V、redis_check:状态检测脚本
[root@redis01 ~]# cat /etc/keepalived/config.d/redis_check.sh
#!/bin/bash
ALIVE=`/usr/local/bin/redis-cli -h $1 -p $2 PING`
LOGFILE="/var/log/keepalived-redis-check.log"
echo "[CHECK]:$ALIVE" >> $LOGFILE
date >> $LOGFILE
if [ $ALIVE == "PONG" ]
then
echo "Success: redis-cli -h $1 -p $2 PING $ALIVE" >> $LOGFILE 2>&1
exit 0
else
echo "Failed:redis-cli -h $1 -p $2 PING $ALIVE " >> $LOGFILE 2>&1
exit 1
fi
B、redis02上的redis主配置文件
[root@redis02 ~]# cat /etc/keepalived/keepalived.conf |grep -v "#"
! Configuration File for keepalived
global_defs {
router_id LVS_DEV
}
vrrp_script status_check
{
script "/etc/keepalived/config.d/redis_check.sh 127.0.0.1 6379"
interval 2
timeout 2
fall 3
}
vrrp_instance VI_1 {
state BACKUP
interface eno16777736
virtual_router_id 51
priority 80
advert_int 1
nopreempt
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.150.131/24
}
track_script {
status_check
}
notify_master "/etc/keepalived/config.d/redis_master.sh 192.168.150.130 192.168.150.129 6379"
notify_backup "/etc/keepalived/config.d/redis_backup.sh 192.168.150.130 192.168.150.129 6379"
notify_fault /etc/keepalived/config.d/redis_fault.sh
notify_stop "/etc/keepalived/config.d/redis_stop.sh 192.168.150.130 192.168.150.129 6379"
}
[root@redis02 ~]#
I、notify_master
[root@redis02 ~]# cat /etc/keepalived/config.d/redis_master.sh
#!/bin/bash
REDISCLI1="/usr/local/bin/redis-cli -h $1 -p $3"
REDISCLI2="/usr/local/bin/redis-cli -h $2 -p $3"
LOGFILE="/var/log/keepalived-redis-state.log"
echo "[master]" >> $LOGFILE
date >> $LOGFILE
REDISCLI=`/usr/local/bin/redis-cli info|grep role|cut -d ":" -f 2`
if [ $REDISCLI == "master" ]
then
echo do nothing here
else
$REDISCLI1 SLAVEOF NO ONE >> $LOGFILE 2>&1
sleep 10
$REDISCLI2 SLAVEOF $1 $3 >> $LOGFILE 2>&1
fi
II、notify_backup
[root@redis02 ~]# cat /etc/keepalived/config.d/redis_backup.sh
#!/bin/bash
REDISCLI="/usr/local/bin/redis-cli -h $1 -p $3"
REDISCLI1="/usr/local/bin/redis-cli -h $2 -p $3"
LOGFILE="/var/log/keepalived-redis-state.log"
echo "[BACKUP]" >> $LOGFILE
date >> $LOGFILE
#sleep 10 #delay 10 s wait data async cancel sync
echo "Run SLAVEOF NO ONE cmd ..." >> $LOGFILE
$REDISCLI1 SLAVEOF NO ONE >> $LOGFILE 2>&1
sleep 15 #delay 10 s wait data async cancel sync
echo "Being slave...." >> $LOGFILE 2>&1
echo "Run SLAVEOF cmd ..." >> $LOGFILE 2>&1
$REDISCLI SLAVEOF $2 $3 >> $LOGFILE
[root@redis02 ~]#
III、notify_fault(和redis01上一样)
IV、notify_stop(和redis01上一样)
V、redis_check.sh(和redis01上一样)
5、其它配置及相关测试
配置类的就这些,通过sheel来控制主从,结合keepalived实现HA高可用
[root@redis01 ~]# chmod +x /etc/keepalived/config.d/*
[root@redis02 ~]# chmod +x /etc/keepalived/config.d/*
由于篇幅限制,测试部分就不贴了,实际过程中我做了如下测试
1、
前置条件:redis01主、redis02从
测试内容:停止redis01上的redis,查看HA是否切换到redis02上,redis02是否变为master;恢复时启动redis01上的redis,检查redis01上redis是否变为slave(启动redis时不做HA切换,不变更主从关系)
2、
前置条件:redis01主、redis02从
测试内容:测试redis01上的keepalived进程停掉,查看HA是否切换到redis02上,redis02是否变为master;恢复时启动redis01上的keepalived,主从不改变,HA不切回。
3、
前置条件:redis01从、redis02主
测试内容:停止redis02上的redis,查看HA是否切换到redis01上,redis01是否变为master;恢复时启动redis02上的redis,检查redis02上redis是否变为slave(启动redis时不做HA切换,不变更主从关系)
4、
前置条件:redis01从、redis02主
测试内容:测试redis02上的keepalived进程停掉,查看HA是否切换到redis01上,redis01是否变为master;恢复时启动redis02上的keepalived,主从不改变,HA不切回。
由于本地模拟环境,数据量比较,测试结果还可以了。
这里没用到Sentinel,因为Sentinel也需要启动一个独立进程(裁决),实在不想为这个进程再做HA
ok,今天先就到这里吧!唉,苦逼的差旅,昨天晚上都快熬到天亮了...
以上是关于利用keepalive搭建高可用redis主从解决方案的主要内容,如果未能解决你的问题,请参考以下文章