redis-py 热升级指南:用多数据库故障转移实现 Redis 模块零停机升级
【免费下载链接】redis-pyRedis Python client项目地址: https://gitcode.com/GitHub_Trending/re/redis-py
给 Redis 换装一个新模块,往往要重启进程才能加载,业务连接随之断掉。redis-py 提供了多数据库(multidb)客户端,内置多数据库故障转移与健康检查策略:把多个互为冗余的实例交给同一个客户端,节点掉线时它会自动把流量引向健康节点。围绕这套机制做 Redis 模块热升级,可以做到零停机升级,应用进程无需重启。
🎯 模块升级为什么会掐断连接
Redis 模块(搜索、JSON、时序等)是注入 redis-server 进程中的动态库,加载新版本需要重启进程。麻烦集中在三点:
- 现有连接集中断开,应用瞬时收到大量连接错误;
- 重启窗口内该实例不可读写,恢复速度取决于复制与数据量;
- 应用层若用单个
Redis实例绑定这一个节点,流量就没有退路。
redis-py 热升级的思路是把"切换"这件事挪进客户端:客户端同时持有两个(或更多)实例,权重最高者处理请求,另一个随时待命。升级时谁不带流量就重启谁,业务侧因此感知不到重启动作。
🔁 多数据库客户端如何自动给流量让路
入口是 redis/multidb/client.py 中的MultiDBClient,配置对象定义在 redis/multidb/config.py。每个节点用DatabaseConfig声明,权重决定优先级:大家都健康时,请求发给权重最高者,其余节点作为备用。
权重加熔断器决定流量走向
每个节点背后挂一个熔断器(见 redis/multidb/circuit.py),状态分 CLOSED(正常)、OPEN(已熔断)、HALF_OPEN(试探性闭合)三种。默认故障转移策略WeightBasedFailoverStrategy定义在 redis/multidb/failover.py:处理请求时按权重顺序扫描,取第一个熔断器处于 CLOSED 的节点;全部 OPEN 则抛出NoValidDatabaseException。
外层还包着一层重试:执行器用failover_attempts(默认 10 次)与failover_delay(默认 12 秒)控制探测节奏。找不到可用节点时抛出TemporaryUnavailableException而非直接失败,等于给调用方留出一个约 120 秒的缓冲窗口,正好覆盖模块重载的时间。
主动探测与被动观测并行
- 主动侧:后台健康检查循环每隔
health_check_interval(默认 5 秒)对各节点做一次探测; - 被动侧:
CommandFailureDetector观察真实命令失败,滑动窗口内失败率越线就打开熔断器。
节点一旦熔断,下一条请求直接落到次高权重节点,应用代码不需要任何改动。
健康检查策略的三种判定口径
一次健康检查会连续发health_check_probes次探针(默认 3 次),每次间隔health_check_delay(默认 0.5 秒),整体受health_check_timeout(默认 3 秒)约束。探针默认是PingHealthCheck,向节点发送 PING(集群需每个节点都通过);也可以自定义探针(例如官方文档示例中的 ECHO 式EchoHealthCheck),实现都在 redis/asyncio/multidb/healthcheck.py。
判定口径由三个策略类承担,通过MultiDbConfig的health_check_policy字段(HealthCheckPolicies枚举)选择:
| 策略类 | 判定口径 | 适用场景 |
|---|---|---|
HealthyAllPolicy(默认) | 全部探针通过才算健康 | 关键链路,宁严勿松,避免把半死不活的节点选进流量 |
HealthyMajorityPolicy | 超过半数通过即可(3 次探针允许 1 次失败) | 网络偶发抖动的平衡之选 |
HealthyAnyPolicy | 任意一次通过即健康 | 可用性优先,容忍探针偶发失败 |
热升级场景下HealthyAllPolicy最稳妥:重启中的实例不会因为某一次探针侥幸成功而被误判可用。
热升级四步走:从配客户端到切流
双节点客户端怎么配
下面定义主节点(权重 1.0)与备用节点(权重 0.5),并开启周期性自动回切高权重节点:
from redis.multidb.client import MultiDBClient from redis.multidb.config import MultiDbConfig, DatabaseConfig from redis.asyncio.multidb.healthcheck import HealthCheckPolicies cfg = MultiDbConfig( databases_config=[ DatabaseConfig(from_url="redis://db-primary:6379/0", weight=1.0), DatabaseConfig(from_url="redis://db-standby:6379/0", weight=0.5), ], health_check_policy=HealthCheckPolicies.HEALTHY_ALL, auto_fallback_interval=60, ) client = MultiDBClient(cfg) client.set("key", "value") # 首次调用触发初始化与健康检查升级、切流、回补的操作顺序
- 升级备用节点:此时流量全在主节点上。对备用节点执行模块重载或重启,健康检查期间它熔断也不影响业务;
- 切换流量:备用节点通过健康检查后,用
client.set_active_database(db_standby)主动切换,或调update_database_weight抬升其权重,让WeightBasedFailoverStrategy自然选中;Pub/Sub 订阅会在新节点上自动重订; - 升级原主节点:它已转为备用状态,重启加载新模块,健康检查会在其恢复后把熔断器闭合;
- 回补为备用:交给
auto_fallback_interval自动回切高权重节点,或用add_database/remove_database显式管理候选池。这套运行时管理 API 都在 redis/multidb/client.py 中。
Redis Enterprise 环境可在健康检查列表里加挂LagAwareHealthCheck(需在DatabaseConfig设置health_check_url),通过 REST 接口确认实例间同步延迟,让切流判断更稳。
✅ 上线前自查与参数调优清单
- 策略选型:关键路径用
HealthyAllPolicy;可用性至上的链路再评估HealthyAnyPolicy; - 重试与延迟:
failover_attempts × failover_delay是重试预算(默认 10×12=120 秒),应略大于最长一次模块重载耗时;上层要捕获TemporaryUnavailableException做本地重试,NoValidDatabaseException则表示全池不可用,两种异常要区别对待; - 监控:通过
EventDispatcher注册ActiveDatabaseChanged事件监听器,把切流时刻与新旧节点写进日志和指标; - 故障演练:上线前在预发环境实际模拟"主节点熔断",验证故障转移、订阅重订、回补路径。单测可以参考 tests/test_multidb/test_failover.py 里构造节点不可用的做法。
完整配置字段见 docs/geographic_failover.rst。客户端容错铺好之后,模块升级只剩"先切流、再升级、双升级、再回切",应用进程不必停一秒。
【免费下载链接】redis-pyRedis Python client项目地址: https://gitcode.com/GitHub_Trending/re/redis-py
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考