1. 前言

目前Redis主流的高可用方案主要是Master+Slave+Sentinel(即主从+哨兵)的模式,主要原理是:通过Sentinel(哨兵)集群来检测集群各节点Redis服务的存活状态及完成Redis集群的主从切换。切换完成后,Sentinel调用notification-script参数指定的配置文件,通知DNS服务更改DNS配置,完成Redis master节点的切换。

然而我们现在的应用不支持Sentinel模式,并且代码改起来改动较大,风险也比较大。所以只好舍弃了Master+Slave+Sentinel模式。

因为需要完成双机热备,并且还只能直接配置Redis服务信息,所以只能借助开源的keepalived工具来完成了。

2. 基础环境及环境部署架构

2.1 基础环境
操作系统IP操作系统版本操作系统主机名Redis版本keepalived版本
192.168.158.11Centos 7.9region015.0.9
192.168.158.12Centos 7.9region025.0.9

以下操作过程中,均使用操作系统主机名来区分两台机器,且两台操作系统都可联网。

keepalived服务涉及到的虚拟IP(VIP): 192.168.158.13

2.2 环境部署架构图

jiagou_redis

其中:

  1. 分别在region01和region02上安装redis,具体安装过程可参照Centos 7.9下源码安装Redis;
  2. keepalived需要在两台机器都进行安装;
  3. 最终程序或者客户端访问,直接用Virtual IP代替服务真实IP即可。
2.3 主备切换原理
  • 当主节点服务正常时,Virtual IP(虚拟IP)在主节点(region01)上,主节点Redis服务为应用提供服务。此时Redis为集群模式,region02上的Redis服务会同步region01上Redis服务的数据;
  • 当主节点服务异常时,Virtual IP(虚拟IP)会自动漂移到备节点(region02)上,备节点Redis服务为应用提供服务。此时Redis为单机模式。
  • 当主节点服务恢复时,包括Redis服务和keepalived服务(需要人为的干预)。主节点(region01)上的Redis会先成为备节点Redis服务的slave节点,先同步差异数据。然后数据同步完成后,主节点Redis服务开始为应用提供服务。此时Redis仍会恢复集群模式,region02上的Redis服务会同步region01上Redis服务的数据。

3. 编译安装keepalived

注意:此步骤需要在region01, region02分别执行。以下步骤以在region01操作为例。

3.1 安装依赖包及下载keepalived包

以下操作均在可以联网的情况下进行,如遇不能联网的情况,请自行准备keepalived源码包。

# 安装keepalived依赖包
[root@region01 ~]# yum -y install openssl-devel libnl3-devel ipset-devel iptables-devel libnfnetlink-devel net-snmp-devel wget gcc
# 下载keepalived源码包到/data/soft/
[root@region01 ~]# cd /data/soft
[root@region01 soft]# wget https://www.keepalived.org/software/keepalived-2.2.4.tar.gz
# 解压下载的源码包
[root@region01 soft]# tar -zvxf keepalived-2.2.4.tar.gz
# 上述操作完成后,/data/soft目录如下所示

kpd_source_viw

3.2 编译安装keepalived
# 编译及安装keepalived服务
[root@region01 soft]# cd keepalived-2.2.4
[root@region01 keepalived-2.2.4]# ./configure --prefix=/usr/local/keepalived
[root@region01 keepalived-2.2.4]# make && make install
# 成功编译完成后,提示如下图

kpd_install_view

3.3 配置keepalived服务
# 创建keepalived配置文件路径
[root@region01 keepalived-2.2.4]# mkdir /etc/keepalived
# 拷贝相关文件到指定路径
[root@region01 keepalived-2.2.4]# cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
[root@region01 keepalived-2.2.4]# cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
[root@region01 keepalived-2.2.4]# cp /data/soft/keepalived-2.2.4/keepalived/etc/init.d/keepalived /etc/init.d/
# 查看各个文件拷贝结果

在这里插入图片描述

4. 准备keepalived切换脚本及配置文件

keepalived切换时涉及多个脚本,且主从配置文件有些区别,所以请注意以下配置分别需要在哪台服务器设置

4.1 region01,region02均需要配置
# 进入/etc/keepalived目录,创建主备切换脚本目录
[root@region01 keepalived]# cd /etc/keepalived
[root@region01 keepalived]# mkdir scripts_redis
# 进入脚本目录,编辑检查redis服务存活状态的脚本
[root@region01 keepalived]# cd scripts_redis
[root@region01 scripts_redis]# vim check_redis.sh
# 以下为check_redis.sh的全部内容
#!/bin/bash

# LOGFILE地址可按照实际情况修改
LOGFILE=/data/env/redis/check-redis-status.log

echo "Running check_redis.sh..." >> $LOGFILE
date >> $LOGFILE

CHECK=$(ss -tnlp|grep 6379)
if [ $? -ne 0 ]; then
   echo "redis-server is not running..." >> $LOGFILE
   # 确保服务正常切换
   systemctl stop keepalived
   exit 1
else
   echo "redis-server is running..." >> $LOGFILE
   exit 0
fi
echo "Finished running check_redis.sh..." >> $LOGFILE

check_redis_shell

# 编写redis_fault脚本
[root@region01 scripts_redis]# vim redis_fault.sh
# 以下为redis_fault.sh脚本内容
#!/bin/bash

# LOGFILE文件需要跟据实际情况更改
LOGFILE=/data/env/redis/keepalived-redis-status.log
echo "Running redis_fault.sh..." >>$LOGFILE
echo "[Fault]" >> $LOGFILE
date >> $LOGFILE
echo "Finished running redis_fault.sh..." >> $LOGFILE

redis_fault

# 编写redis_stop脚本
[root@region01 scripts_redis]# vim redis_stop.sh
# 以下为redis_stop.sh脚本内容
#!/bin/bash

# LOGFILE文件需要跟据实际情况更改
LOGFILE=/data/env/redis/keepalived-redis-status.log
echo "Running redis_stop.sh...." >>$LOGFILE
echo "[Stop]" >> $LOGFILE
date >> $LOGFILE
echo "Finished running redis_stop.sh...." >>$LOGFILE

redis_stop

4.2 region01单独需要的配置

在使用keepalive做redis的高可用方案中,region01、region02两台机器需要配置不同的master及backup切换脚本,也需要单独配置不同的keepalived配置文件。

以下内容需要单独在region01主机(即keepalived主节点)上进行配置。

# 编辑region01上的redis_master脚本
[root@region01 scripts_redis]# vim redis_master.sh
# 以下为redis_master.sh脚本内容
#!/bin/bash

# LOGFILE文件需要跟据实际情况更改
LOGFILE=/data/env/redis/keepalived-redis-status.log
echo "Running redis_master.sh..." >>$LOGFILE

echo "[Master]" >> $LOGFILE
date >> $LOGFILE

REDISCLI="/usr/local/redis/bin/redis-cli"
echo "Being Master..." >> $LOGFILE
echo "Running SLAVEOF cmd..." >> $LOGFILE
# wait 15s 等待数据同步完成
sleep 15s

echo "Run slaveof no one cmd..."
# -h region01主机IP -p redis服务端口 -a redis密码
$REDISCLI -h 192.168.158.11 -p 6379 -a 78e13a SLAVEOF NO ONE >>$LOGFILE 2>&1
echo "Finished running redis_master.sh..." >>$LOGFILE

regino01_redis_master

# 编辑region01上的redis_backup脚本
[root@region01 scripts_redis]# vim redis_backup.sh
# 以下为redis_backup.sh脚本内容
#!/bin/bash

# LOGFILE文件需要跟据实际情况更改
LOGFILE=/data/env/redis/keepalived-redis-status.log
echo "Running redis_bakcup.sh..." >>$LOGFILE

echo "[Backup]" >> $LOGFILE
date >> $LOGFILE

echo "Being Slave..." >> $LOGFILE
sleep 5s
echo "Run SLAVEOF cmd..." >> $LOGFILE
REDISCLI="/usr/local/redis/bin/redis-cli"

# -h region01主机IP -p redis服务端口 -a redis密码
# 192.168.158.11为region02主机IP,6379为region02主机上redis服务端口
$REDISCLI -h 192.168.158.11 -p 6379 -a 78e13a SLAVEOF 192.168.158.12 6379 >>$LOGFILE 2>&1
echo "Finished running redis_backup.sh..." >>$LOGFILE

region01_redis_backup

# 为编辑好的脚本赋予可执行权限
[root@region01 scripts_redis]# chmod 755 *.sh

region01_redis_shell

# 编写region01主机上keepalived master节点的配置文件
[root@region01 scripts_redis]# cd /etc/keepalived/
[root@region01 keepalived]# vim keepalived.conf
# 以下为keepalived.conf文件内容
global_defs {
        router_id redis-master  # 主备节点需不同
}

vrrp_script chk_redis {
        script "/etc/keepalived/scripts_redis/check_redis.sh"
        interval 4
        weight -5
        fall 3
        rise 2
}

vrrp_instance VI_REDIS {
        state MASTER    # 主节点标识
        interface ens33
        virtual_router_id 51
        priority 150    # backup节点值小于150
        advert_int 1
        nopreempt
        unicast_src_ip 192.168.158.11  # 指定源ip
        unicast_peer {
                192.168.158.12   # 指定backup节点ip
                }

        authentication {
                auth_type PASS
                auth_pass 1111
        }

        virtual_ipaddress {
                192.168.158.13   # Virtual IP
        }

        track_script {
                chk_redis
        }
        
        # 不同情况下需要执行的脚本
        notify_master /etc/keepalived/scripts_redis/redis_master.sh
        notify_backup /etc/keepalived/scripts_redis/redis_backup.sh
        notify_fault  /etc/keepalived/scripts_redis/redis_fault.sh
        notify_stop   /etc/keepalived/scripts_redis/redis_stop.sh
}

region01_kpd_view01
region01_kpd_view02
注意:
1. 参照图片所示,最好将脚本中注释内容去掉。
2. 如果最后的脚本执行不成功,请检查脚本是否有可执行的权限。

4.3 region02单独需要的配置

与region01上的配置文件不相同,region02(即keepalived备节点)需要单独配置以下内容。

# 编辑region02上的redis_master脚本
[root@region02 keepalived]# cd /etc/keepalived/scripts_redis/
[root@region02 scripts_redis]# vim redis_master.sh
# 以下为redis_master.sh脚本内容
#!/bin/bash

# LOGFILE文件需要跟据实际情况更改
LOGFILE=/data/env/redis/keepalived-redis-status.log

echo "Runnings redis_master.sh..." >> $LOGFILE
echo "[Master]" >> $LOGFILE
date >> $LOGFILE

sleep 10s
echo "Run slaveof no one cmd...">>$LOGFILE

REDISCLI="/usr/local/redis/bin/redis-cli"
# -h region02主机IP -p redis服务端口 -a redis密码
$REDISCLI -h 192.168.158.12 -p 6379 -a 78e13a SLAVEOF NO ONE >>$LOGFILE 2>&1
echo "Finished running redis_master.sh...."  >> $LOGFILE

region02_redis_master

# 编辑region02上的redis_backup脚本
[root@region02 scripts_redis]# vim redis_backup.sh
# 以下为redis_backup.sh脚本内容
#!/bin/bash

# LOGFILE文件需要跟据实际情况更改
LOGFILE=/data/env/redis/keepalived-redis-status.log

echo "Running redis_backup.sh...." >>$LOGFILE
echo "[Backup]" >>$LOGFILE
echo date >>$LOGFILE

echo "Being Slave..." >> $LOGFILE
sleep 15s
echo "Run SLAVEOF cmd..." >> $LOGFILE
REDISCLI="/usr/local/redis/bin/redis-cli"
$REDISCLI -h 192.168.158.12 -p 6379 -a 78e13a SLAVEOF 192.168.158.11 6379 >>$LOGFILE 2>&1
echo "Finished running redis_backup.sh...." >> $LOGFILE

region02_redis_backup

# 为编辑好的脚本赋予可执行权限
[root@region02 scripts_redis]# chmod 755 *.sh

在这里插入图片描述

# 编辑region02(即keepalived备机)的keepalived的配置文件
[root@region02 scripts_redis]# cd /etc/keepalived/
[root@region02 keepalived]# vim keepalived.conf
# 以下为keepalived.conf文件内容
global_defs {
	router_id redis-slave   # 需与主节点不同
}

vrrp_script chk_redis {
	script "/etc/keepalived/scripts_redis/check_redis.sh"
	interval 4
	weight -5
	fall 3  
	rise 2
}

vrrp_instance VI_REDIS {
	state BAKCUP   # 备节点标识
	interface ens33
	virtual_router_id 51
	priority 100   # 优先值需比主节点小
	advert_int 1
	nopreempt
	unicast_src_ip 192.168.158.12  # 源ip
	unicast_peer {
		      192.168.158.11  # 主节点IP
		}

	authentication {
		auth_type PASS
		auth_pass 1111
	}

	virtual_ipaddress {
		192.168.158.13   # Virtual IP
	}

	track_script {
		chk_redis
	}
    
    # 不同情况分别需要执行的脚本
	notify_master /etc/keepalived/scripts_redis/redis_master.sh
	notify_backup /etc/keepalived/scripts_redis/redis_backup.sh
	notify_fault  /etc/keepalived/scripts_redis/redis_fault.sh
	notify_stop   /etc/keepalived/scripts_redis/redis_stop.sh
}

region02_kpd_view01
在这里插入图片描述
注意:
1. 参照图片所示,最好将脚本中注释内容去掉。
2. 如果最后的脚本执行不成功,请检查脚本是否有可执行的权限。
3. 备节点脚本与主节点基本都是IP地址的差异,但是脚本内容并不一样,请勿直接复制使用。

5. 验证高可用情况

5.1 启动keepalived服务

在启动keepalived服务以前,需要确保redis服务已经启动,否则主节点的keepalived服务会被脚本直接stop,然后漂移到备节点。

以下内容在region01,region02均需检查

# 确保两个节点redis服务均以启动,检查6379端口
# 以region01为例,但region02也需执行
[root@region01 scripts_redis]# ss -tnlp|grep 6379
# 返回结果如下图表明redis服务正常

region01_redis_status

# 启动keepalived服务
# 以region01为例,但region02也需执行
# [root@region01 ~]# systemctl start keepalived
# [root@region01 ~]# systemctl status keepalived
# 返回结果如下图表面keepalived启动成功

region01_kpd_status

5.2 验证主备功能是否正常

根据主备切换原理,验证过程需要分步进行。

1.首先验证Virtual IP能否在两台主机之间互相漂移。

按照主备切换的原理,当主节点服务正常时,虚拟IP会在主节点上;当主节点宕机,虚拟IP会自动切换到备节点。

# 集群正常时,Virtual IP在主节点(region01)上
# 集群主节点宕掉时,Virtual IP在备节点(region01)上

# 主备功能正常时,在region01执行
[root@region01 ~]# ip addr|grep ens33

kpd_status_true

# 模拟主节点redis服务宕机
# 在region01执行操作,杀掉redis-server进程
[root@region01 ~]# ss -tnlp|grep 6379
LISTEN     0      128          *:6379                     *:*                   users:(("redis-server",pid=32767,fd=6))
[root@region01 ~]# kill -9 32767

# 在region02执行
[root@region02 ~]# ip addr|grep ens33
# 如下图所示,表示keepalived虚拟IP漂移功能正常

kpd_status_false
2.验证主节点宕机过程中,Redis集群状态切换

# 在主节点执行脚本,查看正常情况下Redis集群状态
[root@region01 ~]# redis-cli -a 78e13a info
# 此时region01为Redis master节点,region02为Redis slave节点,主备服务正常。

reginon01_redis_status

# 模拟主节点宕机,杀掉redis-server服务
# 在region01上执行
[root@region01 ~]# ss -tnlp|grep 6379
LISTEN     0      128          *:6379                     *:*                   users:(("redis-server",pid=41295,fd=6))
[root@region01 ~]# kill -9 41295
# 在region02上执行
[root@region02 ~]# redis-cli -a 78e13a info
# region02变成Redis单节点,开始为应用提供服务。

region02_redis_status

# 模拟主节点恢复,region01执行脚本
# 启动redis-server服务
[root@region01 ~]# redis-server /etc/redis/redis.conf
# 启动keepalived服务
[root@region01 ~]# systemctl start keepalived

# 服务启动后,需要迅速去region02上查看集群状态
[root@region02 ~]# redis-cli -a 78e13a info
# 此时应该是以region02为master节点,region01为slave节点的集群。

region02_redis_status02

# 15s后,重新查看region02集群状态
[root@region02 ~]# redis-cli -a 78e13a info
# region01变成Redis的master节点,region02变成Redis的slave节点,region01重新开始为应用提供服务。

region02_redis_status03

5.3 验证主备切换过程中数据完整性

1.主备服务正常情况下,验证主从Redis集群数据同步

# 在region01上执行
[root@region01 ~]# redis-cli -a 78e13a
127.0.0.1:6379> set test01 nosql
OK
127.0.0.1:6379> keys *
1) "test01"

# 在region02上执行
[root@region02 ~]# redis-cli -a 78e13a
127.0.0.1:6379> keys *
1) "test01"
# Redis服务正常时,集群主备数据同步正常。

2.主节点服务宕机,备节点可继续用Virtual IP访问
为了更真实的验证,此过程我直接使用Windows客户端进行用Virtual IP访问Redis服务

# 在Windows执行脚本
C:\software\Redis-3.2>redis-cli.exe -h 192.168.158.13 -p 6379 -a 78e13a
192.168.158.13:6379> keys *
1) "test01"

# 在region01上执行
[root@region01 ~]# ss -tnlp|grep 6379
LISTEN     0      128          *:6379                     *:*                   users:(("redis-server",pid=41728,fd=6))
[root@region01 ~]# kill -9 41728

# 继续在Windows上执行
C:\software\Redis-3.2>redis-cli.exe -h 192.168.158.13 -p 6379 -a 78e13a
192.168.158.13:6379> keys *
1) "test01"
192.168.158.13:6379> set test02 nosql
OK
192.168.158.13:6379> keys *
1) "test02"
2) "test01"

# 在主机宕机的情况下,Virtual IP可继续提供服务且主节点数据不会丢。

client_virtual_status
3.主节点恢复,Virtual继续提供服务,同时在主节点宕机期间发生的数据不会丢

# 在region01上执行
[root@region01 ~]# redis-server /etc/redis/redis.conf 
[root@region01 ~]# systemctl restart keepalived

# 在Windows上执行,查看数据是否丢失
C:\software\Redis-3.2>redis-cli.exe -h 192.168.158.13 -p 6379 -a 78e13a
192.168.158.13:6379> keys *
1) "test01"
2) "test02"
# 数据仍存在,数据完整性正常。

client_virtual_status02

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐