【Redis】shell脚本实现redis双机房容灾切换(主从模式)

熟悉redis的人都会知道,redis可以使用sentinel哨兵模式进行容灾切换,但是在一些生产中不方便用到redis的哨兵模式,那么我们就需要对双机房发生容灾进行手动的切换。本次是通过shell脚本实现的双机房容灾切换。

1、双机房切换场景模拟

1、初始的双机房场景
在这里插入图片描述
2、A机房宕机切换至B机房场景
在这里插入图片描述
3、A机房修复后,同步数据场景
在这里插入图片描述
4、调整A、B机房为初始环境
在这里插入图片描述

2、A机房的主从切换

  • 当我们需要解决双机房的容灾时,首先要解决的是单个机房的容灾。这里我们用keepalived对A机房的redis进行心跳检测,再通过通知脚本实现redis主从的来回切换。

2.1、A机房的主从切换方案

1、初始的A机房场景
在这里插入图片描述

  • A机房在Master与Slave节点分别搭建Keepalived,设置虚拟vip;
  • B机房salveof A机房的vip;

2、A机房容灾的场景
在这里插入图片描述

  • 编写keepalived脚本检测Master心跳,当A机房的Master宕机后,将A机房的Slave设置为新的Master;
  • 当宕机的Master恢复后,将宕机的Master改为Slave,进行同步数据;
  • 数据同步完毕后,切换回初始的Master与slave;

2.2、A机房的容灾测试过程

服务器172.18.40.173为A机房的Master
服务器172.18.40.174为A机房的Slave
173,174服务器上分别搭建keepalive,设置虚拟IP为172.18.40.222

1、在A机房的173、174服务器上搭建keepalived;

① keepalived的虚拟地址监控redis的Master节点, 所以搭建好keepalived虚拟VIP在173的master节点;
② 在173节点上通过ip addr就可以看到
在这里插入图片描述

2、分别修改与编写173,174服务器的Master与slave的keepalived.conf与redis_check.sh、redis_master.sh、redis_backup.sh脚本;

keepalived.conf与redis_check.sh、redis_master.sh、redis_backup.sh脚本具体见[2.3、A机房的keepalived配置文件与脚本]

3、启动向redis存储的程序,配置地址为虚拟Vip的地址;
在这里插入图片描述
4、查看Master与Slave的存储状态,发现Master写入数据正常,Slave备份数据正常;

由于程序在循环存入数据,查看数据时不是同一时间,所以图片显示的存储数量不同. 此处要说明Master在写入数据,Slave在进行备份,存储良好
在这里插入图片描述

5、关闭173的Master的节点;
在这里插入图片描述
6、keepalived的虚拟Vip已经漂移到174服务器,数据转移到174服务器进行写入;

keepalived的虚拟vip监控Master节点, 说明173的master宕机后,174的slave切换master成功
在这里插入图片描述

7、查看174服务器的存储情况与节点信息,174已经变为Master的状态,且正在进行写入数据;
在这里插入图片描述
在这里插入图片描述
8、重启173服务器的redis;
在这里插入图片描述
9、虚拟vip已经又漂移到173服务器;

说明当173的服务器恢复后,keepalived让主从切换为原来的状态
在这里插入图片描述

10、查看174服务器的节点状态,已改变为slave,且备份的偏移量相同
在这里插入图片描述
11、停止写入数据程序,查看173、174服务器存储情况,数据一致没有丢失;
在这里插入图片描述

2.3、A机房的keepalived配置文件与脚本

1.Master的keepalived.conf配置文件

! Configuration File for keepalived
global_defs {
   router_id redis01
}
vrrp_script chk_redis{
     script "/etc/keepalived/script/redis_check.sh 172.18.40.173 6379 auth"   ## 修改auth为密码
     interval 2
     timeout 2
     fall 3
}
vrrp_instance redis {
    state MASTER
    interface ens192   ##需要修改为实际网卡名称
    virtual_router_id 60
    priority 100          ##权重,数字越大权重越大,主节点数值大于备节点
    advert_int 1
authentication {   #all node must same
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        172.18.40.222     ##需要修改为实际分配的虚拟IP
    }
    track_script {
         chk_redis
    }

    notify_master "/etc/keepalived/script/redis_master.sh 127.0.0.1 172.18.40.174 6379 auth"     ## 172.18.40.174 6379需要修改为实际的远端主机IP   ## 修改auth为密码

    notify_backup "/etc/keepalived/script/redis_backup.sh 127.0.0.1 172.18.40.174 6379 auth"     ## 172.18.40.174 6379需要修改为实际的远端主机IP   ## 修改auth为密码
}

2.Master的redis_check.sh脚本文件

#!/bin/bash 

ALIVE=`/app/soft/redis-5.0.5/bin/redis-cli -h $1 -p $2 -a $3 PING` 
LOGFILE="/app/log/keepalived/status" 
echo "[CHECK]" >> $LOGFILE
date >> $LOGFILE
if [ "$ALIVE" == "PONG" ]; then
    echo "Success: redis-cli -h $1 -p $2 -a $3  PING $ALIVE" >> $LOGFILE 2>&1
    exit 0   
else  
    echo "Failed:redis-cli -h $1 -p $2 -a $3 PING $ALIVE " >> $LOGFILE 2>&1
    exit 1 
fi 

3.Master的redis_master.sh脚本文件

#!/bin/bash

REDISCLI="/app/soft/redis-5.0.5/bin/redis-cli -h $1 -p $3 -a $4"
LOGFILE="/app/log/keepalived/status"
echo "[master]" >> $LOGFILE
date >> $LOGFILE
echo "Being master...." >> $LOGFILE
echo "Run MASTER cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF $2 $3 >> $LOGFILE

##判断偏移量,也可以使用下面注释掉的sleep进行同步数据的等待

slave=$(/app/soft/redis-5.0.5/bin/redis-cli -h $2 -a $4 info | grep slave0 | awk -F "=" '{print $5}' | awk -F "," '{print $1}')  
master=$(/app/soft/redis-5.0.5/bin/redis-cli -h $2 -a  $4 info | grep master_repl_offset | awk -F ":" '{print $2}' | awk -F "\r" '{print $1}' )

  while [ "$slave" != "$master" ];
  do
      slave=$(/app/soft/redis-5.0.5/bin/redis-cli -h $2 -a $4 info | grep slave0 | awk -F "=" '{print $5}' | awk -F "," '{print $1}')
      master=$(/app/soft/redis-5.0.5/bin/redis-cli -h $2 -a $4 info | grep master_repl_offset | awk -F ":" '{print $2}' | awk -F "\r" '{print $1}' )
      echo $slave
      echo $master
  done 
#sleep 10 #delay 10 s wait data async cancel sync
echo "Run SLAVEOF NO ONE cmd ..." >> $LOGFILE
${REDISCLI} SLAVEOF NO ONE >> $LOGFILE

4.Master的redis_backup.sh脚本文件

#!/bin/bash

REDISCLI="/app/soft/redis-5.0.5/bin/redis-cli -h $1 -p $3 -a $4"
LOGFILE="/app/log/keepalived/status"
echo "[backup]" >> $LOGFILE
date >> $LOGFILE
echo "Run SLAVEOF cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF $2 $3 >> $LOGFILE 2>&1

##判断偏移量,也可以使用下面注释掉的sleep进行同步数据的等待
slave=$(/app/soft/redis-5.0.5/bin/redis-cli -h $2 -a $4 info | grep slave0 | awk -F "=" '{print $5}' | awk -F "," '{print $1}')  
master=$(/app/soft/redis-5.0.5/bin/redis-cli -h $2 -a  $4 info | grep master_repl_offset | awk -F ":" '{print $2}' | awk -F "\r" '{print $1}' )

while [ "$slave" != "$master" ];
 do
      slave=$(/app/soft/redis-5.0.5/bin/redis-cli -h $2 -a $4 info | grep slave0 | awk -F "=" '{print $5}' | awk -F "," '{print $1}')
      master=$(/app/soft/redis-5.0.5/bin/redis-cli -h $2 -a $4 info | grep master_repl_offset | awk -F ":" '{print $2}' | awk -F "\r" '{print $1}' )
      echo $slave
      echo $master
  done 


#sleep 15 #delay 15 s wait data sync exchange role

5.Slave的keepalived.conf配置文件

! Configuration File for keepalived
global_defs {
   router_id redis02
}

vrrp_script chk_redis
{
     script "/etc/keepalived/script/redis_check.sh 172.18.40.174 6379 auth " ##修改auth为密码
     interval 2
     timeout 2
     fall 3
}

vrrp_instance redis {
    state BACKUP
    interface ens192   ##需要修改为实际网卡名称
    virtual_router_id 60
    priority 90
    advert_int 1
authentication {   #all node must same
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        172.18.40.222     ##需要修改为实际分配的虚拟IP
    }
    track_script {
         chk_redis
    }

   notify_master "/etc/keepalived/script/redis_master.sh 127.0.0.1 172.18.40.173 6379 auth"     ## 172.18.40.174 6379需要修改为实际的远端主机IP   ## 修改auth为密码

    notify_backup "/etc/keepalived/script/redis_backup.sh 127.0.0.1 172.18.40.173 6379 auth"     ## 172.18.40.174 6379需要修改为实际的远端主机IP   ## 修改auth为密码

}

6.Slave的redis_check.sh脚本文件

#!/bin/bash 

ALIVE=`/app/soft/redis-5.0.5/bin/redis-cli -h $1 -p $2 -a $3 PING` 
LOGFILE="/app/log/keepalived/status" 
echo "[CHECK]" >> $LOGFILE
date >> $LOGFILE
if [ "$ALIVE" == "PONG" ]; then
    echo "Success: redis-cli -h $1 -p $2 -a $3  PING $ALIVE" >> $LOGFILE 2>&1
    exit 0   
else  
    echo "Failed:redis-cli -h $1 -p $2 -a $3 PING $ALIVE " >> $LOGFILE 2>&1
    exit 1 
fi 

7.Slave的redis_master.sh脚本文件

#!/bin/bash

REDISCLI="/app/soft/redis-5.0.5/bin/redis-cli -h $1 -p $3 -a $4"
LOGFILE="/app/log/keepalived/status"
echo "[master]" >> $LOGFILE
date >> $LOGFILE
echo "Being master...." >> $LOGFILE
echo "Run MASTER cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF $2 $3 >> $LOGFILE

##判断偏移量,也可以使用下面注释掉的sleep进行同步数据的等待

slave=$(/app/soft/redis-5.0.5/bin/redis-cli -h $2 -a $4 info | grep slave0 | awk -F "=" '{print $5}' | awk -F "," '{print $1}')  
master=$(/app/soft/redis-5.0.5/bin/redis-cli -h $2 -a  $4 info | grep master_repl_offset | awk -F ":" '{print $2}' | awk -F "\r" '{print $1}' )

  while [ "$slave" != "$master" ];
  do
      slave=$(/app/soft/redis-5.0.5/bin/redis-cli -h $2 -a $4 info | grep slave0 | awk -F "=" '{print $5}' | awk -F "," '{print $1}')
      master=$(/app/soft/redis-5.0.5/bin/redis-cli -h $2 -a $4 info | grep master_repl_offset | awk -F ":" '{print $2}' | awk -F "\r" '{print $1}' )
      echo $slave
      echo $master
  done 

#sleep 10 #delay 10 s wait data async cancel sync
echo "Run SLAVEOF NO ONE cmd ..." >> $LOGFILE
${REDISCLI} SLAVEOF NO ONE >> $LOGFILE

8.Slave的redis_backup.sh脚本文件

#!/bin/bash

REDISCLI="/app/soft/redis-5.0.5/bin/redis-cli -h $1 -p $3 -a $4"
LOGFILE="/app/log/keepalived/status"
echo "[backup]" >> $LOGFILE
date >> $LOGFILE
echo "Run SLAVEOF cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF $2 $3 >> $LOGFILE 2>&1

##判断偏移量,也可以使用下面注释掉的sleep进行同步数据的等待
slave=$(/app/soft/redis-5.0.5/bin/redis-cli -h $2 -a $4 info | grep slave0 | awk -F "=" '{print $5}' | awk -F "," '{print $1}')  
master=$(/app/soft/redis-5.0.5/bin/redis-cli -h $2 -a  $4 info | grep master_repl_offset | awk -F ":" '{print $2}' | awk -F "\r" '{print $1}' )

while [ "$slave" != "$master" ];
 do
      slave=$(/app/soft/redis-5.0.5/bin/redis-cli -h $2 -a $4 info | grep slave0 | awk -F "=" '{print $5}' | awk -F "," '{print $1}')
      master=$(/app/soft/redis-5.0.5/bin/redis-cli -h $2 -a $4 info | grep master_repl_offset | awk -F ":" '{print $2}' | awk -F "\r" '{print $1}' )
      echo $slave
      echo $master
  done 
#sleep 15 #delay 15 s wait data sync exchange role

3、AB机房的容灾切换

3.1、AB机房的容灾切换方案

1.初始场景
在这里插入图片描述

2.A机房宕机后切换为B机房
在这里插入图片描述

  • A机房宕机后B机房设置Slaveof no one;

3.A机房修复后,进行同步B机房的数据
在这里插入图片描述

  • A机房恢复后,A机房Master设置为slaveof B机房进行数据同步;
  • B机房的master防止程序继续写入数据,直到数据同步完成;
  • master没有只读一说,防止程序写入,可以通过设置min-slaves-to-write参数阻止程序写入

4.数据同步完成,切换为原来的状态

在这里插入图片描述

  • A机房恢复后A机房Master的设置为slaveof no one;
  • B机房的设置为slaveof vip;

3.2、AB机房的容灾切换脚本

1.当A机房宕机后,执行task1.sh的脚本,实现切换到B机房;

task1.sh

#!/bin/bash
user='root'
ip='172.18.40.175'
password='*******'
#-----------ssh连接到B机房------------
function ssh(){
      /app/soft/redis-5.0.5/bin/redis-cli -h $ip -a $password  slaveof no one >/dev/null 2>&1
      /app/soft/redis-5.0.5/bin/redis-cli -h $ip -a $password  CONFIG REWRITE >/dev/null 2>&1

echo '完成B机房的切换'
     
}

ssh

2.当A机房恢复后,执行task2.sh的脚本,实现A机房同步B机房的数据,同步数据完成后,切换为原来的状态;

task2.sh

#!/bin/bash

ip1='172.18.40.175'
ip2='172.18.40.173'
user='root'
password='*******'

#----------登录Master修改节点---------
function change1(){

/app/soft/redis-5.0.5/bin/redis-cli -h $ip2 -a $password slaveof $ip1 6379  > /dev/null 2>&1
/app/soft/redis-5.0.5/bin/redis-cli -h $ip2 -a $password CONFIG REWRITE > /dev/null 2>&1
echo '完成B机房的节点修改'
}
#-------------判断偏移量-------------

function decide(){
   
  slave=$(/app/soft/redis-5.0.5/bin/redis-cli -h $ip1 -a powersi@redis info | grep slave0 | awk -F "=" '{print $5}' | awk -F "," '{print $1}')  
  master=$(/app/soft/redis-5.0.5/bin/redis-cli -h $ip1 -a powersi@redis info | grep master_repl_offset | awk -F ":" '{print $2}' | awk -F "\r" '{print $1}' )

  while [ "$slave" != "$master" ];
  do
      slave=$(/app/soft/redis-5.0.5/bin/redis-cli -h $ip1 -a powersi@redis info | grep slave0 | awk -F "=" '{print $5}' | awk -F "," '{print $1}')
      master=$(/app/soft/redis-5.0.5/bin/redis-cli -h $ip1 -a powersi@redis info | grep master_repl_offset | awk -F ":" '{print $2}' | awk -F "\r" '{print $1}' )
      echo $slave
      echo $master
  done 

}

function change2(){

    /app/soft/redis-5.0.5/bin/redis-cli -h $ip2 -a $password slaveof no one > /dev/null 2>&1
    /app/soft/redis-5.0.5/bin/redis-cli -h $ip2 -a $password CONFIG REWRITE  > /dev/null 2>&1

    echo '完成Master节点的切换'
    /app/soft/redis-5.0.5/bin/redis-cli -h $ip1 -a $password slaveof $ip2 6379  > /dev/null 2>&1
    /app/soft/redis-5.0.5/bin/redis-cli -h $ip1 -a $password CONFIG REWRITE > /dev/null 2>&1 
}
#----------------方法-------------------

change1
decide
change2

3.3、AB机房的容灾切换测试

1.向A机房的173的Master节点写入10条数据;
在这里插入图片描述
2.关闭A机房的173、174的Master与Slave节点;
在这里插入图片描述
3.执行task1.sh脚本切换到B机房;
在这里插入图片描述
4.查看B机房的节点状态,B机房已切换为Master节点;
在这里插入图片描述
5.向B机房写入5条数据,加上之前同步A机房的10条数据,此时共有15条数据;

在这里插入图片描述
6.重启A机房173、174的Master与Slave节点,并执行task2.sh脚本;
在这里插入图片描述
7.查看A机房173、174节点与B机房175节点的数据情况,发现切换后数据同步正常;
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
8.查看A机房173、174节点与B机房175节点的节点信息,发现已切换为原来的状态;

A 机房173的Master节点
在这里插入图片描述

A 机房174的Slave节点
在这里插入图片描述

B机房的175的Slave节点
在这里插入图片描述

4、总结

本次通过keepalived与shell脚本分别实现了单机房的容灾切换与双机房的容灾切换,但是双机房容灾切换时需要将两个shell脚本应用到具体的生产中,通过程序检测各个机房的心跳,调用shell脚本可实现自动化的切换。

©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页