少女祈祷中...
NEKO
知识库

redis 性能运维面试要点

一、性能排查总览类

Q1:Redis 变慢了,你的排查思路是什么?

  1. 确认现象:延迟、QPS、错误率。

  2. 看慢查询:SLOWLOG GET 找慢命令。

  3. 看大 key / 热 key:--bigkeys、--hotkeys。

  4. 看阻塞命令:KEYS、FLUSHALL、大 DEL。

  5. 看内存:是否触发淘汰、碎片率。

  6. 看网络:连接数、带宽、Pipeline。

  7. 看持久化:fork、AOF 刷盘。

  8. 看系统:CPU、内存、磁盘、网络。

Q2:Redis 的延迟来源有哪些?

  • 命令本身慢:KEYS、SORT、大集合操作。

  • 大 key:单次操作数据量大。

  • fork 阻塞:RDB/AOF 重写。

  • AOF 刷盘:always 每次 fsync。

  • 内存淘汰:频繁淘汰。

  • 网络:带宽满、RTT 高。

  • CPU 竞争:其他进程抢占。

  • swap:内存不足触发交换,性能骤降。

Q3:怎么衡量 Redis 性能?

  • redis-benchmark:压测工具。

  • INFO stats:QPS、命中率。

  • INFO commandstats:各命令调用次数和耗时。

  • SLOWLOG:慢命令。

  • LATENCY:延迟监控。

二、慢查询类

Q4:Redis 慢查询怎么用?

  • slowlog-log-slower-than:阈值,微秒,默认 10000(10ms)。

  • slowlog-max-len:保留条数,默认 128。

  • SLOWLOG GET [n]:查看。

  • SLOWLOG RESET:清空。

  • 慢查询只记录命令执行时间,不含网络。

Q5:慢查询日志会记录所有命令吗?

  • 不会。只记录超过阈值的。

  • 阈值设为 0 记录所有,设为 -1 关闭。

  • 只记录命令执行,不记录网络和排队。

Q6:常见慢命令有哪些?

  • KEYS *:遍历所有 key。

  • FLUSHALL、FLUSHDB:清库。

  • DEL 大 key。

  • HGETALL、LRANGE、SMEMBERS 大集合。

  • SORT、ZRANGE 大范围。

  • SAVE:同步持久化。

  • MGET 大量 key。

Q7:怎么替代慢命令?

慢命令

替代

KEYS

SCAN

DEL 大 key

UNLINK

HGETALL

HSCAN

SMEMBERS

SSCAN

FLUSHALL

FLUSHALL ASYNC

SAVE

BGSAVE

Q8:KEYS 为什么慢?

  • 遍历所有 key,O(n)。

  • 单线程执行,阻塞其他请求。

  • 生产禁用,用 SCAN 替代。

Q9:SCAN 和 KEYS 的区别?

维度

KEYS

SCAN

复杂度

O(n)

分批 O(1)

阻塞

全阻塞

不阻塞

完整性

完整

可能重复/遗漏

生产

禁用

推荐

三、大 key 类

Q10:什么是大 key?

  • 单个 key 的 value 很大。

  • 判断标准:

    • String > 10KB。

    • Hash/List/Set/ZSet 元素 > 5000。

  • 没有绝对标准,按业务和实例规模。

Q11:大 key 有什么危害?

  • 阻塞主线程:DEL、HGETALL 慢。

  • 网络拥塞:传输大 value 占带宽。

  • 内存不均:Cluster 下分布不均。

  • 持久化慢:RDB/AOF 变大。

  • 主从同步慢:全量同步传输大。

Q12:怎么发现大 key?

  • redis-cli --bigkeys:扫描各类型最大 key。

  • MEMORY USAGE key:单 key 内存。

  • SCAN + STRLEN/LLEN/HLEN/SCARD/ZCARD。

  • 分析 RDB 文件:redis-rdb-tools。

Q13:怎么解决大 key?

  • 拆分:大 Hash 拆多个小 Hash。

  • 异步删除:UNLINK 替代 DEL。

  • 压缩:序列化后压缩。

  • 分片:按字段或范围拆。

  • 设计阶段避免:控制集合大小。

Q14:DEL 和 UNLINK 的区别?

  • DEL:同步删除,阻塞主线程。

  • UNLINK:异步删除,后台线程释放。

  • 大 key 用 UNLINK。

  • FLUSHALL ASYNC、FLUSHDB ASYNC 同理。

Q15:怎么异步删除大 key?

  • UNLINK key。

  • FLUSHALL ASYNC。

  • FLUSHDB ASYNC。

  • 后台线程逐步释放内存。

四、热 key 类

Q16:什么是热 key?

  • 被高频访问的 key。

  • 可能导致单节点 CPU 或网络瓶颈。

  • Cluster 下热点 key 落在单个分片。

Q17:怎么发现热 key?

  • redis-cli --hotkeys:需 LFU 策略。

  • MONITOR:采样,生产慎用。

  • 客户端埋点统计。

  • 代理层(如 ProxySQL)统计。

Q18:怎么解决热 key?

  1. 本地缓存:热点放 JVM 本地。

  2. key 拆分:加随机后缀分散。

  3. 读写分离:从库分担读。

  4. 限流:保护后端。

  5. 多级缓存:本地 + Redis。

Q19:热 key 拆分怎么做?

  • 原 key hot 拆成 hot:1、hot:2...hot:N。

  • 读时随机选一个,写时写所有。

  • 分散到多个节点。

  • 适合读多写少。

Q20:本地缓存和 Redis 怎么配合?

  • 热点数据放本地(Caffeine、Guava)。

  • 本地没有查 Redis,Redis 没有查 DB。

  • 本地缓存一致性用 MQ 广播失效。

  • 减少 Redis 压力。

五、Pipeline 与批量类

Q21:Pipeline 是什么?

  • 一次发送多条命令,减少 RTT。

  • 客户端打包,服务端依次执行,批量返回。

  • 不是原子操作。

  • 适合批量读写。

Q22:Pipeline 有什么注意事项?

  • 批量大小要控制,如每次几百条。

  • 太大会占内存、阻塞。

  • 不是原子,中间可能插入其他命令。

  • 错误要逐条处理。

Q23:Pipeline 能提升多少性能?

  • 取决于 RTT 和命令数。

  • 本地网络可能提升几倍到几十倍。

  • 跨机房 RTT 大,提升更明显。

Q24:Pipeline 和事务能一起用吗?

  • 能。MULTI、命令、EXEC 一起打包。

  • 减少 RTT + 原子。

  • 注意批量大小。

Q25:MGET 和 Pipeline 怎么选?

  • MGET 是单命令多 key,原子。

  • Pipeline 是多命令批量。

  • 简单批量用 MGET,复杂用 Pipeline。

六、内存与碎片类

Q26:怎么查看 Redis 内存?

  • INFO memory:used_memory、maxmemory、碎片率。

  • MEMORY USAGE key:单 key。

  • MEMORY STATS:内存分布。

  • MEMORY DOCTOR:诊断建议。

Q27:内存碎片率是什么?

  • mem_fragmentation_ratio = used_memory_rss / used_memory。

  • >1.5 碎片多,<1 可能 swap。

  • 碎片来自频繁分配释放不同大小内存。

  • 用 activedefrag yes 自动整理。

Q28:怎么处理内存碎片?

  • 开启 activedefrag yes。

  • 重启实例(需持久化)。

  • 主从切换,重建从库。

  • 合理设计 key,避免频繁增删。

Q29:maxmemory 怎么设?

  • 设 Redis 可用最大内存。

  • 留出系统内存和 fork COW 余量。

  • 一般设物理内存的 50%~70%。

  • 不设可能 OOM。

Q30:内存淘汰策略怎么选?

  • 纯缓存:allkeys-lru 或 allkeys-lfu。

  • 有持久数据:volatile-lru。

  • 不能丢:noeviction。

  • 详见过期与淘汰模块。

七、阻塞与持久化类

Q31:哪些操作会阻塞 Redis?

  • KEYS、FLUSHALL、FLUSHDB。

  • DEL 大 key。

  • 大集合 HGETALL、LRANGE。

  • SAVE。

  • fork(RDB/AOF 重写)。

  • 长 Lua 脚本。

  • AOF always 刷盘。

Q32:fork 会阻塞多久?

  • 取决于内存页表大小。

  • 内存越大,fork 越慢。

  • 通常毫秒到几十毫秒。

  • 大实例可能上百毫秒。

Q33:怎么减少 fork 影响?

  • 控制实例大小,分片。

  • 低峰执行 BGSAVE。

  • 用从库做持久化。

  • 避免频繁重写。

Q34:AOF always 性能差在哪?

  • 每个命令都 fsync。

  • 磁盘 IO 成为瓶颈。

  • 用 everysec 折中。

  • 要求不丢才用 always。

Q35:怎么监控持久化?

  • INFO persistence:rdb_last_bgsave_status、aof_last_bgrewrite_status。

  • INFO stats:rdb_changes_since_last_save。

  • 监控 fork 耗时、AOF 大小。

八、监控与运维类

Q36:Redis 监控哪些指标?

  • 性能:QPS、延迟、命中率。

  • 内存:used_memory、碎片率、淘汰数。

  • 连接:connected_clients、rejected_connections。

  • 持久化:RDB/AOF 状态。

  • 主从:offset、延迟。

  • 集群:槽状态、节点健康。

  • 工具:Prometheus + redis_exporter、Grafana。

Q37:命中率怎么算?

  • keyspace_hits / (keyspace_hits + keyspace_misses)。

  • 低于预期排查 key 设计、TTL、容量。

  • 命中率低说明缓存没起作用。

Q38:连接数怎么监控?

  • INFO clients:connected_clients。

  • maxclients:最大连接数。

  • 拒绝连接看 rejected_connections。

  • 连接泄漏要排查客户端。

Q39:怎么做 Redis 容量规划?

  • 估算数据量和增长。

  • 留 30%~50% 余量。

  • 考虑 fork COW 内存。

  • 按 QPS 规划分片。

Q40:怎么做 Redis 备份?

  • RDB 定期备份。

  • AOF 实时。

  • 异地备份。

  • 定期恢复演练。

九、高频陷阱题

Q41:Redis 慢查询会记录网络时间吗?

  • 不会。只记录命令执行时间。

  • 网络慢要另查。

  • 用 LATENCY 或客户端埋点。

Q42:SCAN 能保证返回所有 key 吗?

  • 不能。rehash 期间可能重复或遗漏。

  • 但保证不遗漏“一直存在”的 key。

  • 适合遍历,不适合精确统计。

Q43:大 key 拆分后怎么读?

  • 读时合并多个小 key。

  • 或维护索引。

  • 写时写所有分片。

  • 复杂度增加。

Q44:热 key 本地缓存会不一致吗?

  • 会。本地缓存更新有延迟。

  • 用 MQ 广播失效。

  • 设短 TTL 兜底。

  • 强一致场景慎用。

Q45:Pipeline 越大越好吗?

  • 不是。太大占内存、阻塞。

  • 每次几百条合适。

  • 根据命令大小和网络调整。

Q46:内存碎片率小于 1 说明什么?

  • 可能用了 swap。

  • used_memory_rss 小于 used_memory。

  • 性能会骤降。

  • 要检查系统内存和 swap。

Q47:activedefrag 有什么代价?

  • 整理碎片占 CPU。

  • 可能影响性能。

  • 低峰开启。

  • 碎片不严重可不开。

Q48:Redis 能存多少 key?

  • 理论上 2^32 个。

  • 实际受内存限制。

  • key 太多会影响 SCAN 和持久化。

  • 按内存规划。

评论