当前位置: 首页 > news >正文

【Redis从入门到精通】第44篇:Sentinel启动与监控——它是怎么盯着主服务器的

上一篇【第43篇】Redis Sentinel——主从集群的守门员
下一篇【第45篇】主观下线和客观下线——Sentinel怎么判断主库挂了


上一篇我们认识了Sentinel的功能和配置,但还有一个核心问题没回答:Sentinel到底是怎么"盯着"主库的?它是怎么发现从库的?Sentinel之间又是怎么互相认识的?今天我们深入源码级别,拆解Sentinel的启动初始化和信息收集机制。

一、Sentinel初始化的5个步骤

当你执行redis-sentinel sentinel.conf时,Sentinel的启动过程分为5步:

┌───────────────────────────────────────────────────┐ │ Sentinel 启动初始化流程 │ ├───────────────────────────────────────────────────┤ │ │ │ ① 初始化Redis服务器基础结构 │ │ (和普通Redis启动一样:加载配置、初始化数据结构) │ │ │ │ │ ▼ │ │ ② 将普通Redis服务器代码替换为Sentinel专用代码 │ │ (换命令表、关闭RDB/AOF、换定时器函数) │ │ │ │ │ ▼ │ │ ③ 初始化Sentinel专用状态 │ │ (创建sentinelState结构体) │ │ │ │ │ ▼ │ │ ④ 根据sentinel.conf中的配置,初始化主库列表 │ │ (创建sentinelRedisInstance) │ │ │ │ │ ▼ │ │ ⑤ 创建到主库的命令连接和订阅连接 │ │ (开始监控) │ │ │ └───────────────────────────────────────────────────┘

步骤②非常关键——Sentinel把普通Redis服务器的命令表换掉了。普通Redis支持几百个命令,而Sentinel只支持几个:

普通Redis命令表: Sentinel命令表: ┌─────────────┐ ┌─────────────┐ │ GET │ │ PING │ │ SET │ │ SENTINEL │ │ HSET │ │ SUBSCRIBE │ │ LPUSH │ │ UNSUBSCRIBE │ │ ZADD │ │ PSYNC │ │ ... (200+) │ │ PUBLISH │ │ │ │ INFO │ └─────────────┘ └─────────────┘ (仅7个)

二、sentinelState与sentinelRedisInstance——核心数据结构

Sentinel的内部状态主要通过两个C结构体管理:

sentinelState(Sentinel全局状态)

structsentinelState{charmyid[CONFIG_RUN_ID_SIZE+1];/* 当前Sentinel的运行ID */uint64_tcurrent_epoch;/* 当前纪元(用于Raft选举)*/dict*masters;/* 主库字典:key=主库名, value=sentinelRedisInstance */inttilt;/* 是否进入TILT模式 */intrunning_scripts;/* 正在执行的脚本数量 */mstime_ttilt_start_time;/* TILT模式开始时间 */mstime_tprevious_time;/* 上次执行时间处理器的时间 */list*scripts_queue;/* 待执行脚本队列 */};

sentinelRedisInstance(被监控的Redis实例)

typedefstructsentinelRedisInstance{intflags;/* 实例状态标志:SRI_MASTER/SRI_SLAVE/SRI_SENTINEL等 */char*name;/* 实例名称 */char*runid;/* 实例的运行ID */uint64_tconfig_epoch;/* 配置纪元 */sentinelAddr*addr;/* 实例地址:IP + 端口 */mstime_tdown_after_period;/* 主观下线超时时间 */intquorum;/* 客观下线所需票数 */intparallel_syncs;/* 故障转移后同时同步的从库数 */mstime_tfailover_timeout;/* 故障转移超时时间 *//* 主库专用字段 */dict*sentinels;/* 监控该主库的其他Sentinel */dict*slaves;/* 该主库的从库 */intfailover_state;/* 故障转移状态 */intfailover_state_change_time;/* 状态变更时间 *//* 从库专用字段 */sentinelRedisInstance*master;/* 指向主库实例 */mstime_tmaster_link_down_time;/* 与主库断开的时长 *//* 连接相关 */redisAsyncContext*cc;/* 命令连接 */redisAsyncContext*pc;/* 订阅连接 */mstime_tlast_pub_time;/* 上次发布消息时间 */mstime_tlast_pong_time;/* 上次收到PONG时间 */}sentinelRedisInstance;

关键字段解读:

字段说明
flags实例类型和状态,如SRI_MASTERSRI_SLAVESRI_S_DOWN(主观下线)
name主库有名字(sentinel.conf中定义),从库和Sentinel用ip:port作为名字
runid实例的运行ID,空则表示还未获取到
addr实例的IP和端口
quorum触发客观下线的最少Sentinel数

三、Sentinel发现从库:INFO命令的妙用

Sentinel初始只知道主库的地址,从库是它通过INFO命令"发现"的。

Sentinel Master │ │ │ ─── INFO replication ────→ │ 每10秒发送一次 │ │ │ ←── # Replication ────── │ │ role:master │ │ connected_slaves:2 │ │ slave0:ip=192.168.1.102, │ │ port=6380,state=online │ │ slave1:ip=192.168.1.103, │ │ port=6381,state=online │ │ │ │ (解析INFO输出,发现2个从库) │ │ (为每个从库创建sentinelRedisInstance)│ │ (建立到从库的命令连接+订阅连接) │

解析INFO输出后,Sentinel会:

  1. 提取每个从库的IP和端口
  2. 检查该从库是否已经在自己的slaves字典中
  3. 如果不在,创建新的sentinelRedisInstance并建立连接

踩坑提示:从库的IP地址由主库的INFO输出决定。如果从库配置了replica-announce-ip,Sentinel使用该IP;否则使用从库与主库建立连接时的IP。在Docker/NAT环境中,可能需要显式配置replica-announce-ipreplica-announce-port,否则Sentinel可能连接不到从库。

四、Sentinel互相发现:sentinel:hello频道

Sentinel之间通过主库的发布/订阅频道__sentinel__:hello互相发现:

Sentinel 1 Master Sentinel 2 │ │ │ │ 订阅 __sentinel__:hello │ │─────────────────→│←────────────────│ │ │ │ 订阅 __sentinel__:hello │ │ │ │ 发布 HELLO消息 │ │ │─────────────────→│ │ │ │ 转发 ──────────→│ │ │ │ │ │ ←──── 发布HELLO │ │ ←──── 转发 ─────│ │ │ │ │ │ (互相发现!) │ │

Sentinel每2秒向__sentinel__:hello频道发送一条消息,包含:

消息格式: __sentinel__:hello <sentinel_ip> <sentinel_port> <sentinel_runid> <sentinel_epoch> <master_name> <master_ip> <master_port> <master_epoch>

收到其他Sentinel的消息后:

  1. 如果该Sentinel不在自己的sentinels字典中,添加它
  2. 更新已知Sentinel的信息(IP、端口、epoch等)

五、Sentinel的连接管理

对于每个被监控的主库,Sentinel建立两个连接

Sentinel ─────────────────────→ Master │ │ │ ┌─── 命令连接 (Command Connection) ───┐ │ │ 用途:发送INFO、PING、SENTINEL命令 │ │ └────────────────────────────────────┘ │ │ │ ┌─── 订阅连接 (Subscription Connection) ┐ │ │ 用途:订阅__sentinel__:hello频道 │ │ └─────────────────────────────────────┘

为什么需要两个连接?因为Redis的发布/订阅机制中,一个连接进入订阅状态后就只能执行SUBSCRIBE/UNSUBSCRIBE/PSUBSCRIBE/PUNSUBSCRIBE命令,不能发其他命令。

完整连接关系图:

┌─────────────┐ │ Sentinel │ │ :26379 │ └──┬───┬───┬──┘ │ │ │ ┌──────────┘ │ └──────────┐ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Master │ │ Slave 1 │ │ Slave 2 │ │ 6379 │ │ 6380 │ │ 6381 │ └──────────┘ └──────────┘ └──────────┘ 2个连接 2个连接 2个连接 (cmd+sub) (cmd+sub) (cmd+sub) 另外,Sentinel还会与其他Sentinel建立命令连接 (不需要订阅连接,因为通过主库的频道通信) ┌─────────────┐ │ Sentinel │ │ :26379 │ └──┬───────┬──┘ │ │ ┌─────┘ └─────┐ ▼ ▼ ┌──────────┐ ┌──────────┐ │Sentinel 2│ │Sentinel 3│ │ :26380 │ │ :26381 │ └──────────┘ └──────────┘ 1个连接(cmd) 1个连接(cmd)

六、Sentinel的信息更新频率

Sentinel定期向所有被监控的实例发送命令,频率如下:

目标命令频率说明
主库INFO每10秒发现从库、获取主从状态
从库INFO每10秒确认从库角色和状态
所有实例PING每1秒检测是否在线
主库PUBLISH每2秒__sentinel__:hello发布自身信息
所有SentinelSENTINEL is-master-down-by-addr按需询问其他Sentinel是否认为主库下线
Sentinel 的时间线(1秒精度): 0s 1s 2s 3s ... 10s 11s ... 20s │ │ │ │ │ │ │ PING PING PING PUBLISH PING PING PING all all all hello all all all │ │ │ │ │ │ │ │ │ │ │ INFO │ INFO │ │ │ │ master│ master │ │ │ │ &slaves &slaves

七、TILT模式——Sentinel的自我保护

如果Sentinel检测到系统时间异常(比如系统时间被修改、进程被暂停),它会进入TILT模式

正常模式 TILT模式 ┌──────────────────┐ ┌──────────────────┐ │ 正常监控 │ 时间异常 │ 停止故障转移 │ │ 正常检测下线 │ ────────→ │ 只执行PING/INFO │ │ 可以执行故障转移 │ │ 不做下线判断 │ └──────────────────┘ └──────────────────┘ 持续30秒正常后退出TILT

进入TILT的原因:

  • 两次时间处理器调用之间的时间差为负数或超过2秒
  • 说明系统可能出现进程暂停(如虚拟机暂停、容器冻结)

踩坑提示:在Kubernetes中,如果Pod的CPU被严重限制,可能导致Sentinel进入TILT模式。确保Sentinel有足够的CPU资源。

总结

Sentinel的监控机制是一个精密的信息收集网络:通过INFO发现从库,通过发布/订阅频道发现其他Sentinel,通过PING检测存活状态。每个连接都有明确用途,每种消息都有固定频率。理解这些机制,有助于排查Sentinel的监控盲区和误判问题。

下一篇,我们将深入Sentinel最核心的判断逻辑——主观下线和客观下线,看看Sentinel是如何决定主库"到底挂没挂"的。


上一篇【第43篇】Redis Sentinel——主从集群的守门员
下一篇【第45篇】主观下线和客观下线——Sentinel怎么判断主库挂了


http://www.jsqmd.com/news/947378/

相关文章:

  • 实战指南:基于快马生成生产级PyTorch模型推理镜像与部署方案
  • PHP风控系统与反欺诈策略
  • 学生编程入门最佳AI编程工具最新推荐:8款实测工具搞定作业、课程项目与竞赛
  • 让 Agent 具备业务常识的三种策略
  • 别再死记硬背!用‘客户服务系统’实战案例,轻松搞懂UML类图与包图设计
  • 从零到一:在CentOS服务器上为Tesla K80双卡配置CUDA深度学习环境(实测记录)
  • 2026实测|英文论文AI率94%降至7%:5款结构级降AI工具推荐 - 降AI实验室
  • MyBatis-Plus更新数据实战:从单字段修改到复杂条件更新的完整配置流程
  • 新手避坑指南:用BC35-G模块和AT指令,5分钟搞定NBIOT设备上云OneNET
  • 深度整合ai开发力量:在快马平台实现比idea ai插件更强大的智能结对编程助手
  • FPGA上跑的纯硬件俄罗斯方块:Verilog代码+VGA显示+完整编译工程
  • DeepSeek V4实测:MoE架构与百万上下文的工程真相
  • 给一个web网站,如何开展测试?
  • 别再只用@Scheduled了!手把手教你搭建可管理、可持久化的Quartz+PostgreSQL任务中心
  • 从零打造 99.99% 在线 CRM:高可用架构设计与系统化工程方法论
  • ubuntu 无权限安装多个cuda和cudnn
  • PHP魔术方法深入理解与实战
  • 郑州市 家电维修清洗上门|维小达空调、冰箱、洗衣机、热水器、电视、油烟机灶具、消毒柜、小家电一站式维保清洗服务 - 维小达科技
  • 魔兽争霸III终极性能优化:三大核心功能免费解决宽屏适配、地图加载与帧率限制
  • Arxiv上传前必读:关于撤稿、专利与源码政策的那些‘坑’,科研新人如何提前规避?
  • Qwen3.6-Plus工程落地指南:Agent底座的可交付实践
  • 基于深度学习+AI的电梯内电动车目标检测与预警系统(Python源码+数据集+UI可视化界面+YOLOv11训练结果)
  • 用Multisim 14.2从零搭建一个三路抢答器:我的课程设计实战与避坑全记录
  • 工地PPE实时检测工具:PyQt5界面+YOLOv8模型,支持安全帽/马甲/面具三类识别
  • 从啤酒瓶到二维码:手把手教你复用Gazebo官方模型,打造自定义贴图仿真资产
  • AI生成可玩游戏:单文件HTML卡丁车实战指南
  • SQL 无关联条件拼接
  • PHP国际化与多语言支持实现
  • SAIL系统架构:SRAM与查找表优化LLM推理性能
  • 开源报表工具JimuReport实战:手把手教你配置SQL数据源并生成动态销售报表