Redis面试题及详细答案100道(61-70) --- 性能优化篇
《前后端面试题
》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,MySQL,Linux… 。
文章目录
- 一、本文面试题目录
- 61. Redis慢查询是什么?通过什么配置?
- 62. Redis慢查询修复经验有哪些?
- 63. 有做过Redis服务的性能优化吗?具体措施有哪些?
- 64. 哪些操作可能会导致Redis性能下降?
- 65. 如何发现Redis阻塞异常情况?
- 66. 请介绍几个可能导致Redis阻塞的原因。
- 67. Redis支持的连接数是多少?如何调整?
- 68. Redis内存消耗分类有哪些?内存统计使用什么命令?
- 69. 如何设置Redis的内存上限?有什么作用?
- 70. Redis报内存不足怎么处理?
- 二、100道面试题目录列表
一、本文面试题目录
61. Redis慢查询是什么?通过什么配置?
- 原理说明:
Redis慢查询指执行时间超过预设阈值的命令,用于定位耗时操作,帮助优化性能。慢查询不会阻塞Redis主线程,其日志记录在内存队列中,可通过命令查看。 - 配置方式:
可在redis.conf
中配置两个核心参数:slowlog-log-slower-than <microseconds>
:设定慢查询阈值(微秒,1秒=1000000微秒),默认10000。值为0时记录所有命令,负值则不记录。slowlog-max-len <count>
:设定慢查询日志队列的最大长度,默认128,超出后会覆盖最早的记录。
- 示例配置:
slowlog-log-slower-than 5000 # 记录执行时间超过5毫秒的命令 slowlog-max-len 1000 # 最多保留1000条慢查询日志
- 查看慢查询:
127.0.0.1:6379> SLOWLOG get # 查看所有慢查询 127.0.0.1:6379> SLOWLOG len # 查看慢查询数量 127.0.0.1:6379> SLOWLOG reset # 清空慢查询日志
62. Redis慢查询修复经验有哪些?
- 原理说明:
慢查询通常由命令复杂度高、数据量过大或资源竞争导致,修复需结合命令特性和业务场景优化。 - 修复措施:
- 优化命令复杂度:
- 避免使用
KEYS *
(时间复杂度O(N)),改用SCAN
分批迭代。 - 减少
HGETALL
、LRANGE
等全量操作,改用HMGET
、LRANGE key start end
(限制范围)。
示例:
# 替代 KEYS user:* 127.0.0.1:6379> SCAN 0 MATCH user:* COUNT 100# 替代 LRANGE list 0 -1(全量获取) 127.0.0.1:6379> LRANGE list 0 99 # 分批获取前100条
- 避免使用
- 拆分大数据结构:
- 对超大Hash/Set,按ID哈希拆分(如
user:1000
、user:1001
拆分为user:1000:info
、user:1001:info
)。
- 对超大Hash/Set,按ID哈希拆分(如
- 增加缓存预热/异步处理:
- 高频访问的大结果集提前计算并缓存,避免实时计算。
- 调整配置参数:
- 若因内存不足导致swap频繁,需增加内存或调整内存淘汰策略。
- 避免长事务/管道滥用:
- 事务或管道中命令过多会阻塞主线程,需拆分执行。
- 优化命令复杂度:
63. 有做过Redis服务的性能优化吗?具体措施有哪些?
- 原理说明:
Redis性能优化需从硬件、配置、命令、架构多维度入手,目标是降低响应时间、提高吞吐量。 - 具体措施:
- 硬件与系统优化:
- 使用SSD减少持久化IO延迟,关闭Swap避免内存交换。
- 调整内核参数:
vm.overcommit_memory = 1
(允许Redis使用超过物理内存的内存)、net.core.somaxconn = 1024
(提高TCP连接队列上限)。
- Redis配置优化:
- 开启
no-appendfsync-on-rewrite yes
:AOF重写时暂停fsync,减少IO阻塞。 - 合理设置
maxmemory
和内存淘汰策略(如allkeys-lru
)。 - 关闭
daemonize no
(非后台运行),生产环境建议daemonize yes
。
- 开启
- 命令与数据结构优化:
- 优先使用高效命令(如
HSET
比多次SET
更优),避免O(N)
命令。 - 选择合适数据结构(如用
Bitmap
存储布尔值,HyperLogLog
做基数统计)。
- 优先使用高效命令(如
- 架构优化:
- 主从复制分担读压力,哨兵实现高可用,集群分片扩展容量。
- 使用Pipeline批量发送命令,减少网络往返。
- 持久化优化:
- 混合持久化(RDB+AOF)平衡性能与安全性,AOF采用
everysec
同步策略。
- 混合持久化(RDB+AOF)平衡性能与安全性,AOF采用
- 硬件与系统优化:
64. 哪些操作可能会导致Redis性能下降?
- 原理说明:
Redis性能下降通常与命令阻塞、资源竞争、配置不当有关,主线程单线程特性使其对阻塞敏感。 - 常见操作:
- 高复杂度命令:
KEYS *
(O(N))、HGETALL
(O(N))、SORT
(O(N log N))等,数据量大时耗时剧增。
- 大数据结构操作:
- 对百万级元素的List执行
LPOP
/RPOP
(全量遍历),或对大Hash执行HDEL
。
- 对百万级元素的List执行
- 持久化阻塞:
- AOF同步策略为
always
时,每写命令都触发fsync,IO阻塞主线程。 - RDB生成快照时(
BGSAVE
),若内存大,fork子进程可能阻塞主线程。
- AOF同步策略为
- 网络与连接问题:
- 大量长连接未释放,占用文件描述符;网络延迟高导致命令响应慢。
- 内存不足与Swap:
- 内存达到
maxmemory
后,频繁触发淘汰策略(如LRU淘汰需遍历筛选);Swap启用后,内存读写转为磁盘IO。
- 内存达到
- 集群分片不均:
- 某节点数据量过大,成为热点,读写集中导致负载过高。
- 高复杂度命令:
65. 如何发现Redis阻塞异常情况?
- 原理说明:
Redis阻塞会导致命令响应延迟,需通过监控指标和日志定位异常。 - 检测方法:
- 监控命令响应时间:
- 使用
redis-cli --latency
实时查看延迟,正常应在毫秒级,突增可能表示阻塞。
$ redis-cli --latency min: 0, max: 10, avg: 0.5 (100 samples) # 平均延迟0.5毫秒,正常
- 使用
- 查看慢查询日志:
- 通过
SLOWLOG get
定位耗时命令,判断是否因命令阻塞。
- 通过
- 分析INFO命令指标:
info stats
中的latest_fork_usec
:若值过大(如超过1秒),说明fork子进程阻塞。info server
中的uptime_in_seconds
:若服务频繁重启,可能因阻塞崩溃。
- 监控系统资源:
- 查看CPU使用率(
top
):Redis进程CPU过高可能是命令计算密集。 - 查看内存与Swap(
free -m
):Swap使用量增加可能导致阻塞。
- 查看CPU使用率(
- 日志与告警:
- 配置Redis日志(
logfile
),记录错误和异常;结合Prometheus+Grafana监控redis_blocked_clients
等指标。
- 配置Redis日志(
- 监控命令响应时间:
66. 请介绍几个可能导致Redis阻塞的原因。
- 原理说明:
Redis主线程为单线程,任何阻塞操作都会导致后续命令排队,需从命令、系统、配置多方面分析。 - 常见原因:
- 命令级阻塞:
- 执行
KEYS
、SORT
、FLUSHDB
等耗时命令,或对超大集合执行全量操作(如SMEMBERS
)。
- 执行
- 持久化相关阻塞:
BGSAVE
/BGREWRITEAOF
时,fork子进程的瞬间(Copy-on-Write机制)会阻塞主线程,内存越大阻塞越久。- AOF同步策略为
always
时,每写命令触发fsync,IO延迟阻塞主线程。
- 内存与GC问题:
- 内存碎片率过高(
info memory
中mem_fragmentation_ratio > 1.5
),Redis需花时间整理内存。 - jemalloc内存分配器在大内存分配时可能产生阻塞。
- 内存碎片率过高(
- 系统级阻塞:
- CPU资源被抢占(如其他进程占用高CPU),Redis主线程无法调度。
- 网络中断或防火墙限制,导致客户端连接超时,命令堆积。
- 配置不当:
client-output-buffer-limit
设置过小,大结果集返回时被截断,导致客户端重试阻塞。
- 命令级阻塞:
67. Redis支持的连接数是多少?如何调整?
- 原理说明:
Redis的最大连接数受系统文件描述符限制和自身配置控制,默认值满足一般场景,高并发场景需调整。 - 连接数配置:
- 默认连接数:
- Redis默认最大客户端连接数为10000(
maxclients
参数),但实际受系统ulimit
(文件描述符上限)限制。
- Redis默认最大客户端连接数为10000(
- 调整方式:
- 步骤1:修改Redis配置(
redis.conf
):maxclients 100000 # 支持10万客户端连接
- 步骤2:调整系统文件描述符限制:
Redis进程的文件描述符需大于maxclients + 32
(预留内部连接),可通过ulimit
临时调整:
永久生效需修改ulimit -n 10032 # 至少为maxclients + 32
/etc/security/limits.conf
:* soft nofile 10032 * hard nofile 10032
- 步骤1:修改Redis配置(
- 默认连接数:
- 查看当前连接数:
127.0.0.1:6379> INFO clients # Clients connected_clients:100 # 当前连接数 maxclients:100000 # 最大连接数
68. Redis内存消耗分类有哪些?内存统计使用什么命令?
- 原理说明:
Redis内存消耗包括数据本身、元数据、进程开销等,合理统计可优化内存使用。 - 内存消耗分类:
- 数据内存:存储键值对的内存,占比最大(如String、Hash等数据结构)。
- 元数据内存:键的名称、过期时间、类型等信息,每个键约占32~96字节(取决于Redis版本和键名长度)。
- 进程内存:Redis进程本身的代码、常量、栈等内存,通常较小(几MB)。
- 内存碎片:内存分配器(如jemalloc)产生的碎片,
mem_fragmentation_ratio
指标反映碎片率(理想值1.0~1.5)。
- 内存统计命令:
INFO memory
:查看详细内存统计,关键指标包括:127.0.0.1:6379> INFO memory used_memory:1048576 # Redis分配的内存总量(字节) used_memory_rss:2097152 # 操作系统看到的内存(包括碎片) used_memory_dataset:524288 # 数据实际占用内存 mem_fragmentation_ratio:2.0 # 内存碎片率(used_memory_rss / used_memory) maxmemory:0 # 最大内存限制(0为无限制)
MEMORY USAGE <key>
:查看单个键的内存占用:127.0.0.1:6379> MEMORY USAGE user:1000 (integer) 88 # 键user:1000占用88字节
69. 如何设置Redis的内存上限?有什么作用?
- 原理说明:
设置内存上限可防止Redis无限制占用内存导致系统资源耗尽,结合内存淘汰策略控制数据规模。 - 设置方式:
- 配置文件设置(
redis.conf
):maxmemory 1024mb # 限制最大内存为1GB
- 动态设置(无需重启):
127.0.0.1:6379> CONFIG SET maxmemory 2048mb # 动态调整为2GB
- 配置文件设置(
- 作用:
- 防止内存溢出:避免Redis因数据量增长耗尽系统内存,导致进程被OOM killer杀死。
- 触发内存淘汰:当内存达到
maxmemory
且需写入新数据时,Redis会根据maxmemory-policy
淘汰旧数据(如LRU策略)。 - 资源隔离:在多实例部署时,限制单个Redis实例的内存占用,避免相互影响。
- 注意事项:
- 需预留部分内存(如10%)给Redis自身元数据和系统操作,避免频繁触发淘汰。
- 结合业务场景选择合适的淘汰策略(如
allkeys-lru
适合通用场景,volatile-lru
适合带过期时间的键)。
70. Redis报内存不足怎么处理?
- 原理说明:
Redis内存不足通常因达到maxmemory
限制且无法淘汰足够数据,导致新命令被拒绝(返回OOM command not allowed when used memory > 'maxmemory'
)。 - 处理措施:
- 临时扩容内存上限:
动态增加maxmemory
(需系统有足够空闲内存):127.0.0.1:6379> CONFIG SET maxmemory 4096mb # 从2GB扩容到4GB
- 优化内存淘汰策略:
- 若当前策略为
noeviction
(默认,不淘汰只拒绝写),改为allkeys-lru
(淘汰最近最少使用的键):127.0.0.1:6379> CONFIG SET maxmemory-policy allkeys-lru
- 若当前策略为
- 清理无效数据:
- 删除过期键:
KEYS *
结合DEL
(生产环境用SCAN
批量删除):# 批量删除过期键(示例) 127.0.0.1:6379> SCAN 0 MATCH * COUNT 1000 | xargs redis-cli DEL
- 清理大键:用
MEMORY USAGE
找出占用高的键,评估后删除或拆分。
- 删除过期键:
- 持久化与重启:
- 执行
BGSAVE
生成RDB快照,重启Redis并加载快照,利用重启释放内存碎片。
- 执行
- 架构扩展:
- 分片集群:将数据分散到多个节点,降低单节点内存压力。
- 冷热数据分离:低频访问数据迁移到数据库或对象存储,Redis只保留热点数据。
- 代码层面优化:
- 减少无效写入,避免存储冗余数据(如用
Bitmap
替代多个String存储布尔值)。
- 减少无效写入,避免存储冗余数据(如用
- 临时扩容内存上限:
二、100道面试题目录列表
文章序号 | Redis面试题100道 |
---|---|
1 | Redis面试题及详细答案100道(01-15) |
2 | Redis面试题及详细答案100道(16-32) |
3 | Redis面试题及详细答案100道(33-48) |
4 | Redis面试题及详细答案100道(49-60) |
5 | Redis面试题及详细答案100道(61-70) |
6 | Redis面试题及详细答案100道(71-85) |
7 | Redis面试题及详细答案100道(86-100) |