利用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主从解决方案的主要内容,如果未能解决你的问题,请参考以下文章

生产环境搭建高可用Harbor

Linux运维-搭建高可用Redis缓存

Redis Cluster搭建高可用Redis服务器集群

Redis 实战搭建高可用架构

搭建高可用主从DNS域名解析服务

搭建高可用MongoDB集群(Replica set)