当系统中只有一台redis运行时,一旦该redis挂了,会致使整个系统没法运行。php
单个实例css
因为单台redis出现单点故障,就会致使整个系统不可用,因此想到的办法天然就是备份(通常工业界认为比较安全的备份数应该是3份
)。当一台redis出现问题了,另外一台redis能够继续提供服务。git
备份github
虽然上面redis作了备份,看上去很完美。但因为redis目前只支持主从复制备份(不支持主主复制
),当主redis挂了,从redis只能提供读服务,没法提供写服务。因此,还得想办法,当主redis挂了,让从redis升级成为主redis。redis
这就须要自动故障转移,redis sentinel带有这个功能,当一个主redis不能提供服务时,redis sentinel能够将一个从redis升级为主redis,并对其余从redis进行配置,让它们使用新的主redis进行复制备份。vim
自动故障转移c#
1.环境安全
这里使用三台服务器,每台服务器上开启一个redis-server和redis-sentinel服务,redis-server端口为8000,redis-sentinel的端口为6800,修改默认端口是安全的第一步_。bash
redis-server说明服务器
192.168.56.101:8000 主
192.168.56.102:8000 从
192.168.56.103:8000 从
redis-sentinel说明
192.168.56.101:6800
192.168.56.102:6800
192.168.56.103:6800
2.搭建redis系统
首先下载安装redis
wget http://download.redis.io/releases/redis-3.2.8.tar.gz tar zxvf redis-3.2.8.tar.gzcd redis-3.2.8 makecd src#复制redis相关命令到/usr/sbin目录下,这样就能够直接执行这些命令,不用写全路径sudo cp redis-cli redis-server redis-sentinel /usr/sbin/
在redis目录下有redis.conf和sentinel.conf配置文件示例,使用sudo cp redis.conf sentinel.conf /etc/
命令将两个配置文件复制到/etc目录下(固然也能够在/etc/目录新建配置文件),而后修改配置文件。
修改主redis-server配置文件内容以下:
port 8000 #修改端口是安全的第一步daemonize yesbind 0.0.0.0 pidfile /var/run/redis-8000.pid logfile /var/log/redis/redis-8000.log
修改从redis-server配置文件内容以下:
port 8000 #修改端口是安全的第一步daemonize yesbind 0.0.0.0 pidfile /var/run/redis-8000.pid logfile /var/log/redis/redis-8000.log slaveof 192.168.56.101 8000 #从redis比主redis多这一行
启动redis-server。
sudo redis-server /etc/redis.conf
三个redis服务启动完毕后,进入命令行,执行info replication查看当前主从配置。
主节点上查看主从信息
发现并无从节点信息。
3.主从间没法通讯
这里的缘由是防火墙屏蔽了8000端口,须要修改防火墙设置,开放8000端口(同理redis-sentinel的6800端口)。
# 打开防火墙配置文件,增长8000端口sudo vim /etc/sysconfig/iptables#修改完后,须要重启防火墙sudo service iptables restart
增长8000端口和6800端口
而后从新进入主节点,查看主从信息,能够发现两个从节点信息,代表redis-server主从已经配置完毕。
主节点上查看主从信息
4.搭建redis-sentinel系统
redis-sentinel程序上面已经安装过了,这里只须要修改配置文件就能够了。修改/etc/sentinel.conf,若是没有建立便可。
修改sentinel.conf配置文件内容以下:
daemonize yes port 6800logfile /var/log/redis/sentinel.log pidfile /var/run/sentinel.pid sentinel monitor master8000 192.168.56.101 8000 2#5秒内master6800没有响应,就认为SDOWNsentinel down-after-milliseconds master8000 5000 sentinel failover-timeout master8000 15000
启动redis-sentinel。
redis-sentinel /etc/sentinel.conf
三个redis-sentinel服务启动完毕后,链接任意sentinel服务能够获知当前主redis服务信息。
sentinel监控状态
1.把住redis停掉
redis-cli -h 192.168.56.101 -p 8000 shutdown
2.查看redis-sentinel的监控状态
sentinel监控状态
发现102这台redis-server提高为主库。
至此,redis的高可用方案已经搭建完成。
客户端程序(如PHP程序)链接redis时须要ip和port,但redis-server进行故障转移时,主redis是变化的,因此ip地址也是变化的。客户端程序如何感知当前主redis的ip地址和端口呢?redis-sentinel提供了接口,请求任何一个sentinel,发送SENTINEL get-master-addr-by-name <master name>
就能获得当前主redis的ip和port。
获取当前主redis的ip和port
客户端每次链接redis前,先向sentinel发送请求,得到主redis的ip和port,而后用返回的ip和port链接redis。
这种方法的缺点是显而易见的,每次操做redis至少须要发送两次链接请求,第一次请求sentinel,第二次请求redis。
php请求sentinel程序代码可参见:https://github.com/huyanping/redis-sentinel
更好的办法是使用VIP,固然这对配置的环境有必定的要求,好比redis搭建在阿里云服务器上,可能不支持VIP。
VIP方案是,redis系统对外始终是同一ip地址,当redis进行故障转移时,须要作的是将VIP从以前的redis服务器漂移到如今新的主redis服务器上。
好比:当前redis系统中主redis的ip地址是192.168.56.101,那么VIP(192.168.56.250)指向192.168.56.101,客户端程序用VIP(192.168.56.250)地址链接redis,实际上链接的就是当前主redis,这样就避免了向sentinel发送请求。
当主redis宕机,进行故障转移时,192.168.56.102这台服务器上的redis提高为主,这时VIP(192.168.56.250)指向192.168.56.102,这样客户端程序不须要修改任何代码,链接的是192.168.56.102这台主redis。
VIP指向192.168.56.101
故障转移后,VIP漂移指向192.168.56.102
那么如今的问题是,如何在进行redis故障转移时,将VIP漂移到新的主redis服务器上。
这里可使用redis sentinel的一个参数client-reconfig-script,这个参数配置执行脚本,sentinel在作failover的时候会执行这个脚本,而且传递6个参数<master-name>、 <role>、 <state>、 <from-ip>、 <from-port>、 <to-ip> 、<to-port>,其中<to-ip>是新主redis的IP地址,能够在这个脚本里作VIP漂移操做。
sentinel client-reconfig-script master8000 /opt/notify_master6800.sh
修改三个服务器的redis-sentinel配置文件/etc/sentinel.conf,增长上面一行。而后在/opt/目录下建立notify_master6800.sh脚本文件,这个脚本作VIP漂移操做,内容以下:
#notify_master6800.sh脚本内容#!/bin/bashMASTER_IP=$6 #第六个参数是新主redis的ip地址LOCAL_IP='192.168.56.101' #其余两个服务器上为192.168.56.102,192.168.56.103VIP='192.168.56.250'NETMASK='24'INTERFACE='eth1'if [ ${MASTER_IP} = ${LOCAL_IP} ];then /sbin/ip addr add ${VIP}/${NETMASK} dev ${INTERFACE} #将VIP绑定到该服务器上 /sbin/arping -q -c 3 -A ${VIP} -I ${INTERFACE} exit 0else /sbin/ip addr del ${VIP}/${NETMASK} dev ${INTERFACE} #将VIP从该服务器上删除 exit 0fiexit 1 #若是返回1,sentinel会一直执行这个脚本
如今当前主redis是192.168.56.102,须要手动绑定VIP到该服务器上。
/sbin/ip addr add 192.168.56.250/24 dev eth1 /sbin/arping -q -c 3 -A 192.168.56.250 -I eth1
而后,去另外一个服务器上经过VIP地址链接redis-server和redis-sentinel。
经过VIP链接redis
从上面也能够看出当前主redis是192.168.56.102。
下面关闭这台redis服务,看看VIP是否漂移到另外一台服务器上。
redis-cli -h 192.168.56.102 -p 8000 shutdown
经过查询sentinel发现192.168.56.103提高为主。
经过访问VIP链接redis,发现VIP确实指向了192.168.56.103。
经过上面的操做,使用redis主从 + 哨兵(sentinel)+ 漂移VIP的方案搭建了一个redis高可用系统,但这个系统保证的是单个redis实例的高可用,因此适合业务比较小的应用。若是业务比较大,并发量比较高,建议搭建redis集群,好比官方redis cluster,还有开源的codings集群。
另外,漂移VIP可使用keepalived软件来实现,这里就很少介绍了。