羽根が千切れ散っても
分布式缓存(下)
Redis哨兵
slave节点宕机恢复后可以找master节点同步数据,而master节点宕机的话,数据可以通过数据持久化来恢复,但是外界的读操作和写操作此时被阻塞了。
我们希望在Redis主从集群搭建完成后,在Master宕机的情况会有Slave来紧急替换Master完成工作。
哨兵机制和原理
Redis提供了哨兵(Sentinel)机制来实现主从集群的自动故障恢复。哨兵的结构如下:

作用如下:
监控:Sentinel会不断检查您的Master和Slave是否按预期工作
自动故障恢复:如果Master故障,Sentinel会将一个Slave提升为Master。当故障实例恢复后也以新的Master为主
通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端
Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令:
主观下线:如果某Sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线。
客观下线:若超过指定数量(quorum)的Sentinel都认为该实例主观下线,则该实例客观下线。quorum值最好超过Sentinel实例数量的一半。

选择作为新Master的Slave的选择依据如下:
首先会判断Slave节点与master节点断开时间长短,如果超过指定值(
down-after-milliseconds*10)则会排除该Slave节点
然后判断Slave节点的slave-priority值,越小优先级越高,如果是O则永不参与选举
如果slave-prority一样,则判断Slave节点的offset值,越大说明数据越新,优先级越高
最后是判断Slave节点的运行id大小,越小优先级越高。(其实这个时候选哪个都一样没啥区别)
当选中了其中一个Slave为新的Master后(例如Slave1),故障的转移的步骤如下:
Sentinel给备选的Slave1节点发送
slaveof no one命令,让该节点成为Master
Sentinel给所有其它Slave发送slaveof 127.0.0.1 7002命令,让这些Slave成为新Master的从节点,开始从新的Master上同步数据。
最后,Sentinel将故障节点标记为Slave,当故障节点恢复后会自动成为新的Master的Slave节点

RedisTemplate的哨兵模式
在Sentinel集群监管下的Redis主从集群,其节点会因为自动故障转移而发生变化,Redis的客户端必须感知这种变化及时更新连接信息。Spring的RedisTemplate底层利用lettuce实现了节点的感知和自动切换。
首先在Redis配置文件pom.xml中引入Redis的starter依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
在配置文件application.yml中设置sentinel的相关信息(注意是sentinel)
spring:redis:sentinel:master:mymaster # 指定master名称nodes: # 指定redis-sentinel集群信息- 127.0.0.1:27001- 127.0.0.1:27002- 127.0.0.1:27003
配置主从读写分离
@Bean
public LettuceClientConfigurationBuilderCustomizer ConfigurationBuilderCustomizer() {return configBuilder -> configBuilder.readFrom (ReadFrom.REPLICA_PREFERRED);
}
这里的ReadFrom是配置Redis的读取策略,是一个枚举,包括下面选择:
MASTER:从主节点读取
MASTER_PREFERRED:优先从Master节点读取,Master不可用才读取replica
REPLICA: 从Slave (replica) 节点读取
REPLICA_PREFERRED:优先从Slave (replica)节点读取,所有的Slave都不可用才读取Master
该配置类含义是:优先从Slave读取数据,如果从节点不可用,则回退到Master读取。
Redis分片集群
主从和哨兵可以解决高可用、高并发读的问题。但是依然有两个问题没有解决:
海量数据存储问题
高并发写的问题。
使用分片集群可以解决上述问题,分片集群特征:
集群中有多个Master,每个Master保存不同数据
每个Master都可以有多个Slave节点
Master之间通过ping监测彼此健康状态
客户端请求可以访问集群任意节点,最终都会被转发到正确节点
Redis分片集群的JAVA配置和用法同哨兵机制比起来只有配置文件存在差异:
spring:redis:cluster:nodes: # 指定分片集群的每一个节点信息- 127.0.0.1:7001- 127.0.0.1:7002- 127.0.0.1:7003- 127.0.0.1:8001- 127.0.0.1:8002- 127.0.0.1:8003
