Redis HA官方提供两种方案,Cluster(分片)及Sentinel(哨兵模式),这里仅介绍Sentinel配置及使用。两者不冲突,实际可同时使用。
Sentinel优势如下:
- 监控(Monitoring): 不断检查主从服务器是否运行正常
- 通知(Notification) : 被监控的某个redis服务器出现问题时,可通过api通知管理员或其他应用程序
- 自动故障迁移(Automatic Failover): 当主服务器不能正常工作时,失效主服务器的其中一台从服务器升级为新的主服务器,失效主服务器的其他从服务器从属于新主服务器;客户端尝试连接失效主服务器时,集群返回客户端新的主服务器地址,保证可用性
Redis集群搭建
Redis Sentinel方案至少需一个Master节点,两个Slave节点,三个Sentinel,本例Redis版本号为3.2.10,使用六个节点,拓扑结构如下:
配置文件
redis-6379.conf
|
|
注:Redis有两种持久化方式,Snapshot(rdb)和Append-only file(aof)。可使用其中一种方式,也可以两种都使用。
rdb方式的持久化通过快照完成,即符合一定条件时redis会自动将内存中的所有数据存储到rdb文件中。相对aof方式,rdb文件更小,数据恢复快,但是会丢失最后一次snapshot后更改的所有数据,如果容忍数据丢失,可采用这种方式。
本例对应配置参数为
dbfilename “dump-6379.rdb”aof方式,redis默认不开启,aof方式是以追加的方式将所有写操作命令写入到磁盘文件.aof中,所以文件会越来越大,redis重启的恢复时间较长,为了缓解这种问题,redis使用了BGREWRITEAOF,用于删除重复多余的写命令,是一个占用一定系统资源的background进程(redis自行触发),因为rewrite的时候会删除旧的AOF文件,如果AOF文件比较大的话,会消耗更多的系统资源,好处就是数据一般不会丢失。
本例对应配置参数为
appendonly yes
appendfilename appendonly.aof
redis-6380.conf
|
|
redis-6381.conf
|
|
sentinel-36379.conf
|
|
sentinel-36380.conf和sentinel-36381.conf配置(除sentinel节点端口和日志文件名)与sentinel-36379.conf配置相同。
其他参数备注,本例不使用:
验证
root模式下
启动主从节点
|
|
此时从属关系如下图
登入主从节点,查看主从状态如下图
启动sentinel
启动三个sentinel,可用两种方式,如
redis sentinel部署完成后,sentinel配置文件发生如下变化:
- sentinel节点自动发现了从节点、其余Sentinel节点
- 去掉了默认配置,如:parallel-syncs、failover-timeout
- 新添加了参数,如epoch
此时查看sentinel-36379.conf配置文件如下
故障转移实验
干掉主节点后,查看sentinel节点监控的主节点信息,如下图,可以看到,节点6381成为主节点
查看从节点信息如下图,原本的主节点(端口6379)已经断开了连接
重启端口为6379的数据节点后,查看从节点信息,可以看到6379节点复活,不过此时已经降级为端口6381的从节点,如下图
延迟测试
同一网段下的其他机器连接redis,平均耗时为2ms, 如下所示:
通过如下命令可查看当前连接数及配置的最大连接数
Springboot 接入
开始接入
依赖
|
|
配置示例
配置从哪里读取无所谓,本例的配置从apollo读取,如下图:
Java类配置类
RedisCon
|
|
RedisConfig
|
|
至此,完成集群配置及接入。
调用封装类:RedisUtil
|
|
问题备注
1.使用redis作为session,需在logback.xml中更改日志级别不为debug,否则有日志打印过多的报警
2.若构建RedisConnectionFactory Bean时(即RedisConfig类的redisConnectionFactory方法)不加 jedisConnectionFactory.afterPropertiesSet();,那么在连接redis时,抛异常Cannot get Jedis connection; nested exception is java.lang.NullPointerException。
查源码,从JedisSentinelPool类的构造函数追溯,被JedisConnectionFactory类的createRedisSentinelPool方法调用,逐步向上推,最后可得关键方法afterPropertiesSet(),源码如下:
3.本地window开发环境没有问题,linux环境启动报错如下
解决:
①.查看linux系统主机名,shell输入hostname返回tencent_QA_test11
②.查看/etc/hosts文件中是否有127.0.0.1对应主机名,如果没有则添加
扩展
1.以上RedisCon的配置从配置中心apollo获取;也可以从K8s Secret获取,首先注释掉@EnableApolloConfig(value = “RedisCon”),然后读取secret文件内容,加载到内存中,启动SpringBoot服务:
2.以上服务通过哨兵节点连接自建Redis;若Redis使用云服务(如腾讯云),哨兵地址内部封装,不对外提供,仅提供数据节点地址,配置类更改如下