【微服务】第31节:Redis的哨兵模式
创始人
2025-01-07 03:02:23
0

 IT领域往往都是面试造火箭,实际工作拧螺丝。为了更好的应对面试,让大家能拿到更高的offer✉,我们接下来就讲讲“造火箭”的事情🧑‍🚀。

🔥🔥🔥 包括以下几方面🔽 🎈:

🌈 - Redis - 高级:

  • 📛 -Redis主从

  • 🤿 - Redis哨兵(◀️)

  • 🧩 - Redis分片集群

  • 👨‍💻 - Redis数据结构

  • ♻️ - Redis内存回收

  • ✅ - Redis缓存一致性

1.Redis哨兵

主从结构中master节点的作用非常重要,一旦故障就会导致集群不可用。那么有什么办法能保证主从集群的高可用性呢?

1.1.哨兵工作原理

Redis提供了哨兵Sentinel)💂 机制来监控主从集群监控状态,确保集群的高可用性。

1.1.1.哨兵作用

哨兵集群作用原理图:

哨兵的作用如下:

  • 💠状态监控 📹Sentinel 会不断检查您的masterslave是否按预期工作。

  • 💠故障恢复(failover)🔁:如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后会成为slave。

  • 💠状态通知⁉️Sentinel充当Redis客户端的服务发现来源,当集群发生failover时,会将最新集群信息推送给Redis的客户端。

那么问题来了,Sentinel怎么知道一个Redis节点是否宕机呢?

1.1.2.状态监控

Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个节点发送ping命令,并通过实例的响应结果来做出判断:

  • 🔹主观下线(sdown):如果某sentinel节点发现某Redis节点未在规定时间响应,则认为该节点主观下线。

  • 🔹 客观下线(odown):若超过指定数量(通过quorum设置)的sentinel都认为该节点主观下线,则该节点客观下线。quorum值最好超过Sentinel节点数量的一半,Sentinel节点数量至少3台。

如图:

一旦发现master故障,sentinel需要在salve中选择一个作为新的master,选择依据是这样的:

  • 🔹 首先会判断slave节点与master节点断开时间长短,如果超过down-after-milliseconds * 10则会排除该slave节点

  • 🔹 然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举(默认都是1)。

  • 🔹 如果slave-prority一样,则判断slave节点的offset值,越大说明数据越新,优先级越高

  • 🔹 最后是判断slave节点的run_id大小,越小优先级越高(通过info server可以查看run_id)。

对应的官方文档如下:

https://redis.io/docs/management/sentinel/

💡 问题来了,当选出一个新的master后,该如何实现身份切换呢?

大概分为两步:

  • 🔸在多个sentinel中选举一个leader

  • 🔸由leader执行failover

1.1.3.选举leader

首先,Sentinel集群要选出一个执行failover的Sentinel节点,可以成为leader。要成为leader要满足两个条件:

  • ❇️ 最先获得超过半数的投票

  • ❇️ 获得的投票数不小于quorum

而sentinel投票的原则有两条:

  • ➿ 优先投票给目前得票最多的

  • ➿ 如果目前没有任何节点的票,就投给自己

比如有3个sentinel节点,s1s2s3,假如s2先投票:

  • ✴️ 此时发现没有任何人在投票,那就投给自己。s2得1票

  • ✴️ 接着s1s3开始投票,发现目前s2票最多,于是也投给s2s2得3票

  • ✴️ s2称为leader,开始故障转移

不难看出,谁先投票,谁就会称为leader,那什么时候会触发投票呢?

答案是第一个确认master客观下线的人会立刻发起投票,一定会成为leader

OK,sentinel找到leader以后,该如何完成failover呢?

1.1.4.failover

我们举个例子,有一个集群,初始状态下7001为master,7002和7003为slave

假如master发生故障,slave1当选。则故障转移的流程如下:

1)sentinel给备选的slave1节点发送slaveof no one命令,让该节点成为master

2)sentinel给所有其它slave发送slaveof 192.168.150.101 7002 🖥命令,让这些节点成为新master,也就是7002slave节点,开始从新的master上同步数据。

3)最后,当故障节点恢复后会接收到哨兵信号,执行slaveof 🖥192.168.150.101 7002命令,成为slave

1.2.搭建哨兵集群

首先,我们停掉之前的redis集群:

# 老版本DockerCompose docker-compose down  # 新版本Docker docker compose down

资料提供的sentinel.conf 📄文件:

其内容如下:

sentinel announce-ip "192.168.150.101" sentinel monitor hmaster 192.168.150.101 7001 2 sentinel down-after-milliseconds hmaster 5000 sentinel failover-timeout hmaster 60000

说明:

  • 🏳️‍🌈 sentinel announce-ip "192.168.150.101":声明当前sentinel的ip

  • 🏳️‍🌈 sentinel monitor hmaster 192.168.150.101 7001 2:指定集群的主节点信息

    • 🚩 hmaster:主节点名称,自定义,任意写

    • 🚩 192.168.150.101 7001:主节点的ip和端口

    • 🚩2:认定master下线时的quorum

  • 🏳️‍🌈 sentinel down-after-milliseconds hmaster 5000:声明master节点超时多久后被标记下线
  • 🏳️‍🌈 sentinel failover-timeout hmaster 60000:在第一次故障转移失败后多久再次重试

我们在虚拟机的/root/redis目录下新建3个文件夹:s1s2s3:

将课前资料提供的sentinel.conf文件分别拷贝一份到3个文件夹中。

接着修改docker-compose.yaml文件,内容如下:

version: "3.2"  services:   r1:     image: redis     container_name: r1     network_mode: "host"     entrypoint: ["redis-server", "--port", "7001"]   r2:     image: redis     container_name: r2     network_mode: "host"     entrypoint: ["redis-server", "--port", "7002", "--slaveof", "192.168.150.101", "7001"]   r3:     image: redis     container_name: r3     network_mode: "host"     entrypoint: ["redis-server", "--port", "7003", "--slaveof", "192.168.150.101", "7001"]   s1:     image: redis     container_name: s1     volumes:       - /root/redis/s1:/etc/redis     network_mode: "host"     entrypoint: ["redis-sentinel", "/etc/redis/sentinel.conf", "--port", "27001"]   s2:     image: redis     container_name: s2     volumes:       - /root/redis/s2:/etc/redis     network_mode: "host"     entrypoint: ["redis-sentinel", "/etc/redis/sentinel.conf", "--port", "27002"]   s3:     image: redis     container_name: s3     volumes:       - /root/redis/s3:/etc/redis     network_mode: "host"     entrypoint: ["redis-sentinel", "/etc/redis/sentinel.conf", "--port", "27003"]

直接运行命令,启动集群:

docker-compose up -d

运行结果:

我们以s1节点为例,查看其运行日志:

# Sentinel ID is 8e91bd24ea8e5eb2aee38f1cf796dcb26bb88acf # +monitor master hmaster 192.168.150.101 7001 quorum 2 * +slave slave 192.168.150.101:7003 192.168.150.101 7003 @ hmaster 192.168.150.101 7001 * +sentinel sentinel 5bafeb97fc16a82b431c339f67b015a51dad5e4f 192.168.150.101 27002 @ hmaster 192.168.150.101 7001 * +sentinel sentinel 56546568a2f7977da36abd3d2d7324c6c3f06b8d 192.168.150.101 27003 @ hmaster 192.168.150.101 7001 * +slave slave 192.168.150.101:7002 192.168.150.101 7002 @ hmaster 192.168.150.101 7001

可以看到sentinel已经联系到了7001这个节点,并且与其它几个哨兵也建立了链接。哨兵信息如下:

  • ☑️27001Sentinel ID8e91bd24ea8e5eb2aee38f1cf796dcb26bb88acf

  • ☑️27002Sentinel ID5bafeb97fc16a82b431c339f67b015a51dad5e4f

  • ☑️27003Sentinel ID56546568a2f7977da36abd3d2d7324c6c3f06b8d

1.3.演示failover

接下来,我们演示一下当主节点故障时,哨兵是如何完成集群故障恢复(failover)的。

我们连接7001这个master节点,然后通过命令让其休眠60秒,模拟宕机:

# 连接7001这个master节点,通过sleep模拟服务宕机,60秒后自动恢复 docker exec -it r1 redis-cli -p 7001 DEBUG sleep 60

稍微等待一段时间后,会发现sentinel节点触发了failover

1.4.总结

Sentinel的三个作用是什么?

  • 📛集群监控

  • 📛故障恢复

  • 📛状态通知

Sentinel如何判断一个redis实例是否健康?

  • ✅每隔1秒发送一次ping命令,如果超过一定时间没有相向则认为是主观下线(sdown

  • ✅如果大多数sentinel都认为实例主观下线,则判定服务客观下线(odown

故障转移步骤有哪些?

  • ✅首先要在sentinel中选出一个leader,由leader执行failover

  • ✅选定一个slave作为新的master,执行slaveof noone,切换到master模式

  • ✅然后让所有节点都执行slaveof 新master

  • ✅ 修改故障节点配置,添加slaveof 新master

sentinel选举leader的依据是什么?

  • ☑️票数超过sentinel节点数量1半

  • ☑️票数超过quorum数量

  • ☑️一般情况下最先发起failover的节点会当选

sentinel从slave中选取master的依据是什么?

  • ⭕首先会判断slave节点与master节点断开时间长短,如果超过down-after-milliseconds * 10则会排除该slave节点

  • ⭕然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举(默认都是1)。

  • ⭕如果slave-prority一样,则判断slave节点的offset值,越大说明数据越新,优先级越高

  • ⭕最后是判断slave节点的run_id大小,越小优先级越高(通过info server可以查看run_id)。

1.5.RedisTemplate连接哨兵集群(自学)

分为三步:

  • 1)引入依赖

  • 2)配置哨兵地址

  • 3)配置读写分离

1.5.1.引入依赖

就是SpringDataRedis的依赖:

     org.springframework.boot     spring-boot-starter-data-redis 

1.5.2.配置哨兵地址

连接哨兵集群与传统单点模式不同,不再需要设置每一个redis的地址,而是直接指定哨兵地址:

spring:   redis:     sentinel:       master: hmaster # 集群名       nodes: # 哨兵地址列表         - 192.168.150.101:27001         - 192.168.150.101:27002         - 192.168.150.101:27003

1.5.3.配置读写分离

最后,还要配置读写分离,让java客户端将写请求发送到master节点,读请求发送到slave节点。定义一个bean即可:

@Bean public LettuceClientConfigurationBuilderCustomizer clientConfigurationBuilderCustomizer(){     return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED); }

这个bean中配置的就是读写策略,包括四种:

  • MASTER从主节点读取

  • MASTER_PREFERRED:优先从master节点读取,master不可用才读取slave

  • REPLICA:从slave节点读取

  • REPLICA_PREFERRED优先从slave节点读取,所有的slave都不可用才读取master

相关内容

热门资讯

一分钟内幕!科乐吉林麻将系统发... 一分钟内幕!科乐吉林麻将系统发牌规律,福建大玩家确实真的是有挂,技巧教程(有挂ai代打);所有人都在...
一分钟揭秘!微扑克辅助软件(透... 一分钟揭秘!微扑克辅助软件(透视辅助)确实是有挂(2024已更新)(哔哩哔哩);1、用户打开应用后不...
五分钟发现!广东雀神麻雀怎么赢... 五分钟发现!广东雀神麻雀怎么赢,朋朋棋牌都是是真的有挂,高科技教程(有挂方法)1、广东雀神麻雀怎么赢...
每日必看!人皇大厅吗(透明挂)... 每日必看!人皇大厅吗(透明挂)好像存在有挂(2026已更新)(哔哩哔哩);人皇大厅吗辅助器中分为三种...
重大科普!新华棋牌有挂吗(透视... 重大科普!新华棋牌有挂吗(透视)一直是有挂(2021已更新)(哔哩哔哩)1、完成新华棋牌有挂吗的残局...
二分钟内幕!微信小程序途游辅助... 二分钟内幕!微信小程序途游辅助器,掌中乐游戏中心其实存在有挂,微扑克教程(有挂规律)二分钟内幕!微信...
科技揭秘!jj斗地主系统控牌吗... 科技揭秘!jj斗地主系统控牌吗(透视)本来真的是有挂(2025已更新)(哔哩哔哩)1、科技揭秘!jj...
1分钟普及!哈灵麻将攻略小,微... 1分钟普及!哈灵麻将攻略小,微信小程序十三张好像存在有挂,规律教程(有挂技巧)哈灵麻将攻略小是一种具...
9分钟教程!科乐麻将有挂吗,传... 9分钟教程!科乐麻将有挂吗,传送屋高防版辅助(总是存在有挂)1、完成传送屋高防版辅助透视辅助安装,帮...
每日必看教程!兴动游戏辅助器下... 每日必看教程!兴动游戏辅助器下载(辅助)真是真的有挂(2025已更新)(哔哩哔哩)1、打开软件启动之...