喜旎果 发表于 2018-11-2 08:27:32

keepalived+expect方式实现redis主从高可用(亲测有用)

  前言:
  redis高可用有Sentinel、Cluster等多种方式,本文主要介绍keepalived方式。
  keepalived常用的实现高可用方式是当检查到被监控进程或keepalived服务本身挂掉时触发切换,这种方式对于redis主从高可用会有一个问题:当主的keepalived挂掉时,此时无法触发keepalived里的notify_backup脚本,主的redis状态还是master;此时从服务器会接管vip并且redis状态由slave切换为master,这时就会有两个master,主从架构被破坏。为了解决该问题,在notify_master脚本使用expect工具,本文在主从发生切换时,切换为master的主机会触发notify_master脚本,该脚本中的expect工具会远程到对方主机执行slaveof命令,重新确定主从关系。
  架构:

  配置:
hostnameiposredis版本keepalived版本备注redis-master172.27.9.30Centos7.3.16114.0.101.3.5关闭防火墙和selinuxredis-slave172.27.9.31Centos7.3.16114.0.101.3.5关闭防火墙和selinux  一、redis安装
  redis安装有yum和编译两种方式,本文以编译方式安装,参考文档为官网安装文档
  1.gcc安装
# yum -y install gcc  2.下载安装包
# wget http://download.redis.io/redis-stable.tar.gz  3.解压编译
# tar xvzf redis-stable.tar.gz  
# cd redis-stable
  
# make
  
# make install
  4.修改配置文件
# mkdir /etc/redis# mkdir -p /var/redis/6379  
# cp redis.conf /etc/redis/6379.conf
  
# cd /etc/redis/
  
# cp 6379.conf 6379.conf.bak
  
# grep -Ev '^$|#' 6379.conf.bak > 6379.conf
  主要配置修改如下:
#bind 127.0.0.1  
protected-mode no
  
daemonize yes
  
pidfile /var/run/redis_6379.pid
  
logfile /var/log/redis_6379.log
  
dir /var/redis/6379
  5.制作启动服务
# cp utils/redis_init_script /etc/init.d/redis_6379  6.启动服务并加入开机启动
# service redis_6379 start  
# chkconfig redis_6379 on
  7.RedisDesktopManager管理工具
  该工具为redis图形化管理工具
  软件下载:https://pan.baidu.com/s/1no0IWcIEBapfehNi8dfCfw 密码:7dvc
  连接设置:

  连接后效果

  二、redis主从复制及持久化
  1.从服务器设置
  redis主从复制很简单,只需要在从服务器配置文件新增一条配置即可
# sed -i '$a slaveof 172.27.9.30 6379' /etc/redis/6379.conf  2.主从测试
  2.1主机上写入值
# redis-cli set test-key abc  
OK
  查看从机redis键值:

  2.2从机写入值
# redis-cli set test-key 123  
(error) READONLY You can't write against a read only slave.
  发现报错,处于slave状态redis无法写入。
  3.持久化
  redis持久化有RDB和AOF两种方式,默认持久化为RDB方式,关闭默认持久化只需要把默认配置注释就行:
#save 900 1  
#save 300 10
  
#save 60 10000
  三、keepalived安装配置
  1.keepalived安装
# yum -y install keepalived  2.keepalived配置
# more /etc/keepalived/keepalived.conf  
! Configuration File for keepalived
  
global_defs {
  
   router_id master      #router_id 机器标识,通常为hostname,但不一定非得是hostname。故障发生时,邮件通知会用到。
  
}
  

  
vrrp_script chk_redis {
  
script "/etc/keepalived/redis-check.sh"
  
interval 2    #健康检查周期
  
weight 30   #优先级变化幅度
  
fall 2      #尝试两次都成功才成功
  
rise 2      #尝试两次都失败才失败
  
}
  

  
vrrp_instance VI_1 {            #vrrp实例定义部分
  
    state MASTER               #设置lvs的状态,MASTER和BACKUP两种,必须大写
  
    interface ens33               #设置对外服务的接口
  
    virtual_router_id 100      #设置虚拟路由标示,这个标示是一个数字,同一个vrrp实例使用唯一标示
  
    priority 100               #定义优先级,数字越大优先级越高,在一个vrrp——instance下,master的优先级必须大于backup
  
    advert_int 1            #设定master与backup负载均衡器之间同步检查的时间间隔,单位是秒
  
    authentication {         #设置验证类型和密码
  
      auth_type PASS         #主要有PASS和AH两种
  
      auth_pass 1111         #验证密码,同一个vrrp_instance下MASTER和BACKUP密码必须相同
  
    }
  
    virtual_ipaddress {         #设置虚拟ip地址,可以设置多个,每行一个
  
      172.27.9.100
  
    }
  
    track_script {            #执行脚本chk_redis
  
      chk_redis
  
    }
  

  
notify_master "/etc/keepalived/redis-master.sh" #指定当切换为master时,执行的脚本
  
}
  相比master,slave配置有3点不同:
router_id slave  
state BACKUP
  
priority 90
  为了避免主从间的来回切换,也可以设置nopreemt参数,开启非抢占式模式;不过当redis或者keepalived发生异常时都会触发各种告警,运维人员会及时介入处理。
  3.启动并设置开机启动
# systemctl start keepalived  
# systemctl enable keepalived
  四、expect安装
# yum -y install expect  expect是一个提供自动交互的工具,本文notify_master中的脚本会使用到。
  五、高可用脚本
  1.redis-check.sh脚本
# more redis-check.sh  
#!/bin/sh
  
rediscli="/usr/local/bin/redis-cli"
  
logfile="/var/log/redis_6379.log"
  
result=$($rediscli ping)
  
echo $result
  
echo "-------------------redis-check-------------------" >> $logfile
  
date >> $logfile
  
if [ $result == "PONG" ]; then :
  
   echo "Success: the result is $result" >> $logfile 2>&1
  
   exit 0
  
else
  
   echo "Failed:the result is $result " >> $logfile 2>&1
  
   exit 1
  
fi
  该脚本为对redis状态检查
  2.redis-master.sh脚本
# more redis-master.sh  
#!/bin/bash
  
rediscli="/usr/local/bin/redis-cli"
  
logfile="/var/log/redis_6379.log"
  
sync=`$rediscli info replication|grep master_sync_in_progress|awk -F: '{print $2}'|sed 's/\r//'`
  
#sync=`/usr/local/bin/redis-cli info replication|grep master_sync_in_progress|awk -F: '{print $2}'`
  
echo $sync
  
echo "-------------------change to master-------------------" >> $logfile 2>&1
  
date >> $logfile
  
if [ $sync == 0 ]; then :
  
    echo "the master_sync_in_progress is 0 and excute slaveof no one" >>$logfile 2>&1
  
    $rediscli slaveof no one
  
elif [ $sync == 1 ]; then :
  
    sleep 10
  
    $rediscli slaveof no one
  
else
  
    echo "the host is master,do nothing" >>$logfile 2>&1
  
fi
  
/etc/keepalived/exp.sh 172.27.9.31 monitor >>$logfile 2>&1
  该脚本为本文高可用切换的关键。
  monitor为31的root密码;slave脚本的ip应改为172.27.9.30;该脚本为服务器切换为master时执行的脚本,首先会检查切换前与master的主从同步是否完成,然后利用expect工具跳到另一台服务器将其redis状态更改为slave。
  3.exp.sh脚本
# more exp.sh  
#!/usr/bin/expect -f
  
set ip
  
set password
  
set timeout 30
  
spawn ssh root@$ip
  
expect {
  
"*yes/no" { send "yes\r"; exp_continue}
  
"*password:" { send "$password\r";exp_continue }
  
}
  
expect "#*"
  
send "/usr/local/bin/redis-cli slaveof 172.27.9.30 6379\r"
  
send"exit\r"
  
expect eof
  slave脚本中的ip为172.27.9.31;该脚本作用是跳到另一台服务执行slaveof命令。
  六、测试
  1.模拟redis服务异常
  操作:停掉master的redis服务
  预期:vip漂移,slave主机的redis状态切换为master
  测试过程:
  1.1停止master的redis服务
# service redis_6379 stop  1.2查看虚ip


  发现vip由30漂移至31
  1.3查看redis状态
# redis-cli info replication
  31的redis状态切换为master
  1.4回切
  启动30的redis服务
# service redis_6379 start  查看vip和redis状态
  30:

  31:

  结论:redis服务异常时会发生切换,从机会切换为master状态对外提供服务。
  2.模拟keepalived服务异常
  操作:停掉master的keepalived服务
  预期:vip漂移,master的redis状态切换为slave,slave的redis状态切换为master
  测试过程:
  2.1停止master的keepalived服务
# systemctl stop keepalived  2.2查看vip和redis状态
  30:

  31:

  vip由30漂移至31且主从发生反转;开启keepalived服务会触发回切。
  结论:keepalived服务异常时会发生切换,主从会反转。
  3.模拟master宕机
  操作:master关机
  预期:vip漂移,slave的redis状态切换为master
  测试过程:
  3.1master服务器关机
# init 0  3.2查看vip和redis状态

  vip漂移至31且状态切换为master;30开机会触发回切。
  结论:master宕机时会发生切换,从机切换为master状态对外提供服务。
  至此完成redis高可用测试。
  本文所有脚本和配置文件已上传,下载地址:https://github.com/loong576/redis-keepalived/archive/master.zip


页: [1]
查看完整版本: keepalived+expect方式实现redis主从高可用(亲测有用)