bigywater.tech
Redis · 92

客户端发现 Sentinel 新主节点

Sentinel 把主库换了,客户端怎么知道?答案是:客户端自己要去问 sentinel。这篇把三种常见做法放在同一次故障里比较:写死地址、连接失败后重新问 sentinel、订阅 +switch-master 事件。

永不恢复
写死主库地址的客户端:切换之后一直连旧地址
4294 ms
连接失败后重新向 sentinel 询问的客户端恢复时间
5407 ms
仅订阅 +switch-master 事件的客户端恢复时间

三个客户端,一次故障

实测 · 本机执行输出
客户端策略                   kill 后失败次数     首次失败(ms)            恢复(首次成功于新主库,ms)
失败后问 sentinel               60            2                       4294
订阅 +switch-master            77            7                       5407
固定地址                       131           10                       从未恢复
  各客户端失败的错误类型: {'失败后问 sentinel': [('ConnectionRefusedError', 59), ('ConnectionResetError', 1)], '订阅 +switch-master': [('ConnectionRefusedError', 76), ('EOFError', 1)], '固定地址': [('ConnectionRefusedError', 130), ('EOFError', 1)]}

三个线程每 10 ms 写一次。故障之后,写死地址的客户端始终失败;「失败后问 sentinel」的客户端在切换完成后的第一次询问就拿到新地址;「订阅事件」的客户端要等它订阅的那个 sentinel 发出 +switch-master。

实现建议(从数据得出的)

1) 不要把主库地址写死,启动时和每次连接失败(或收到 READONLY)时都向 sentinel 询问;2) 事件订阅可以作为「更快通知」的补充,但不要只靠它——事件可能晚到,也可能因为订阅的 sentinel 自己不可用而收不到;3) 询问要在多个 sentinel 之间轮换。第 3 条来自常识,这里没有实验。

分步演示:三种发现策略

客户端发现 Sentinel 新主库
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / Redis 8.10.2 独立实例(本机回环端口,save 关闭),redis-cli 风格输出由自写的 RESP 客户端打印;计时用 time.perf_counter,数字每次运行会有小幅抖动。三个客户端各自一个线程;kill -9 只杀主库进程;没有使用真正的客户端库
    • 没有验证:真实客户端库(redis-py Sentinel、Lettuce、Jedis)的具体策略、READONLY 错误触发重新发现的路径(本实验里旧主库进程已死,没有产生 READONLY)、订阅多个 sentinel 的组合策略
    京ICP备2026067502号-1京公网安备11010502063487号