2019.04.30 丨 壹佰案例

基于腾讯云CVM自建高可用Redis实践

2019.04.30 丨 壹佰案例

本文来源 | 云+社区专栏文章

作者  | 万守兵,腾讯云资深架构师。8年以上大型互联网公司运维工作经验,腾讯云资深迁云架构师,一直从事大型互联网服务端架构设计和优化工作。个人专注于云计算、k8s和 DevOps领域。



导读:在企业实际生产环境中为了能够给业务上层应用提供高可靠、低延迟、低数据损失的Redis缓存服务,本文通过对目前主流的几种redis高可用方案进行对比分析,并基于腾讯云CVM和HAVIP等基础产品进行搭建、配置、测试、总结,供大家参考。



01环境说明


1.需求与目标


本文将通过对目前主流的几种redis高可用方案进行对比分析,并基于腾讯云CVM和HAVIP等基础产品进行搭建、配置、测试、总结。


2.软件版本


redis用3.2.8版本,keepalived用1.2.19版本。


3.基本环境


采用同一网络内的三台主机(可以是物理主机、虚拟机或docker容器),要求三台主机之间都能相互访问。我这里使用腾讯云上3台CVM,每台CVM上开启一个redis-server、redis-sentinel和keepalived服务,redis-server端口为6379,redis-sentinel的端口为26379(我这里用默认端口,生产环境中可以修改默认端口),3台CVM上都安装keepalived服务。


role

IP

port

redis-master1

172.16.2.4

6379

redis-master2

172.16.2.2

6379

redis-master3

172.16.2.15

6379

redis-sentinel1

172.16.2.4

26379

redis-sentinel2

172.16.2.2

26379

redis-sentinel3

172.16.2.15

23679


02几种redis高可用方案说明


1.一般的主从复制方案


由于redis目前只支持主从复制备份(不支持主主复制),当主redis挂了,从redis只能提供读服务,无法提供写服务。所以,还得想办法,当主redis挂了,让从redis升级成为主redis。


优点:

(1)实现了对master数据的备份,一旦master出现故障,slave节点可以提升为新的master,顶替旧的master继续提供服务


(2)实现读扩展。使用主从复制架构, 一般都是为了实现读扩展。Master主要实现写功能,  Slave实现读的功能


缺点:

(1)一旦主节点宕机,从节点晋升成主节点,同时需要修改应用方的主节点地址,还需要命令所有从节点去复制新的主节点,整个过程需要人工干预,此时需要经过如下操作(假设提升Slave1为Master):


  • 在Slave1上执slaveof no one命令提升Slave1为新的Master节点

  • 在Slave1上配置为可写,这是因为大多数情况下,都将slave配置只读

  • 告诉Client端(也就是连接Redis的程序)新的Master节点的连接地址

  • 配置Slave2从新的Master进行数据复制


(2)主节点的写能力受到单机的限制


(3)主节点的存储能力受到单机的限制


2.sentinel高可用方案


客户端程序(如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 Sentinel 端口和 Redis 主节点均需要开放访问权限。如果前端业务使用 Java,有 JedisSentinelPool 可以复用;如果前端业务使用 PHP,可以在 phpredis 的基础上做二次封装。


优点:

(1)redis sentinel带有自动故障转移功能(failover),当一个主redis不能提供服务时,redis sentinel可以将一个从redis升级为主redis,并对其他从redis进行配置,让它们使用新的主redis进行复制备份;


(2)服务探测故障及时;


(3)DBA 维护成本低。


缺点:

(1)对应用有入侵性:客户端每次连接redis前,先向sentinel发送请求,获得主redis的ip和port,然后用返回的ip和port连接redis。每次操作redis至少需要发送两次连接请求,第一次请求sentinel,第二次请求redis;


(2)Sentinel服务器和Redis节点需要开放访问权限。


3.redis-sentinel+VIP方案+自定义脚本方案


底层是Redis Sentinel 集群,代理着 Redis 主从,Web端通过VIP提供服务。在部署Redis主从的时候,需要将虚拟IP绑定到当前的Redis 节点。当主节点发生故障,比如机器故障、Redis节点故障或者网络不可达,Sentinel 集群会调用 client-reconfig-script 配置的脚本,将VIP漂移到新的主节点上。


比如:当前redis系统中主redis的ip地址是172.16.2.4,那么VIP(172.16.2.250)指向172.16.2.4,客户端程序用VIP(172.16.2.250)地址连接redis,实际上连接的就是当前主redis,这样就避免了向sentinel发送请求。


优点:

(1)脚本自定义,架构可控;


(2)对应用透明,当主redis宕机,进行故障转移时,192.168.56.102这台服务器上的redis提升为主,这时VIP(172.16.2.4)指向192.168.56.102,这样客户端程序不需要修改任何代码,连接的是192.168.56.102这台主redis;


(3)秒级切换,在 5s 内完成整个切换操作.


缺点:

(1)使用VIP增加维护成本,存在IP混乱风险;


(2)需要自行编写VIP切换脚本,需要通过ip addr手动先在主redis上配置vip,配置相对复杂;


(3)Sentinel模式存在短时间的服务不可用;


(4)应用场景局限于内网,例如部分业务只能通过外网访问Redis时,该方案不可用


注意:

VIP方案对配置的环境有一定的要求,在腾讯云上搭建redis,需要用到腾讯云HAVIP,文档见:https://cloud.tencent.com/document/product/215/18025



4.redis-sentinel+keepalived方案


keepalived通过vrrp_script检测当前主机上的redis-server是否以master状态运行,如果当前主机上的redis-server正在以master状态运行,则将vrrp_instance标记为存活状态,并分配VIP;如果当前主机上的redis-server正在以slave状态运行,则将vrrp_instance标记为错误状态。当某台主机宕机后,其他两台主机上的keepalived会将VIP切换到新的master(当前主机上的redis-server正在以master状态运行)上。


优点:

(1)相对redis-sentinel+VIP方案,不需编写VIP切换脚本,配置更简洁、清晰;


(2)对应用透明;


(3)秒级切换。


缺点:

(1)对网络环境有要求:keepalived的核心协议VRRP使用IP多播数据包进行封装,组地址为224.0.0.18,发布范围只限于同一局域网内,而且在网络不受自己控制时基本不能用,但是腾讯云是支持组播协议,可以使用keepalived;


(2)存在脑裂;


(3)Sentinel模式存在短时间的服务不可


注意:

keepalived方案也需要一个VIP,且网络要能支持组播协议。



03安装部署

方案一:sentinel高可用方案


1.首先下载安装redis:http://download.redis.io/releases/

$ wget http://download.redis.io/releases/redis-3.2.8.tar.gz

$ tar -zxvf redis-3.2.8.tar.gz

$ cd redis-3.2.8

$ make (如果没有安装gcc会报错,所以强烈建议在make之前先yum install gcc先安装gcc)

make报错如下:(make是用来编译的,从Makefile中读取指令,安装到指定的位置)

make3: gcc: Command not found

make3: * net.o Error 127

make3: Leaving directory `/opt/redis-3.2.8/deps/hiredis'

make2: * hiredis Error 2

make2: Leaving directory `/opt/redis-3.2.8/deps'

make1: persist-settings Error 2 (ignored)

CC adlist.o

/bin/sh: cc: command not found

make1: * adlist.o Error 127

make1: Leaving directory `/opt/redis-3.2.8/src'

make: * all Error 2

安装gcc:

yum install gcc

继续编译:

make

Make报错如下:

make1: Entering directory `/opt/redis-3.2.8/src'

CC adlist.o

In file included from adlist.c:34:0:

zmalloc.h:50:31: fatal error: jemalloc/jemalloc.h: No such file or directory

#include <jemalloc/jemalloc.h>

^

compilation terminated.

make1: * adlist.o Error 1

make1: Leaving directory `/opt/redis-3.2.8/src'

make: * all Error 2

重新编译:

make MALLOC=libc

编译成功!!!

2.基本配置:

(1)make完后 redis-3.2.8目录下会出现编译后的redis服务程序redis-server,还有用于测试的客户端程序redis-cli,两个程序位于安装目录 src 目录下:

复制redis相关命令到/usr/sbin目录下,这样就可以直接执行这些命令,不用写全路径。

$ cd src

$ cp redis-cli  redis-server  redis-sentinel   /usr/sbin/

(2)在redis目录下有redis.conf和sentinel.conf配置文件示例,将两个配置文件复制到/etc目录下(当然也可以在/etc/目录新建配置文件),然后修改配置文件

$ cp  redis.conf  sentinel.conf  /etc/

(3)redis.conf 是一个默认的配置文件。我们可以根据需要修改配置文件


●修改主redis-server(172.16.2.4)配置文件内容如下:

#不修改,使用默认端口

port  6379  

#修改为0.0.0.0,可以从外部连接redis服务端    

bind  0.0.0.0

#默认情况下redis运行在保护模式(这种模式下,访问不需要密码),但是这种模式只允许本地回路访问,这里改为no

protected-mode no

#默认情况下,redis不是在后台模式运行的,如果需要在后台进程运行,把该项的值更改为yes,默认为no

daemonize yes

#redis服务以后台进程运行的时候,Redis默认会把pid写入/var/run/redis.pid文件组

pidfile /var/run/redis.pid

#开启AOF持久化,默认是关闭的,RDB默认是开启的,但是AOF的优先级更高,启动时Redis 会优先载入 AOF 文件来恢复数据,与 RDB 相比,AOF 的实时性更好,因此已成为主流的持久化方案

#如果不希望丢掉任何一条数据的话就该用纯累加模式:一旦开启这个模式,Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件。

appendonly yes


● 修改从redis-server(172.16.2.2和172.16.2.15)配置文件内容如下:

#不修改,使用默认端口

port  6379  

#修改为0.0.0.0,可以从外部连接redis服务端    

bind  0.0.0.0

#默认情况下redis运行在保护模式(这种模式下,访问不需要密码),但是这种模式只允许本地回路访问,这里改为no

protected-mode no

#默认情况下,redis不是在后台模式运行的,如果需要在后台进程运行,把该项的值更改为yes,默认为no

daemonize yes

#redis服务以后台进程运行的时候,Redis默认会把pid写入/var/run/redis.pid文件组,改为yes

pidfile /var/run/redis.pid

#开启AOF持久化,默认是关闭的,RDB默认是开启的,但是AOF的优先级更高,启动时Redis 会优先载入 AOF 文件来恢复数据,与 RDB 相比,AOF 的实时性更好,因此已成为主流的持久化方案

#如果不希望丢掉任何一条数据的话就该用纯累加模式:一旦开启这个模式,Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件。

appendonly yes

#从redis比主redis多这一行,使用slaveof实现主从复制

slaveof  172.16.2.4 6379

● 启动redis服务之前,建议先修改kernel参数,重启生效

vim /etc/sysctl.conf

#表示内核允许分配所有的物理内存,而不管当前的内存状态如何

vm.overcommit_memory = 1

#定义了TCP全连接队列长度,默认128太小,启动redis服务会报错

net.core.somaxconn = 511
#使配置文件永久生效

sysctl -p

(4)启动redis-server服务:

$ redis-server &        #加上‘&’号使redis以后台程序方式运行



$ redis-server /etc/redis.conf   #通过指定配置文件启动,在生产环境中强烈建议使用这种方式启动服务

(5)停止:

使用客户端:

$ redis-cli shutdown

因为Redis可以妥善处理SIGTERM信号,所以直接kill -9也是可以的

$ kill -9 PID

(6)启动redis服务进程后,就可以使用测试客户端程序redis-cli和redis服务交互了,连接redis-server:

$ redis-cli   #本地连接redis-server,如果要连接远程redis,redis-cli -h host -p port -a password

redis> set key1 value1

OK

redis> get key1

"value1"

(7)查看主从状态:

通过redis-cli 进入主redis命令行,执行info replication查看当前主从配置,可以发现两个从节点信息,表明redis-server主从已经配置完毕。

redis>  INFO replication

查看redis主从关系已经建立


● 可能遇到的问题:redis主从建立失败,有可能是启动服务时没有指定正确的配置文件

● 解决思路:

(1)通过ps -ef查看服务进程ID

(2)通过lsof -p pid查看进程打开的文件,如果打开文件有误,通过redis-server /etc/redis.conf指定正确的配置文件重新启动服务

(8)搭建redis-sentinel系统:

redis-sentinel程序上面已经安装过了,这里只需要修改配置文件就可以了。修改/etc/sentinel.conf如下:

● 三台sentinel服务器配置都一致

#当前Sentinel服务运行的端口

port 26379

#监控的master的名字叫做mymaster(自定义),地址为172.16.2.4:6379,行尾最后的一个2代表在sentinel集群中,多少个sentinel认为masters死了,才能真正认为该master不可用了

sentinel monitor mymaster 172.16.2.4 6379 2  

#每个Sentinel节点都要定期PING命令来判断Redis数据节点和其余Sentinel节点是否可达,如果超过30秒且没有回复,则判定不可达

sentinel down-after-milliseconds mymaster 30000

#当Sentinel节点集合对主节点故障判定达成一致时,Sentinel领导者节点会做故障转移操作,选出新的主节点,原来的从节点会向新的主节点发起复制操作,限制每次向新的主节点发起复制操作的从节点个数为1,在从Redis实例较多的情况下这个数字越小,同步的时间越长,完成故障转移所需的时间就越长  

sentinel parallel-syncs mymaster 1

#failover过期时间,当failover开始后,在此时间内仍然没有触发任何failover操作,当前sentinel将会认为此次failover失败。默认180秒,即3分钟。

sentinel failover-timeout mymaster 18000  

#如果Sentinel监控的主节点配置了密码,可以通过sentinel auth-pass配置通过添加主节点的密码,防止Sentinel节点无法对主节点进行监控。

#例如:sentinel auth-pass mymaster MySUPER--secret-0123passw0rd

sentinel auth-pass  

#在故障转移期间,当一些警告级别的Sentinel事件发生(指重要事件,如主观下线,客观下线等)时,会触发对应路径的脚本,想脚本发送相应的事件参数。

# 例如:sentinel notification-script mymaster /var/redis/notify.sh

sentinel notification-script  

#在故障转移结束后,触发应对路径的脚本,并向脚本发送故障转移结果的参数。

#例如:sentinel client-reconfig-script mymaster /var/redis/reconfig.sh

sentinel client-reconfig-script  

● 常见问题:在172.16.2.4(主redis)上查看sentinel的信息,发现报错

查看sentinel服务报错


● 解决方案:修改/etc/sentinel.conf文件

#原因是sentinel没有指定bind和密码访问,所以被开启了protected-mode保护模式,拒绝其他sentinel的连接。导致进入了ODWON。在sentinel.conf里加入关闭保护,protected-mode no

protected-mode no
#指定文件启动sentinel服务

redis-sentinel sentinel.conf  &

3.测试验证:

(1)基本连接测试:

redis-cli -h host -p port info sentinel

三个redis-sentinel服务启动完毕后,连接任意sentinel服务可以获知当前主redis服务信息,说明sentinel服务已经成功起来

查看sentinel服务已经启动


(2)测试sentinel的failover故障切换功能:

● 把主redis(172.16.2.4)停掉

redis-cli -h 172.16.2.4 -p 6379 shutdown

● 查看redis-sentinel的监控状态:

 redis-cli -h 172.16.2.4 -p 26379 info sentinel

查看sentinel信息发现master已经切换为172.16.2.2


● 发现172.16.2.2这台redis-server提升为主:

  redis-cli -h 172.16.2.2 -p 6379 info replication

在master上查看主从状态


● 控制台也输出相关信息,表示主从切换成功。

控制台log,redis主从切换成功


● 172.16.2.2切换成主之后,也可以执行写操作了。至此,redis的sentinel方案已经搭建完成。

确认当前主可以执行写操作


4.客户端使用方式:

客户端程序(如PHP程序)连接redis时需要ip和port,但redis-server进行故障转移时,主redis是变化的,所以ip地址也是变化的。客户端程序如何感知当前主redis的ip地址和端口呢?redis-sentinel提供了接口,请求任何一个sentinel,发送SENTINEL get-master-addr-by-name<master name>就能得到当前主redis的ip和port。

● 连接到sentinel获取当前主redis的ip和端口(因为又执行了一次切换,这里的主已经切换到172.16.2.15,这里只是说明客户端的使用方式)

客户端程序连接方式

方案二:redis-sentinel+vip方案


1.方案说明


VIP方案是redis系统对外始终是同一ip地址,当redis主从进行故障转移时,需要做的是将VIP从之前的redis服务器漂移到现在新的主redis服务器上。

比如:当前redis系统中主redis的ip地址是172.16.2.4,那么VIP(172.16.2.250)指向172.16.2.4,客户端程序用VIP(172.16.2.250)地址连接redis,实际上连接的就是当前主redis,这样就避免了向sentinel发送请求。


● 正常情况下VIP指向172.16.2.4

正常情况下VIP指向172.16.2.4


● 故障情况下,VIP漂移指向172.16.2.2

master故障情况下,VIP自动漂移指向172.16.2.2


2.基本配置:

那么现在的问题是,如何在进行redis故障转移时,将VIP漂移到新的主redis服务器上。在方案一的配置基础之上增加对sentinel.conf的配置,具体配置如下:

(1)在sentinel.conf配置文件设置要执行的vip漂移的脚本

使用sentinel.conf配置文件的有一个参数client-reconfig-script,这个参数配置执行脚本,sentinel在做failover的时候会执行这个脚本,并且传递6个参数<master-name>、 <role>、 <state>、 <from-ip>、 <from-port>、 <to-ip> 、<to-port>,其中<to-ip>是新主redis的IP地址,可以在这个脚本里做VIP漂移操作。

#修改三个服务器的redissentinel配置文件etcsentinelconf,增加下面一行。

vi etcsentinelconf

sentinel clientreconfigscript mymaster   optnotify_mymastersh

(2)创建VIP漂移脚本(VIP用之前在腾讯云控制台上申请的VIP)

然后在/opt/目录下创建notify_mymaster.sh脚本文件,这个脚本做VIP漂移操作。

chmod  notify_mymastersh #赋予脚本执行权限

脚本内容如下:

#notify_mymastersh脚本内容

#binbash

MASTER_IP$  #第六个参数是新主redis的ip地址

LOCAL_IP  #其他两个服务器上为

VIP

NETMASK

INTERFACE

  $MASTER_IP  $LOCAL_IP then   

   sudo sbinip  addr  add $VIP$NETMASK  dev $INTERFACE  #将VIP绑定到该服务器上

   sudo sbinarping q c  A $VIP I $INTERFACE

   exit 

 

  sudo sbinip  addr del  $VIP$NETMASK  dev $INTERFACE   #将VIP从该服务器上删除

  exit 

fi

exit   #如果返回,sentinel会一直执行这个脚本

(3)第一次需在主redis上手工设置VIP

只需要第一次手工在主redis上设置vip,现在当前主redis是172.16.2.2,需要手动绑定VIP到该服务器上。注意强烈建议加sudo执行

sudo /sbin/ip  addr add 172.16.2.250/24 dev eth0
sudo /sbin/arping -q   -c 3 -A 172.16.2.250 -I eth0

3.测试验证

(1)配置完成之后,去另一个服务器上(172.16.2.15)通过VIP地址连接redis-server和redis-sentinel。从上面可以看到主redis是172.16.2.2

VIP成功绑定在master 172.16.2.2上


(2)验证:下面关闭这台主redis服务(172.16.2.2),看看VIP是否漂移到另一台服务器上

redis-cli -h 172.16.2.2 -p 6379 shutdown

通过查询sentinel发现172.16.2.15提升为主。

sentinel自动failover,将172.16.2.15提升为master


(3)通过访问VIP连接查看redis sentinel信息和redis-server主从关系,发现VIP确实指向了172.16.2.15

通过VIP成功查看sentinel状态


通过VIP成功查看redis的状态

方案三:redis-sentinel+keepalived方案


1.方案说明


VIP方案是通过sentinel服务在做redis主从切换的时候,通过配置文件sentinel.conf中的一个参数client-reconfig-script来执行相应的脚本,这种方式需要自己编写脚本。而keepalived方案通过vrrp_script检测当前主机上的redis-server是否以master状态运行,如果当前主机上的redis-server正在以master状态运行,则将vrrp_instance标记为存活状态,并分配VIP;如果当前主机上的redis-server正在以slave状态运行,则将vrrp_instance标记为错误状态。当某台主机宕机后,其他两台主机上的keepalived会将VIP切换到新的master(当前主机上的redis-server正在以master状态运行)上。三台CVM都需要安装keepalived组件


2.在VIP方案基础之上安装keepalived组件(3台CVM都需要安装)

wget c httpwwwkeepalivedorgsoftwarekeepalivedtargz     

tar zxf keepalivedtargz     

cd keepalived     

configure prefixusrlocalkeepalived     

make     

make install

3.基本配置

(1)编译安装keepalived之后,做初始化

 cp usrlocalkeepalivedsbinkeepalived usr

 cp usrlocalkeepalivedetcsysconfigkeepalived etc

 cp usrlocalkeepalivedetcrcdinitdkeepalived etc

 cd etc

 chkconfig add keepalived

 chkconfig keepalived on

 mkdir p etckeepalived

(2)关于keepalived的配置文件

keepalived的配置文件默认是没有的,当然sample&example文件还是有的,通常在PREFIX/etc/sample目录下。

keepalived master和backup(backups)之间不同的是:

优先级的不同,master的优先级priority的数字要高一些,我这里主redis上设置为,从redis上设置为;

global_defs段的router_id都不一样,实际中可以用任意名字区分也可以用主机名区分;

backup的配置文件中还有一个nopreempt字段,意思是设置为非抢占模式,作用是让master优先获取到VIP,并保证VIP是在原先的master上。

● 主redis172.16.2.4上的配置:

 vim /etc/keepalived/keepalived.conf
 Configuration File  keepalived

global_defs 

   notification_email      #指定keepalived在发生切换时需要发送email到的对象,一行一个

     root@localhost

   

   notification_email_from keepalived@localhost     #指定发件人

   smtp_server         #指定smtp服务器地址

   smtp_connect_timeout       #指定smtp连接超时时间

   router_id keepalivedha_1     #运行keepalived机器的一个标识



vrrp_script chk_http_port      #执行的脚本

    script 

    interval 

    timeout 

    fall 

    rise 



vrrp_sync_group VG_1       #监控多个网段的实例

    group 

        VI_1        #实例名

    



vrrp_instance VI_1 

    state BACKUP

           #设置实例绑定的网卡

    #use_vmac keepalived

    #vmac_xmit_base

    mcast_src_ip 

    smtp_alert

    virtual_router_id         #路由器标识,MASTER和BACKUP必须是一致的

    priority         #优先级,高优先级竞选为master

    advert_int 

    authentication         #设置认证

        auth_type PASS      #认证方式

        auth_pass password      #认证密码

    

    virtual_ipaddress      #设置vip

        

    

    track_script       #监测的对象

        chk_http_port

● 从redis172.16.2.2上的配置:

 Configuration File  keepalived

global_defs 

   notification_email 

     root@localhost

   

   notification_email_from keepalived@localhost

   smtp_server 

   smtp_connect_timeout 

   router_id keepalivedha_2



vrrp_script chk_http_port 

    script 

    interval 

    timeout 

    fall 

    rise 



vrrp_sync_group VG_1 

    group 

        VI_1

    



vrrp_instance VI_1 

    state BACKUP

     

    #use_vmac keepalived

    #vmac_xmit_base

    mcast_src_ip 

    smtp_alert

    virtual_router_id 

    priority 

    advert_int 

    authentication 

        auth_type PASS

        auth_pass password

    

    virtual_ipaddress 

        

    

    track_script 

        chk_http_port

    

        nopreempt

● 从redis172.16.2.15上的配置:

 Configuration File  keepalived

global_defs 

   notification_email 

     root@localhost

   

   notification_email_from keepalived@localhost

   smtp_server 

   smtp_connect_timeout 

   router_id keepalivedha_3



vrrp_script chk_http_port 

    script 

    interval 

    timeout 

    fall 

    rise 



vrrp_sync_group VG_1 

    group 

        VI_1

    



vrrp_instance VI_1 

    state BACKUP

     

    #use_vmac keepalived

    #vmac_xmit_base

    mcast_src_ip 

    smtp_alert

    virtual_router_id 

    priority 

    advert_int 

    authentication 

        auth_type PASS

        auth_pass password

    

    virtual_ipaddress 

        

    

    track_script 

        chk_http_port

    

        nopreempt

4.启动keepalived

service keepalived start

tail logmessages

(1)如果在主redis上keepalived启动后日志如下图显示则表示启动成功

keepalived日志输出


(2)用ip add查看VIP已经绑定到主redis上

查看vip地址已经绑定


5.测试验证

模拟主redis故障时,redis的set、get和复制情况

(1)停掉主Redis(172.16.2.4)上的redis-server服务

停掉主Redis(172.16.2.4)上的redis-server服务


(2)主Redis(172.16.2.4)上的VIP已经被移除

主Redis(172.16.2.4)上的VIP已经被移除


(3)查看Redis(172.16.2.15)上的Redis状态已经切换成master

查看Redis(172.16.2.15)上的Redis状态已经切换成master


(4)可以看出,VIP已经漂移到新的redis master(172.16.2.15)上

可以看出,VIP已经漂移到新的redis-server master了


(5)从sentinel进行redis主从切换,到VIP的漂移过程是需要时间的,用ping VIP来做测试,中断时间大概需要几秒左右,如下图所示:


04总结


以上通过搭建、配置、验证、测试,了解到几种redis高可用方案各有优缺点,如果网络环境能够支持组播协议,建议采用redis-sentinel+keepalived方案,这种方案配置更简单;如果网络环境不支持组播协议,可以使用redis-sentinel+VIP方案;如果业务代码上能够接受在每次操作redis之前都先额外进行一次sentinel查询操作,就可以采用sentinel方案。


以下是实战过程中总结出的最佳实践:


(1)Redis Sentinel 集群建议使用 >= 5 台机器;


(2)不同的大业务可以使用一套 Redis Sentinel 集群,代理该业务下的所有端口;


(3)根据不同的业务划分好 Redis 端口范围;


(4)自定义脚本建议采用 Python 实现,扩展便利;


(5)自定义脚本传入参数:<service_name> <role> <comment> <from_ip> <from_port> <to_ip> <to_port>;


(6)自定义脚本需要远程 ssh 操作机器,建议使用 paramiko 库,避免重复建立 SSH 连接,消耗时间;


(7)加速 SSH 连接,建议关闭以下两个参数:

UseDNS no

GSSAPIAuthentication no


(8)微信或者邮件告警,建议 fork 一个进程,避免主进程阻塞;


(9)自动切换和故障切换,所有操作建议在 15s 以内完成。


以上几种方案都是针对单个redis实例的高可用,比较适合中小型业务的应用。如果业务数据量比较大,并发量比较高的情况下,建议搭建redis集群,比如官方redis cluster和开源的codis方案,或者使用腾讯云PAAS层redis集群方案,文档说明见:

https://cloud.tencent.com/document/product/239。

媒体联系

票务咨询:赵丹丹 15802217295

赞助咨询:郭艳慧 13043218801

媒体支持:景    怡 13920859305

提交需求