前言
redis是一个高性能的缓存数据库。现在越来越多的被当做缓存服务器使用。本文将带着大家从零开始,逐步搭建出一个高可用的redis缓存服务器。本文先从redis主从复制说起,然后介绍sentinel哨兵模式,最后再说一下VIP漂移实现故障切换。
准备
本文示例中使用了3台服务器,当然了都是虚拟服务器。如果有不了解如何搭建本地服务器的同学,请移步到使用vagrant+virtualBox 搭建本地虚拟服务器。
至于linux上如何安装redis,请各位同学自行解决了。
redis主从复制架构
-
redis-server说明
master: 192.168.33.30 slave: 192.168.33.80 slave: 192.168.33.90
-
因为redis默认是只能本机访问的,如果需要远程访问并且需要密码,需要修改如下配置:
> ① vi /etc/redis.conf 进入redis配置文件,找到下面两行,默认是注释掉的,去掉注释。
> ② bind 127.0.0.1 改成:bind 0.0.0.0
> ③ foobared 替换成你要设置的密码,如:123456>注意:3台服务器中redis配置文件都要修改。
# bind 127.0.0.1 # requirepass foobared
改好后应该是:
bind 0.0.0.0 requirepass "123456"
最后重启redis服务即可。
-
redis主从复制配置
-
编辑两台从机的redis配置文件,进入redis.conf,找到
# slaveof
,
默认是注释掉的,去掉注释,填写自己的主机ip和端口号。如下:slaveof 192.168.33.30 6379
-
因为主机设置了密码,所以还需要找到
# masterauth
这一行,去掉注释,然后填入主机的密码。masterauth 123456
-
修改好两台从机的redis.conf文件后,重启redis服务。然后随便进入主机和从机的redis-cli,进入后输入:
INFO replication
可以看到当前机器的redis是什么角色,及其他一些信息。 -
从机上可以看到当前角色role:slave(从),master_host:连接的主机地址和master_port:端口,master_link_status:连接状态。
主机上可以看到当前角色role:master(主),connected_slave:连接的从机个数,slave0、slave1从机地址、端口和从机状态,如果有
多个从机,依次类推,slave2,slave3… -
然后在主机set个值,看看从机能否取到:
如上图,在主机
set moba 666
,可以看到两台从机上都能取到值。注意:
-
从库只有读取的能力,不具备写入数据的能力,如果写入数据会报错误。
-
第一个从库设置连接主库,第二从库可以设置连接第一个从库,第三个从库可以设置连接第二个从库,依次类推。
-
减少主库连接的压力,还可以关掉主库的持久化功能,把持久化的功能交给从库进行处理。
-
sentinel 哨兵模式
自动故障转移
因为Redis目前只支持主从复制备份,不支持主主复制,万一当主Redis挂了,就失去了写入数据能力,因为从Redis只能提供读服务,无法提供写服务。所以当主Redis挂了时,就得让从Redis升个官成为主Redis。
这就需要自动故障转移,Redis Sentinel就具备这个功能,当一个主Redis挂了时,Redis Sentinel可以将一个从Redis升级为主Redis,并对其他从Redis进行配置,让它们使用新的主Redis进行复制。
>需要注意的是:搭建sentinel最好有3台服务器。所以一开始推荐搭建准备好3台虚拟服务器。
Redis Sentinel主要功能
-
监控:哨兵不断的检查master和slave是否正常的运行。
-
通知:当监控的某台Redis实例发生问题时,可以通过API通知系统管理员和其他的应用程序。
-
自动故障转移:当一个master没有在运行了,哨兵可以启动一个故障转移进程,将一个slave升级成为master,其他的slave被重新配置使用新的master,并且应用程序使用Redis服务端通知的新地址。
在 默认情况下,每个Sentinel节点会以每秒一次的频率对Redis节点和其它的Sentinel节点发送PING命令,并通过节点的回复来判断节点是否在线。
如果在down-after-millisecondes毫秒内,没有收到有效的回复,则会判定该节点为主观下线。
如果该节点为master,则该Sentinel节点会通过sentinel is-master-down-by-addr命令向其它sentinel节点询问对该节点的判断,如果超过个数的节点判定master不可达,则该sentinel节点会将master判断为客观下线。
这个时候,各个Sentinel会进行协商,选举出一个领头Sentinel,由该领头Sentinel对master节点进行故障转移操作。
故障转移包含如下三个操作:- 在所有的slave服务器中,挑选出一个slave,并将其转换为master。
- 让其它slave服务器,改为复制新的master。
- 将旧master设置为新master的slave,这样,当旧的master重新上线时,它会成为新master的slave。
搭建 redis sentinel
-
这里还是使用三台服务器。
redis-server说明:192.168.33.30:6379 主 192.168.33.80:6379 从 192.168.33.90:6379 从
redis-sentinel说明
192.168.33.30:26379 192.168.33.80:26379 192.168.33.90:26379
每台服务器上都要开启redis-server和redis-sentinel服务。
-
redis配置文件修改
redis.conf上面我们已经说过了。这里只需要修改redis-sentinel.conf即可。
要做故障自动转移,首先在所有的redis.conf中设置masterauth,因为自动故障只 会重写主从关系,不会自动写入masterauth。当然了,如果原先没有设置密码,忽略即可。vi /etc/redis-sentinel.conf
进入配置文件,修改如下:
sentinel monitor mymaster 192.168.33.30 6379 2 sentinel auth-pass mymaster "123456" sentinel down-after-milliseconds mymaster 10000 sentinel failover-timeout mymaster 15000
配置说明:
① sentinel monitor mymaster 192.168.33.30 6379 2
Sentinel监视一个名为mymaster的主redis实例,主实例的IP地址为192.168.33.30,端口号为6379,而将这个主实例判断为失效至少需要2个 Sentinel进程的同意,只要同意Sentinel的数量不达标,自动failover就不会执行。
② sentinel down-after-milliseconds mymaster 10000
指定了Sentinel认为Redis实例已经失效所需的毫秒数。当实例超过该时间没有返回PING,或者直接返回错误,那么Sentinel将这个实例标记为主观下线。只有在足够数量的Sentinel都将一个实例标记为主观下线之后,实例才会被标记为客观下线,这时自动故障迁移才会执行。
③ sentinel failover-timeout mymaster 15000
如果在该时间(单位:ms)内未能完成failover操作,则认为该failover失败。
④ sentinel notification-script :指定sentinel检测到该监控的redis实例指向的实例异常时,调用的报警脚本。后面会用到此配置项最后重新启动redis-sentinel
service redis-sentinel restart
在任意一台服务器查看相关信息:
然后试一下故障转移是否有效,把主redis关闭,再查看下sentinel的监控信息:
可以看到从库:192.168.33.90:6379 已经变为主库。
漂移VIP实现Redis故障转移
说明
程序中连接redis需要知道ip和端口号port,但是redis服务进行故障转移时,主redis是变化的,不是固定不变的,所以ip地址是变化的。那故障转移后,程序如何知道当前新的主redis的ip地址和端口号呢?redis-sentinel其实是提供了接口,在请求任何一个Sentinel,都会发送SENTINEL get-master-addr-by-name 就能得到当前主Redis的ip和port。
程序中每次连接Redis前,先向sentinel发送请求,获得主Redis的ip和port,然后用返回的ip和port连接Redis。但是使用这种方法,每次操作Redis至少需要发送两次连接请求,第一次请求Sentinel,第二次请求Redis。
VIP漂移就是,Redis对外始终都是同一ip地址,当Redis进行故障转移时,只要将VIP从之前的Redis服务器漂移到现在新的主Redis服务器上即可。
举个例子:当前主Redis的ip地址是192.168.33.30,那么VIP(188.180.0.98)指向192.168.33.30,程序中用VIP(188.180.0.98)地址连接Redis,实际上连接的就是当前主Redis,这样就能避免向Sentinel发送请求。
而且当主Redis宕机,进行故障转移时,192.168.33.90这台服务器上的Redis成为主redis,这个时候VIP(188.180.0.98)指向192.168.33.90,这样程序中就不需要修改任何的代码,依然能连接当前的主redis 192.168.33.90。
具体操作
使用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漂移操作。
在3台服务器的redis-sentinel配置文件/etc/redis-sentinel.conf中加上上面这行。然后到/var/redis目录下创建recfg.sh脚本文件,可根据需要放到别的目录下也行。脚本内容如下:
#!/bin/bash
MASTER_IP=${6} #新主redis的ip地址
LOCAL_IP='192.168.33.30' #当前服务器IP,主机192.168.33.30,从机192.168.33.80,192.168.33.90
VIP='188.180.0.98'
NETMASK='24'
INTERFACE='eth1'
if [ ${MASTER_IP} = ${LOCAL_IP} ]; then
sudo /sbin/ip addr add ${VIP}/${NETMASK} dev ${INTERFACE} #将VIP绑定到该服务器上
sudo /sbin/arping -q -c 3 -A ${VIP} -I ${INTERFACE}
exit 0
else
sudo /sbin/ip addr del ${VIP}/${NETMASK} dev ${INTERFACE} #将VIP从该服务器上删除
exit 0
fi
exit 1 #如果返回1,sentinel会一直执行这个脚本
最后别忘了修改这个脚本的权限。
还需要注意的事需要手动绑定VIP到当前主redis服务器上。
/sbin/ip addr add 172.16.2.250/24 dev eth1
/sbin/arping -q -c 3 -A 172.16.2.250 -I eth1
然后重启redis和Sentinel。在其中一台从服务器上使用VIP访问主redis和sentinel。
一切正常。
关闭主redis服务,查验VIP能否漂移到其他服务器上。
然后再使用VIP访问redis:
图中可看到主redis的ip地址已经从192.168.33.30变为192.168.33.90,说明漂移成功。
结束
至此,高可用redis:主从复制、Sentinel哨兵模式、VIP漂移故障切换已完成。