Redis性能优化全攻略:从内存到架构

📅 2026/7/11 11:26:24 👁️ 阅读次数 📝 编程学习
Redis性能优化全攻略:从内存到架构

一、开场:先澄清场景

Redis 优化没有银弹,要先明确 Redis 的角色 和 瓶颈在哪:

  • 纯缓存:可牺牲持久化,优先吞吐和内存
  • 存储/消息队列:要兼顾持久化、一致性、可用性
  • 瓶颈可能是:内存、CPU、网络、单线程阻塞、热 key、大 key、持久化、主从延迟等

这句话能体现你不是背八股,而是会分析问题。


二、内存优化(最常考)

1. 选对数据结构

  • 小对象用 Hash 存字段,比多个 String key 更省内存(底层编码可压缩)
  • 排行榜用 ZSet,去重用 Set,计数用 String/INCR
  • 避免滥用 String 存 JSON,大对象可考虑 Hash 分字段或压缩

2. 控制 key 设计

  • 避免大 key:单个 key 的 value 过大(如百万级 Hash/List),会导致:
    • 读写阻塞(Redis 单线程)
    • 主从同步慢、AOF rewrite 卡顿
    • 内存碎片、淘汰困难
  • 避免 key 过多:大量小 key 也有元数据开销
  • 合理设置 TTL,防止内存只增不减

3. 内存上限与淘汰策略

maxmemory 4gb maxmemory-policy allkeys-lru # 纯缓存常用 # volatile-lru / allkeys-lfu 等按场景选
  • 纯缓存:allkeys-lru/allkeys-lfu
  • 部分 key 需持久保留:volatile-lru

4. 编码与配置调优

  • 了解 Redis 内部编码(如 listpack、intset),小数据会自动压缩
  • 可用MEMORY USAGE key分析内存占用

三、性能优化(吞吐与延迟)

1. 减少网络往返

  • Pipeline:批量发命令,减少 RTT
  • MGET/MSET:批量读写
  • Lua 脚本:多步操作原子执行,减少往返

2. 避免慢命令

危险命令问题替代方案
KEYS *O(N) 阻塞SCAN游标迭代
HGETALL大 Hash阻塞HSCAN或拆分
SMEMBERS大 Set阻塞SSCAN
LRANGE 0 -1大 List阻塞分页读取

3. 连接管理

  • 使用 连接池,避免频繁建连
  • 合理设置超时、重试,避免连接泄漏

4. 异步删除

  • Redis 4.0+ 用UNLINK替代DEL删除大 key,后台线程异步释放内存

四、热 Key 与大 Key 问题

热 Key(Hot Key)

  • 本地缓存(Caffeine/Guava):多级缓存,减轻 Redis 压力
  • 读写分离:热 key 读走从库(注意主从延迟)
  • key 拆分:如user:1000user:1000:0~user:1000:9分散到不同 slot
  • Redis 6.0+:redis-cli --hotkeys或监控发现

大 Key(Big Key)

  • 拆分:大 Hash 按 field 范围拆成多个 key
  • 压缩:value 序列化后 gzip
  • 定期清理:SCAN+UNLINK分批删除
  • 排查:redis-cli --bigkeysMEMORY USAGE

五、持久化优化

场景建议
纯缓存可关闭 RDB/AOF
可接受分钟级丢失RDB(快照)
需高可靠AOF +appendfsync everysec
兼顾性能与可靠Redis 4.0+ 混合持久化(RDB + AOF 增量)

注意:

  • AOF rewrite 会 fork,大内存实例可能卡顿
  • 可设auto-aof-rewrite-percentage控制 rewrite 频率

六、架构与高可用

1. 水平扩展

  • Redis Cluster:16384 slot 分片,突破单机内存/吞吐
  • 注意:跨 slot 的 multi-key 操作 受限(可用 hash tag{user}:1000

2. 读写分离

  • 主写从读,注意 主从延迟 导致读到旧数据
  • 强一致读需走主库

3. 高可用

  • Sentinel:主从 + 自动故障转移
  • Cluster:分片 + 高可用

七、监控与排查

  • slowlog:SLOWLOG GET查慢命令
  • latency doctor:延迟诊断
  • INFO memory/stats:内存、命中率、连接数
  • redis-exporter + Prometheus + Grafana:持续监控
  • 关注:命中率、evicted_keys、blocked_clients、used_memory_rss(碎片)

八、回答模板(可直接背)

Redis 优化我会从几个层面看:

  1. 内存:选对数据结构、控制 key 大小和数量、设 maxmemory 和淘汰策略、合理 TTL
  2. 性能:Pipeline 减 RTT、避免 KEYS/HGETALL 等慢命令、用 UNLINK 删大 key、连接池
  3. 热点:热 key 用本地缓存或 key 拆分,大 key 拆分或压缩
  4. 持久化:纯缓存可关;要可靠用 AOF 或混合持久化,并控制 rewrite
  5. 架构:单机不够就 Cluster 分片,读多就主从读写分离
  6. 监控:slowlog、bigkeys、hotkeys、命中率,先定位再优化

九、常见追问及简答

追问要点
LRU 和 LFU 区别?LRU 看时间,LFU 看频率;LFU 对热 key 更友好
为什么 Redis 单线程还快?纯内存、IO 多路复用、无锁、简单数据结构
热 key 导致单点打满怎么办?本地缓存 + key 拆分 + 多副本
如何保证缓存与 DB 一致?先更新 DB 再删缓存、延迟双删、Canal 订阅 binlog
Cluster 如何分片?CRC16(key) % 16384 得到 slot