数据库运维7 min read

Redis缓存优化与集群部署实战指南

Redis缓存优化与集群部署实战指南

前言

Redis凭借其极致的性能和丰富的数据结构,已成为现代互联网架构中不可或缺的组件。然而,"Redis很快"不等于"用Redis就一定快"。不当的使用方式、不合理的配置、缺失的监控,都可能让Redis成为系统的瓶颈。本文将从实战出发,全面介绍Redis的优化与集群部署。

一、内存优化策略

1.1 内存使用分析

# 连接Redis
redis-cli

# 内存概况
INFO memory

# 查看大Key
redis-cli --bigkeys

# 内存分析(Redis 4.0+)
MEMORY USAGE key_name
MEMORY DOCTOR

1.2 数据结构优化

# ❌ 散乱的String存储用户信息
SET user:1001:name "张三"
SET user:1001:email "zhangsan@example.com"
SET user:1001:age "25"
# 内存占用约 300 bytes/user

# ✅ 使用Hash存储(ziplist编码)
HSET user:1001 name "张三" email "zhangsan@example.com" age 25
# 内存占用约 120 bytes/user,节省60%

内存优化配置

# redis.conf
# 小hash使用ziplist编码
hash-max-ziplist-entries 512
hash-max-ziplist-value 64

# 小list使用ziplist
list-max-ziplist-size -2
list-compress-depth 0

# 小set使用intset
set-max-intset-entries 512

# 小zset使用ziplist
zset-max-ziplist-entries 128
zset-max-ziplist-value 64

1.3 缓存淘汰策略

策略 说明 适用场景
noeviction 不淘汰,写满报错 不推荐
allkeys-lru 所有key LRU淘汰 通用推荐
volatile-lru 过期key LRU淘汰 混合使用场景
allkeys-lfu 所有key LFU淘汰 热点数据明显
volatile-ttl 过期时间最近的淘汰 定时过期场景
# redis.conf
maxmemory 8gb
maxmemory-policy allkeys-lru

1.4 过期键清理

# 查看带过期时间的key数量
INFO keyspace

# 扫描即将过期的key
redis-cli --scan --pattern '*' | while read key; do
    ttl=$(redis-cli TTL "$key")
    if [ "$ttl" -gt 0 ] && [ "$ttl" -lt 300 ]; then
        echo "Key: $key, TTL: $ttl"
    fi
done

过期删除策略:

  • 惰性删除:访问时检查是否过期
  • 定期删除:每秒10次随机抽查

二、持久化方案

2.1 RDB vs AOF

RDB (快照)
优点: 恢复快、文件小、对性能影响小
缺点: 可能丢失最后一次快照后的数据
适用: 缓存场景、可容忍少量数据丢失

AOF (追加日志)
优点: 数据安全性高、可逐条恢复
缺点: 文件大、恢复慢、性能影响大
适用: 金融、订单等关键数据

混合模式 (Redis 4.0+)
aof-use-rdb-preamble yes
RDB快照 + AOF增量 = 兼顾性能和安全

2.2 推荐配置

# redis.conf
# RDB配置
save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb

# AOF配置
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec          # 每秒同步,性能与安全的平衡
no-appendfsync-on-rewrite yes  # 重写时不fsync

# 自动重写
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

2.3 备份脚本

#!/bin/bash
BACKUP_DIR="/data/backup/redis"
REDIS_DIR="/var/lib/redis"

# 触发BGSAVE
redis-cli BGSAVE

# 等待完成
while [ $(redis-cli INFO persistence | grep rdb_bgsave_in_progress | cut -d: -f2) -eq 1 ]; do
    sleep 1
done

# 备份
cp ${REDIS_DIR}/dump.rdb ${BACKUP_DIR}/dump_$(date +%Y%m%d_%H%M).rdb

# 清理旧备份
find ${BACKUP_DIR} -name "dump_*.rdb" -mtime +7 -delete

三、哨兵模式(Sentinel)

3.1 架构

         Clients
            │
    ┌───────┼───────┐
    ▼       ▼       ▼
┌────────┐┌────────┐┌────────┐
│Sentinel││Sentinel││Sentinel│
│   1    ││   2    ││   3    │
└───┬────┘└───┬────┘└───┬────┘
    │         │         │
    └────┬────┴────┬────┘
         ▼         ▼
    ┌────────┐┌────────┐┌────────┐
    │ Master ││ Slave  ││ Slave  │
    └────────┘└────────┘└────────┘

3.2 Sentinel配置

# sentinel.conf (每个Sentinel相同)
port 26379

# 监控master (至少2个sentinel同意才故障切换)
sentinel monitor mymaster 192.168.1.10 6379 2

# 主观下线判定时间
sentinel down-after-milliseconds mymaster 5000

# 故障切换超时
sentinel failover-timeout mymaster 30000

# 并行同步的slave数量
sentinel parallel-syncs mymaster 1

# 认证密码
sentinel auth-pass mymaster redis_password

3.3 Sentinel运维

# 查看集群状态
redis-cli -p 26379 SENTINEL masters
redis-cli -p 26379 SENTINEL slaves mymaster

# 手动故障切换
redis-cli -p 26379 SENTINEL failover mymaster

# 查看哨兵信息
redis-cli -p 26379 SENTINEL sentinels mymaster

四、Redis Cluster集群

4.1 架构特点

  • 16384个哈希槽分布
  • 无中心代理,客户端直连
  • 自动故障检测和转移
  • 支持在线扩容缩容

4.2 搭建集群

# 每个节点配置
port 6379
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

# 创建集群(6个节点,3主3从)
redis-cli --cluster create \
    192.168.1.11:6379 192.168.1.12:6379 192.168.1.13:6379 \
    192.168.1.14:6379 192.168.1.15:6379 192.168.1.16:6379 \
    --cluster-replicas 1

# 查看集群状态
redis-cli -c -h 192.168.1.11 -p 6379 CLUSTER NODES
redis-cli --cluster check 192.168.1.11:6379

# 添加新节点
redis-cli --cluster add-node 192.168.1.17:6379 192.168.1.11:6379

# 重新分片
redis-cli --cluster reshard 192.168.1.11:6379

4.3 集群运维注意事项

  • 批量操作要求所有key在同一个slot → 用 {hashtag}
  • 事务只能在同一节点的key上执行
  • 多key操作(如 MGET)只能在同slot执行
  • 建议最少3主3从

五、性能问题排查

5.1 慢查询日志

# 配置
CONFIG SET slowlog-log-slower-than 10000  # 10ms
CONFIG SET slowlog-max-len 1000

# 查看
SLOWLOG GET 10
SLOWLOG LEN
SLOWLOG RESET

5.2 延迟排查

# 延迟基线测试
redis-cli --latency
redis-cli --latency-history
redis-cli --latency-dist

# 检查是否是持久化导致的
INFO persistence | grep rdb_bgsave_in_progress
INFO persistence | grep aof_rewrite_in_progress

# 命令延迟监控
redis-cli --intrinsic-latency 30

5.3 常见问题速查

问题 可能原因 解决
延迟突增 fork子进程写RDB 关闭THP, 减少fork频率
OOM maxmemory-policy=noeviction 改为allkeys-lru
连接数满 客户端没关连接 配置timeout, 加连接池
主从断连 复制缓冲区太小 增大repl-backlog-size
CPU飙高 大量key过期 分散过期时间, lazyfree

总结

Redis运维的核心理念:

  1. 内存是命:合理设置maxmemory和淘汰策略
  2. 持久化要稳:RDB+AOF混合模式
  3. 高可用必备:至少Sentinel,量大上Cluster
  4. 监控不掉线:慢查询、内存、延迟持续监控
  5. 备份不偷懒:定期备份,异地存储
分享:

相关文章