redis高可用:keepalived+redis主从部署

1 Redis高可用的可选方案

Redis的高可用方案目前主要5种方式。
1)  Redis Master-Slave + Keepalived + VIP。
这是很经典的db架构,也可以用与mysql的主从切换。基本原理是:Keepalive通过脚本检测master的存活,然后通过漂移VIP(Virtual IP)完成主从切换。
2)  Redis Master-Slave + DNS Service + Sentinel。
基本原理是Sentinel集群进行Redis的存活检测和Redis M-S状态切换。完成切换之后,sentinel调用notification-script参数制定的配置文件,通知DNS Server更改DNS配置,master dns解析执行新的master。
3)  Redis Master-Slave + Configure Center(Zookeeper) + Sentinel.
基本原理和第三种方案相似,只是notification-script通知的是配置中心完成redis连接配置的修改,比如Zookeeper实现的配置中心。
4)  Redis Master-Slave + Sentinel + Twemproxy + Lvs.
这种方案层次比较多,sentinel通知twemproxy进行redis m-s的配置更改。
5)Redis Cluster,redis3.0发布了该功能,稳定性还待市场检验。

 
  

本文演示第一种方案:Redis Master-Slave + Keepalived + VIP.

1. 基本构建与原理

1)Keepalived + VIP : 在redis master-slave上部署keepalived、redis instance存活检测脚本、以及告警通知脚本。

2)当redis master失效的时候,VIP从master上漂移到slave上,完成m-s角色和配置更改。3)客户端连接redis的参数中host设置的是VIP,整个切换过程对客户端透明。

2. 优缺点与适用场景。

优点:实现简单,成本低,整个切换过程对客户端透明。

缺点:整个集群的最大吞吐量受限于redis单实例的处理能力,除非一个应用使用多套这种Keepalived+VIP方案。因而扩展能力较差,而且不适合目前单机部署多个redis实例的部署场景。

适合场景:并发请求不是很高的应用。

 
  
 
  

2 安装keepalived

1. tar zxf  keepalived-1.3.5.tar.gz 2. cd keepalived-1.3.5 3. ./configure --prefix=/usr/local/keepalived/ 4. make 5. make install 拷贝需要的文件: $ cp /usr/local/src/keepalived-1.3.5/keepalived/etc/init.d/keepalived /etc/init.d/keepalived $ cp /usr/local/keepalived/sbin/keepalived /usr/sbin/ $ cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/ $ mkdir -p /etc/keepalived/ $ cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf是默认的配置文件

第一步,安装基础库

yum -y install openssl-devel libnl3-devel ipset-devel iptables-devel libnfnetlink-devel net-snmp-devel

第二步,源码安装keepalived

 
  
 
  

3 keepalived + Redis主从部署

3.1 部署拓补图

基于如下的拓扑图:

redis高可用:keepalived+redis主从部署_第1张图片
 
  
 
  

3.2 Redis主从配置

3.2.1 Redis安装

步骤1: 首先从官网(http://download.redis.io/releases/)下载redis正式版的压缩包redis-2.8.19.tar.gz   步骤2:编译源码安装: cd /usr/local/src/ tar zxvf redis-2.8.19.tar.gz cd redis-2.8.19 make make install

3.2.2 修改redis配置文件

cd redis-2.8.19 vim redis.conf 修改相关配置项,这里仅做DOME演示,其他配置项默认。 修改redis master的redis.conf daemonize yes logfile /var/log/redis.log 修改redis backup的redis.conf daemonize yes logfile /var/log/redis.log slaveof 172.30.1.22 6379

 
  

3.2.3 启动Redis

分别启动主从redis-server:
cd redis-2.8.19
./src/redis-server ./redis.conf
3.2.3 测试主从功能
在主机器上执行set key value:
[root@localhost redis-2.8.19]# ./src/redis-cli -p 6379
127.0.0.1:6379> set nosql redis
OK
127.0.0.1:6379>
在从机器上执行get key:
[root@localhost redis-2.8.19]# ./src/redis-cli -p 6379
127.0.0.1:6379> get nosql
"redis"
127.0.0.1:6379>
OK,测试正常。

 
  

3.2 主从公共脚本

3.2.1 Redis监控脚本

该脚本检测redis的运行状态,并在nginx进程不存在时尝试重新启动ngnix,如果启动失败则停止keepalived,准备让其它机器接管。

/etc/keepalived/scripts/check_redis.sh:

#!/bin/bash
CHECK=`/usr/local/bin/redis-cli PING`
if [ "$CHECK" == "PONG" ] ;then
      echo $CHECK
      exit 0
else 
      echo $CHECK
      service keepalived stop #可确保让出MASTER
      exit 1
fi


keepalived根据监控脚本的返回码调整优先级:

☉如果脚本返回码为0,并且weight配置的值大于0,则优先级相应的增加;

☉如果脚本返回码为非0,并且weight配置的值小于0,则优先级相应的减少;

☉其他情况,原本配置的优先级不变,即配置文件中priority对应的值。

提示:

优先级不会不断的提高或者降低;

可以编写多个检测脚本并为每个检测脚本设置不同的weight(在配置中列出就行);

不管提高优先级还是降低优先级,最终优先级的范围是在[1,254],不会出现优先级小于等于0或者优先级大于等于255的情况;

在MASTER节点的 vrrp_instance 中 配置 nopreempt ,当它异常恢复后,即使它 prio 更高也不会抢占,这样可以避免正常情况下做无谓的切换。

以上可以做到利用脚本检测业务进程的状态,并动态调整优先级从而实现主备切换。

3.2.2 redis_fault.sh

vim /etc/keepalived/scripts/redis_fault.sh 

# !/bin/bash
LOGFILE=/usr/local/src/redis-2.8.19/keepalived-redis-state.log 
echo "[fault]" >> $LOGFILE 
date >> $LOGFILE
3.2.3 redis_stop.sh
# !/bin/bash
LOGFILE=/usr/local/src/redis-2.8.19/keepalived-redis-state.log 
echo "[stop]" >> $LOGFILE 
date >> $LOGFILE

vim /etc/keepalived/scripts/redis_stop.sh  

# !/bin/bash
LOGFILE=/usr/local/src/redis-2.8.19/keepalived-redis-state.log 
echo "[stop]" >> $LOGFILE 
date >> $LOGFILE

3.3 keepalived scripts for redis

  为redis配置keepalived所需要的脚本。

3.3.1 Redis Master scripts

  在redis master配置:

   vim/etc/keepalived/scripts/redis_master.sh

#!/bin/bash
REDISCLI="/usr/local/bin/redis-cli"
LOGFILE="/usr/local/src/redis-2.8.19/keepalived-redis-state.log"
echo "[master]" >> $LOGFILE
date >> $LOGFILE
echo "Being master...." >> $LOGFILE 2>&1
echo "Run SLAVEOF cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF 172.30.1.23 6379 >> $LOGFILE  2>&1
sleep 10 #延迟10秒以后待数据同步完成后再取消同步状态
echo "Run SLAVEOF NO ONE cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF NO ONE >> $LOGFILE 2>&1

vim /etc/keepalived/scripts/redis_backup.sh

#!/bin/bash
REDISCLI="/usr/local/bin/redis-cli"
LOGFILE="/usr/local/src/redis-2.8.19/keepalived-redis-state.log"
echo "[backup]" >> $LOGFILE
date >> $LOGFILE
echo "Being slave...." >> $LOGFILE 2>&1
sleep 15 #延迟15秒待数据被对方同步完成之后再切换主从角色
echo "Run SLAVEOF cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF 172.30.1.23 6379 >> $LOGFILE  2>&1

3.3.2 Redis Backup scripts

  和3.3.1节的配置基本一样,只是脚本中redis的IP为原master主机的IP。

  在redis backup配置:

 vim/etc/keepalived/scripts/redis_master.sh

#!/bin/bash
REDISCLI="/usr/local/bin/redis-cli"
LOGFILE="/usr/local/src/redis-2.8.19/keepalived-redis-state.log"
echo "[master]" >> $LOGFILE
date >> $LOGFILE
echo "Being master...." >> $LOGFILE 2>&1
echo "Run SLAVEOF cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF 172.30.1.22 6379 >> $LOGFILE  2>&1
sleep 10 #延迟10秒以后待数据同步完成后再取消同步状态
echo "Run SLAVEOF NO ONE cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF NO ONE >> $LOGFILE 2>&1

vim /etc/keepalived/scripts/redis_backup.sh

#!/bin/bash
REDISCLI="/usr/local/bin/redis-cli"
LOGFILE="/usr/local/src/redis-2.8.19/keepalived-redis-state.log"
echo "[backup]" >> $LOGFILE
date >> $LOGFILE
echo "Being slave...." >> $LOGFILE 2>&1
sleep 15 #延迟15秒待数据被对方同步完成之后再切换主从角色
echo "Run SLAVEOF cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF 172.30.1.22 6379 >> $LOGFILE  2>&1

3.4 配置keepalived.conf

keepalived.conf样例

global_defs {
	router_id redis
}

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

vrrp_instance VI_REDIS {
	state MASTER
	interface eth1
	virtual_router_id 51
	priority 100
	advert_int 1
	nopreempt

	authentication {
		auth_type PASS
		auth_pass 1111
	}

	virtual_ipaddress {
		172.30.1.15
	}

	track_script {
		chk_redis
	}

	notify_master /etc/keepalived/scripts/redis_master.sh
	notify_backup /etc/keepalived/scripts/redis_backup.sh
	notify_fault  /etc/keepalived/scripts/redis_fault.sh
	notify_stop   /etc/keepalived/scripts/redsi_stop.sh
}

注意,在同一个网段内的,若为不同的应用做高可用,不同应用使用不同的VIP,那么vrrp_instance的名字(这里是VI_REDIS)、virtual_router_id在不同的高可用实例必须设置不同的值区分开。否则keepalived会报如下错误:

Aug 11 11:28:36 localhostKeepalived_vrrp[16958]: (VI_1): received an invalid ip number count 1, expected2!

Aug 11 11:28:36 localhostKeepalived_vrrp[16958]: bogus VRRP packet received on eth1 !!!

Aug 11 11:28:36 localhostKeepalived_vrrp[16958]: VRRP_Instance(VI_1) Dropping received VRRP packet...

以上是keepalived MASTER节点配置文件/etc/keepalived/keepalived.conf的配置信息。在BACKUP节点,只需把vrrp_instance->state改为BACKUP,vrrp_instance->priority改为99即可。

在默认的keepalive.conf里面还有 virtual_server,real_server 这样的配置,我们这用不到,它是为lvs准备的。 notify 可以定义在切换成MASTER或BACKUP时执行的脚本,如有需求请自行google。

  配置选项说明

global_defs

☉notification_email: keepalived在发生诸如切换操作时需要发送email通知地址,后面的 smtp_server 相比也都知道是邮件服务器地址。也可以通过其它方式报警,毕竟邮件不是实时通知的。

☉router_id: 机器标识,通常可设为hostname。故障发生时,邮件通知会用到

vrrp_instance

☉state : 指定instance(Initial)的初始状态,就是说在配置好后,这台服务器的初始状态就是这里指定的,但这里指定的不算,还是得要通过竞选通过优先级来确定。如果这里设置为MASTER,但如若他的优先级不及另外一台,那么这台在发送通告时,会发送自己的优先级,另外一台发现优先级不如自己的高,那么他会就回抢占为MASTER

☉interface: 实例绑定的网卡,因为在配置虚拟IP的时候必须是在已有的网卡上添加的,可以用ifconfig命令查看网卡。

☉mcast_src_ip: 发送多播数据包时的源IP地址,这里注意了,这里实际上就是在那个地址上发送VRRP通告,这个非常重要,一定要选择稳定的网卡端口来发送,这里相当于heartbeat的心跳端口,如果没有设置那么就用默认的绑定的网卡的IP,也就是interface指定的IP地址

☉virtual_router_id: 这里设置VRID,这里非常重要,相同的VRID为一个组,他将决定多播的MAC地址

☉priority: 设置本节点的优先级,优先级高的为master

☉advert_int: 检查间隔,默认为1秒。这就是VRRP的定时器,MASTER每隔这样一个时间间隔,就会发送一个advertisement报文以通知组内其他路由器自己工作正常

☉authentication: 定义认证方式和密码,主从必须一样,样例用的是密码方式。

☉virtual_ipaddress: 这里设置的就是VIP,也就是虚拟IP地址,他随着state的变化而增加删除,当state为master的时候就添加,当state为backup的时候删除,这里主要是有优先级来决定的,和state设置的值没有多大关系。这里可以设置多个虚拟IP地址,类似于一个域名可以解析对应多个IP地址。

☉track_script: 引用VRRP脚本,即在 vrrp_script 部分指定的名字。每隔vrrp_script->interval时间运行脚本,如果监控服务有异常则改变优先级,并最终引发主备切换。

vrrp_script

告诉 keepalived 在什么情况下切换,所以尤为重要。可以有多个 vrrp_script

☉script : 自己写的检测脚本。也可以是一行命令如killall-0 nginx

☉interval4 : 每4s检测一次,这里要大于监控脚本执行的时间,监控脚本会执行超时,☉keepalived会发送SIGTERM信号结束监控脚本的执行。

☉weight-5 : 检测失败(脚本返回非0)则优先级 -5

☉fall 2: 检测连续 2 次失败才算确定是真失败。会用weight减少优先级(1-255之间)

☉rise 1: 检测 1 次成功就算成功。但不修改优先级

4.1启动keepalived 

在Redis Master和Redis Backup上将keepalived启动

启动keepalived:

service keepalived start

或者

/etc/init.d/keepalived start

或者

/usr/local/keepalived/sbin/keepalived -f/etc/keepalived/keepalived.conf -D

查看进程,正常会有三个进程

[root@localhost ~]# ps -ef | grepkeepalived

root     3870     1  0 14:46 ?        00:00:00 keepalived -D

root     3872  3870  0 14:46 ?        00:00:00 keepalived -D

root     3873  3870  0 14:46 ?       00:00:00 keepalived -D

root     3887 18774  0 14:46 pts/1    00:00:00 grep keepalived

[root@localhost ~]#

用ip命令查看VIP,ifconfig命令不能查看虚拟IP。

[root@localhost ~]#  ip a | grep eth1

2: eth1: mtu 1500 qdisc pfifo_fast state UP qlen1000

   inet 172.30.1.22/24 brd 172.30.1.255scope global eth1

   inet 172.30.1.15/32 scope global eth1

[root@localhost ~]#

  可以看到现在是172.30.1.22接管着VIP。

  至此,Keppalived+Redis主从高可用环境已经搭建完成。客户端访问Redis使用VIP,或者将redis的域名解析指向VIP。

4 测试

  测试时可以用命令tail -f /var/log/messages查看keepalived的日志,查看主从机器状态的变化,VIP的漂移等。

4.1 客户端用VIP访问Redis

  在另一台客户端机器,比如172.30.1.20,用VIP登录redis,并使用get命令获取之前设置的[key,value].
[root@localhost redis-2.8.19]# redis-cli -h 172.30.1.15 -p 6379
172.30.1.15:6379> get nosql
"redis"
172.30.1.15:6379>
  再设置一个新的[key,value].
172.30.1.15:6379> set movie ZhanLang2
OK
172.30.1.15:6379> get movie
"ZhanLang2"
172.30.1.15:6379>
  测试结果正常。

4.2 测试VIP漂移

测试之前,先看下那台机器接管这VIP

在172.30.1.22机器查看
[root@localhost ~]# ip a | grep eth1
2: eth1: mtu 1500 qdisc pfifo_fast state UP qlen 1000
    inet 172.30.1.22/24 brd 172.30.1.255 scope global eth1
    inet 172.30.1.15/32 scope global eth1
[root@localhost ~]#
在172.30.1.23查看
[root@localhost ~]#  ip a | grep eth1
2: eth1: mtu 1500 qdisc pfifo_fast state UP qlen 1000
    inet 172.30.1.23/24 brd 172.30.1.255 scope global eth1
[root@localhost ~]#
可见,VIP被172.30.1.22机器接管着。
现在,把172.30.1.22机器上的redis-server干掉,再查看VIP是否还接管着:
[root@localhost ~]# pkill redis-server
[root@localhost ~]# ps -ef | grep redis-server | grep -v grep
root      7372 30964  0 13:57 pts/0    00:00:00 grep redis-server
[root@localhost ~]# ip a | grep eth1
2: eth1: mtu 1500 qdisc pfifo_fast state UP qlen 1000
    inet 172.30.1.22/24 brd 172.30.1.255 scope global eth1
[root@localhost ~]#
可见,172.30.1.22已经没有接管VIP了。
在172.30.1.23查看下是否接管了VIP:
[root@localhost ~]# ip a | grep eth1
2: eth1: mtu 1500 qdisc pfifo_fast state UP qlen 1000
    inet 172.30.1.23/24 brd 172.30.1.255 scope global eth1
    inet 172.30.1.15/32 scope global eth1
[root@localhost ~]#
可见172.30.1.23已经接管了VIP,进入MASTER状态了。
继续测试在VIP下的redis读写:
还是在客户端172.30.1.20下执行
172.30.1.15:6379> get movie
"ZhanLang2"
172.30.1.15:6379> set director WuJing
OK
172.30.1.15:6379>
测试正常,注意,刚刚设置了一个新的[key,value],待会把172.30.1.22上的redis-server起来后,再查询这个新的[key,value]——[director,WuJing].
现在把172.30.1.22上的redis-server启动,keepalived也需要启动,以为检测脚本check_redis.sh检测到redis-server不在时,把keepalived也退出了,确保MASTER角色的让出。
[root@localhost redis-2.8.19]# cd /usr/local/src/redis-2.8.19
[root@localhost redis-2.8.19]# ./src/redis-server redis.conf
[root@localhost redis-2.8.19]#  ps -ef | grep redis-server | grep -v grep
root      7841     1  0 14:25 ?        00:00:00 ./src/redis-server *:6379   
[root@localhost redis-2.8.19]# service keepalived start
Starting keepalived:                                       [  OK  ]
[root@localhost redis-2.8.19]# ip a | grep eth1
2: eth1: mtu 1500 qdisc pfifo_fast state UP qlen 1000
    inet 172.30.1.22/24 brd 172.30.1.255 scope global eth1
    inet 172.30.1.15/32 scope global eth1
[root@localhost redis-2.8.19]#
 
可见,启动redis-server和keepalived后,172.30.1.22又重新接管了VIP,因为172.30.1.22设置的优先级是100比172.30.1.23的优先级99要高。
在客户端172.30.1.20下继续测试redis的读写
先查询刚刚设置的[director,WuJing]
172.30.1.15:6379> get director
"WuJing"
172.30.1.15:6379>
可以查询到,说明数据已经同步过来了
再测试下写数据
172.30.1.15:6379> set piaofang 4billion
OK
172.30.1.15:6379>
可见,写redis也是正常的。
 
OK,现在高可用的基本功能测试已经完成。


 
  
 
  
 
  

参考

官网

http://www.keepalived.org/

https://github.com/acassen/keepalived

博客

http://redisdoc.com/topic/sentinel.html

http://blog.csdn.net/l1028386804/article/details/52578080

http://mdba.cn/2015/03/06/redis%E9%AB%98%E5%8F%AF%E7%94%A8%E6%9E%B6%E6%9E%84-keepalivevip/

 

 
  
 
  
 
  
 
  
 
 

你可能感兴趣的:(高可用系统)