Redis主从架构哨兵模式
文章目录
- 概述
- 一、主从搭建实例
- 二、主从同步原理
- 三、哨兵架构
- 3.1、搭建哨兵架构
- 3.2、演示故障恢复
- 3.3、哨兵日志
概述
在生产环境下,Redis通常不会单机部署,为了保证高可用性,通常使用主从模式
或集群架构
,同时也面临着一些问题:
- 集群的拓扑结构
- 主节点和从节点各自负责的工作
- 主节点和从节点如何保证数据的一致性,如何同步数据
- 主节点发生故障,从节点如何感知到并且重新选举主节点,达到自动切换的目的
集群通常会使用一主多从
或主 - 从 - 从
的架构:
为了缓解主从复制风暴
的问题,可以使用主 - 从 - 从
的架构,即从节点也承担一些同步数据的工作:
主节点通常负责处理用户的写请求
,从节点处理用户的读请求
。
一、主从搭建实例
简单地搭建一个主从架构,从节点的两个作用:给用户读取数据,同步数据。
- 复制一份配置文件,并且修改文件中的关键信息
修改端口
修改从节点的PID
修改日志名
修改数据存放目录
表明主节点
配置从节点只读
- 启动从节点
- 连接从节点
- 观察到从节点的数据,和主节点是同步的
二、主从同步原理
主要分为全量复制
和增量复制
两部分:
- 从节点第一次启动,会全量复制主节点的所有数据。从节点根据配置文件中的replicaof 主节点ip 主节点端口,获取主节点的信息
- 向主节点发送
psync
命令请求同步 - 同时建立socket长连接
- 向主节点发送
- 主节点接收到命令,使用
bgsave
命令生成接收到命令这一刻
的rdb文件。(和配置文件有没有开启rdb是没有关系的,配置文件的是被动rdb,即符合配置的策略才会进行,而这里是服务端发起的主动rdb)- 生成rdb的过程中,有可能产生新的命令,因为是
bgsave
不阻塞的,放入一个repl buffer
缓存中。 - 将rdb发给从节点
- 生成rdb的过程中,有可能产生新的命令,因为是
- 从节点清理掉旧数据,重新加载rdb数据。
- 主节点将
repl buffer
缓存中的命令发给从节点。 - 从节点执行
repl buffer
缓存中的命令到内存。 - 主节点持续通过socket连接将后续命令发送给从节点。
除了从节点第一次连接主节点触发的全量同步
,还可能存在一种情况,从节点和主节点断开连接一段时间,然后又重新连接上了主节点,例如在断开前,主节点最新数据为10,从节点的数据也同步到了10。但是从节点和主节点断开了连接。等到从节点再次连接上时,主节点的最新数据变成了20。此时触发的就应该是增量同步,主节点向从节点同步11-20之间的数据:
- 从节点重新建立socket长连接
- 主节点有一个缓存区,
repl backlog buffer
记录最近写命令的缓存。(可以在配置文件中配置,默认大小为1M。缓存满了之后会刷新掉) - 从节点将同步数据的偏移量
psync(offset)
发给主节点,(断开连接之前,从节点在主节点同步了10条数据,而此时主节点有了20条数据) - 主节点根据偏移量,从缓冲区找命令
- 能找到,将offest之后的命令,都同步给从节点
- 找不到,说明断开的时间太长了,就全量同步
主节点和从节点的同步,是通过缓存区 + rdb的方式
实现的,如果同一时刻主节点需要生成快照复制给大量的从节点,那么对于性能的损失较大,这种场景也称为主从同步风暴
,可以通过使用主 - 从 - 从
架构的方式缓解。
三、哨兵架构
哨兵架构是指,在主从架构上,使用哨兵集群
去进行监控。普通的主从架构,主节点挂了,需要手动操作
更换从节点为主节点,让其他从节点去复制。在哨兵架构下则可以自动恢复
。哨兵去监听主节点和从节点,当主节点挂了,哨兵去重新选举主节点。
客户端访问的是哨兵,但是哨兵可以监控到所有节点。哨兵会将主节点的信息推送给客户端,相当于客户端还是和主节点通信。
3.1、搭建哨兵架构
哨兵架构的搭建:
- 复制一份redis目录下的sentinel.conf文件,并且修改配置
端口号,文件目录,pid等
设置有多少个sentinel认为master失效时,master才算真正失效,才能开启新的选举
- 哨兵也推荐集群部署(3台),可以复制上面的配置文件,对于端口号等信息进行对应的修改,然后启动哨兵:
目前的架构:
- 6379:主节点
- 6380:从节点1
- 6381:从节点2
- 26379:哨兵节点1
- 26380:哨兵节点2
- 26381:哨兵节点3
3.2、演示故障恢复
案例工程:配置信息
server:port: 8080spring:redis:database: 0timeout: 3000sentinel: #哨兵模式master: mymaster #主服务器所在集群名称nodes: 192.168.101.128:26379,192.168.101.128:26380,192.168.101.128:26381
# cluster:
# nodes: 192.168.101.128:8001,192.168.101.128:8002,192.168.101.128:8003,192.168.101.128:8004,192.168.101.128:8005,192.168.101.128:8006lettuce:pool:max-idle: 50min-idle: 10max-active: 100max-wait: 1000
案例工程,访问/test_sentinel
接口,每隔1s向redis中存入一条数据
@RestController
public class IndexController {private static final Logger logger = LoggerFactory.getLogger(IndexController.class);@Autowiredprivate StringRedisTemplate stringRedisTemplate;/*** 测试节点挂了哨兵重新选举新的master节点,客户端是否能动态感知到** @throws InterruptedException*/@RequestMapping("/test_sentinel")public void testSentinel() throws InterruptedException {int i = 1;while (true){try {stringRedisTemplate.opsForValue().set("test"+i, i+""); //jedis.set(key,value);System.out.println("设置key:"+ "test" + i);i++;Thread.sleep(1000);}catch (Exception e){logger.error("错误:", e);}}}}
连接虚拟机上的redis,需要开放端口或者关闭防火墙,否则报图上的错误:
启动程序,不断地向redis中塞值:
将主节点的进程关闭:
6379主节点
断开连接
观察哨兵重新选举:
6381
被设置成了新的主节点,可以通过info命令
查询
6380从节点
的新主节点为6381:
如果旧的主节点恢复运行了,会变成从节点:
3.3、哨兵日志
通过哨兵日志的部分信息,可以体现出监控集群
和重新选举
的过程:
# 哨兵监控到主节点下线
44861:X 25 Jun 2025 21:52:18.410 # +sdown master mymaster 192.168.101.128 6379
# 标记主节点为不可用,quorum 2/2表示至少有两个哨兵认定了主节点为不可用,可以下定论为主节点下线。
44861:X 25 Jun 2025 21:52:18.505 # +odown master mymaster 192.168.101.128 6379 #quorum 2/2
# 发起一次新的选举周期
44861:X 25 Jun 2025 21:52:18.506 # +new-epoch 1
# 启动故障转移,将会选举新的主节点。
44861:X 25 Jun 2025 21:52:18.506 # +try-failover master mymaster 192.168.101.128 6379
# 投票给67638d61e36685f6509df1622f17bb60041dbabb 节点
44861:X 25 Jun 2025 21:52:18.507 # +vote-for-leader 67638d61e36685f6509df1622f17bb60041dbabb 1
# 哨兵集群中的其他两个节点,都投票给67638d61e36685f6509df1622f17bb60041dbabb 节点
44861:X 25 Jun 2025 21:52:18.509 # cf6af8e65382739aa40cd0407e8a3d8f0e122d06 voted for 67638d61e36685f6509df1622f17bb60041dbabb 1
44861:X 25 Jun 2025 21:52:18.509 # 191cb89148e07d0e79a5ded4fcfe8320ae976b5a voted for 67638d61e36685f6509df1622f17bb60041dbabb 1
# 67638d61e36685f6509df1622f17bb60041dbabb 成为新的主节点,并获得领导者身份。
44861:X 25 Jun 2025 21:52:18.566 # +elected-leader master mymaster 192.168.101.128 6379
# 选择一个从节点作为主节点
44861:X 25 Jun 2025 21:52:18.566 # +failover-state-select-slave master mymaster 192.168.101.128 6379
# 选择从节点 192.168.101.128:6381 作为新的主节点。
44861:X 25 Jun 2025 21:52:18.659 # +selected-slave slave 192.168.101.128:6381 192.168.101.128 6381 @ mymaster 192.168.101.128 6379
# 新的主节点 192.168.101.128:6381 会停止同步原来的主节点,并准备成为独立的主节点。
44861:X 25 Jun 2025 21:52:18.659 * +failover-state-send-slaveof-noone slave 192.168.101.128:6381 192.168.101.128 6381 @ mymaster 192.168.101.128 6379
# 等待新的主节点完成晋升过程。
44861:X 25 Jun 2025 21:52:18.721 * +failover-state-wait-promotion slave 192.168.101.128:6381 192.168.101.128 6381 @ mymaster 192.168.101.128 6379
# 192.168.101.128:6381 成为新的主节点,完成晋升。
44861:X 25 Jun 2025 21:52:18.785 # +promoted-slave slave 192.168.101.128:6381 192.168.101.128 6381 @ mymaster 192.168.101.128 6379
# 将其他从节点重新配置,使其从新的主节点同步数据。
44861:X 25 Jun 2025 21:52:18.785 # +failover-state-reconf-slaves master mymaster 192.168.101.128 6379
# mymaster 恢复到正常状态,移除其不可用状态。
44861:X 25 Jun 2025 21:52:19.675 # -odown master mymaster 192.168.101.128 6379
#将 192.168.101.128:6380 配置为从新的主节点同步。
44861:X 25 Jun 2025 21:52:19.802 * +slave-reconf-inprog slave 192.168.101.128:6380 192.168.101.128 6380 @ mymaster 192.168.101.128 6379
# 192.168.101.128:6380 完成了重新配置,开始从新的主节点同步。
44861:X 25 Jun 2025 21:52:19.802 * +slave-reconf-done slave 192.168.101.128:6380 192.168.101.128 6380 @ mymaster 192.168.101.128 6379
# 故障转移过程完成,192.168.101.128:6381 成为新的主节点,集群恢复正常。
44861:X 25 Jun 2025 21:52:19.894 # +failover-end master mymaster 192.168.101.128 6379
# 原来的主节点 192.168.101.128:6379 被替换为新的主节点 192.168.101.128:6381。
44861:X 25 Jun 2025 21:52:19.894 # +switch-master mymaster 192.168.101.128 6379 192.168.101.128 6381
# 6380 6379 作为从节点,从6381进行同步
44861:X 25 Jun 2025 21:52:19.894 * +slave slave 192.168.101.128:6380 192.168.101.128 6380 @ mymaster 192.168.101.128 6381
44861:X 25 Jun 2025 21:52:19.894 * +slave slave 192.168.101.128:6379 192.168.101.128 6379 @ mymaster 192.168.101.128 6381