跳到主要内容

Redis 高可用

问题

如何保证 Redis 的高可用?从部署架构、数据持久化、故障转移等维度如何设计?

答案

高可用方案全景

持久化保障

参见 Redis 持久化,生产环境推荐混合持久化(RDB + AOF),确保数据不丢失。

主从 + 哨兵

参见 Redis 集群方案,哨兵模式实现自动故障转移。

关键配置建议:

生产环境推荐配置
# 哨兵个数 ≥ 3(奇数),部署在不同机器
sentinel monitor mymaster 192.168.1.100 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1

# 从节点配置
replica-read-only yes # 从节点只读
replica-serve-stale-data yes # 主节点下线时从节点仍可读
min-replicas-to-write 1 # 至少 1 个从节点同步成功才允许写
min-replicas-max-lag 10 # 从节点最大延迟 10 秒

Redis Cluster

适合大规模部署,自带分片和高可用。参见 Redis 集群方案

客户端最佳实践

连接池配置

Jedis 连接池推荐配置
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(200); // 最大连接数
config.setMaxIdle(50); // 最大空闲连接
config.setMinIdle(10); // 最小空闲连接
config.setMaxWaitMillis(3000); // 获取连接最大等待时间
config.setTestOnBorrow(true); // 借用时检测连接有效性
config.setTestWhileIdle(true); // 空闲时检测

降级策略

Redis 不可用时的降级
public Object getData(String key) {
try {
Object value = redis.get(key);
if (value != null) return value;
} catch (Exception e) {
log.warn("Redis 不可用,走降级逻辑", e);
// 降级方案:
// 1. 本地缓存(Caffeine)
// 2. 直接查数据库(限流保护)
// 3. 返回默认值
}
return getFromDBWithRateLimit(key);
}

大 Key 问题

大 Key 会导致内存不均、网络阻塞、主从同步延迟等问题。

类型大 Key 标准
Stringvalue 超过 10KB
Hash/List/Set/ZSet元素超过 5000 个
发现大 Key
# Redis 4.0+ 内置大 Key 扫描
redis-cli --bigkeys

# 更精确的内存分析
redis-cli --memkeys
删除大 Key(避免阻塞)
# Redis 4.0+ 异步删除
UNLINK bigkey

# 渐进式删除 Hash
HSCAN bigkey cursor COUNT 100
# 然后逐批 HDEL

监控告警

指标阈值建议命令
内存使用率< 80%INFO memory
连接数< maxclients 的 80%INFO clients
命中率> 95%INFO stats(keyspace_hits / (hits + misses))
慢查询关注SLOWLOG GET 10
主从延迟< 1 秒INFO replication(master_repl_offset 差值)

常见面试问题

Q1: Redis 如何保证高可用?

答案

四个层面:

  1. 持久化:混合持久化(RDB + AOF)保证数据不丢失
  2. 多副本:主从复制提供数据冗余
  3. 自动故障转移:Sentinel(中小规模)或 Cluster(大规模)自动检测故障并切换
  4. 客户端兜底:连接池、重试机制、降级策略、多级缓存

Q2: 如何处理大 Key?

答案

  1. 发现redis-cli --bigkeys 扫描,或通过监控 SLOWLOG 发现处理慢的 key
  2. 拆分:将大 Hash 按前缀拆成多个小 Hash,将大 List 按时间或 ID 范围分片
  3. 删除:使用 UNLINK(异步删除)代替 DEL,或渐进式删除(HSCAN + HDEL)
  4. 预防:设计时控制集合类型元素数量,String value 不超过 10KB

Q3: Redis 为什么这么快?

答案

  1. 内存操作:数据存储在内存中,读写速度远高于磁盘
  2. 单线程模型:避免了多线程上下文切换和锁竞争的开销
  3. I/O 多路复用:使用 epoll/kqueue 处理大量并发连接
  4. 高效数据结构:SDS、ziplist/listpack、skiplist 等针对性能优化的数据结构
  5. 单线程避免锁:核心操作串行执行,不需要加锁
Redis 6.0 的多线程

Redis 6.0 引入了 I/O 多线程io-threads),但只用于网络读写(解析请求、发送响应),命令执行仍然是单线程。这既利用了多核 CPU 的网络处理能力,又保持了单线程执行的简单性和安全性。

相关链接