bigywater.tech
Redis · 86

Sentinel 主观下线

Sentinel 判断主库挂了分两步:先是每个 sentinel 自己的「主观下线」(sdown),再是多个 sentinel 达成一致的「客观下线」。这一篇量第一步:多久判定、一个 sentinel 说了算不算、什么样的「挂」会被判定。

3957 ms
down-after-milliseconds = 3000 时 s_down 实际出现的时间(平均)
不触发
单个 sentinel 的 s_down 不会引发故障转移
3942 → 5097 ms
主库阻塞 6 秒(进程活着)时 s_down → o_down

一个 sentinel 说了不算

实测 · 本机执行输出
  三个 sentinel 眼中主库的 flags: ['master', 'master', 'master']
  主库被冻结,另外两个 sentinel 也被冻结;sentinel0 眼中主库 flags 的变化(相对冻结的毫秒):{'master': 1, 's_down,master': 3904}
  9 秒后主库地址仍是 ('127.0.0.1', 7660) (没有发生故障转移:sdown 只是「我认为它挂了」,不够触发)

冻结主库,同时冻结另外两个 sentinel,只让 sentinel0 活着:它在约 3.9 s 后标出 s_down,但 9 秒后主库地址仍是原来的——主观下线只是本地判断。

判定时间 = down-after + 探测间隔

每种设置 2 次
实测 · 本机执行输出
 down-after        s_down 出现(ms)
       1000           1838, 1936
       3000           3966, 3948
       6000           7010, 6935

实际出现的时间比设置值多约 0.9–1 秒。我没有单独验证原因;和第 85 篇里观察到的「每秒一次 PING」吻合(要等到下一次探测才发现超时),但这是推测。

进程活着也会被判

实测 · 本机执行输出
  主库被 DEBUG SLEEP 6 阻塞(进程活着,只是 6 秒不响应),sentinel0 眼中 flags 变化:{'master': 1, 's_down,master': 3942, 's_down,o_down,master': 5097, 'master,disconnected': 5178}
  6 秒后 sentinel 眼中主库: master  主库地址: ('127.0.0.1', 7661)

sentinel 只看「有没有回复」。DEBUG SLEEP 6 让主库进程 6 秒不响应,sentinel 同样标 s_down,随后客观下线、故障转移;原主库没有死,但被换掉了。所以 down-after-milliseconds 太小会把 GC 停顿、大 key 阻塞一类的短暂卡顿误判成故障。

分步演示:主观下线

Sentinel 主观下线
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / Redis 8.10.2 独立实例(本机回环端口,save 关闭),redis-cli 风格输出由自写的 RESP 客户端打印;计时用 time.perf_counter,数字每次运行会有小幅抖动。1 主 2 从 + 3 个 sentinel;主库用 SIGSTOP 冻结或 DEBUG SLEEP 阻塞
    • 没有验证:PING 回复错误(-LOADING、-BUSY 等)的判定、网络延迟高时的表现、down-after 的最优取值、多个 sentinel 各自 down-after 不同时的行为
    京ICP备2026067502号-1京公网安备11010502063487号