写在前面Redis以高性能著称但在实际生产环境中不当的使用方式可能导致性能急剧下降。今天我们来系统学习Redis性能优化的方法包括慢查询分析、内存优化、网络优化和大key治理。文章目录写在前面一、慢查询分析1.1 什么是慢查询1.2 SLOWLOG配置1.3 查看慢查询日志1.4 常见慢查询命令1.5 慢查询优化案例二、内存优化2.1 内存使用分析2.2 内存碎片问题2.3 对象编码优化2.4 内存优化技巧三、网络优化3.1 Pipeline管道3.2 Lua脚本优化3.3 连接池优化3.4 网络配置优化四、大key治理4.1 什么是大key4.2 大key的危害4.3 大key发现4.4 大key删除4.5 大key预防五、踩坑提醒5.1 KEYS命令在生产环境禁用5.2 避免使用SELECT切换数据库5.3 避免大量key同时过期5.4 避免使用阻塞命令5.5 常见性能问题汇总六、性能监控6.1 关键监控指标6.2 监控命令6.3 监控工具七、面试高频考点7.1 如何排查Redis性能问题7.2 Redis内存优化有哪些方法7.3 为什么KEYS命令在生产环境禁用7.4 如何处理大key八、参考资料九、互动话题一、慢查询分析1.1 什么是慢查询实际场景某天运维收到告警Redis响应时间飙升需要排查是哪些命令导致的。慢查询定义执行时间超过指定阈值的命令。1.2 SLOWLOG配置# 查看慢查询配置 CONFIG GET slowlog-* # 设置慢查询阈值微秒 CONFIG SET slowlog-log-slower-than 10000 # 设置慢查询日志最大条数 CONFIG SET slowlog-max-len 128配置说明配置项说明默认值slowlog-log-slower-than慢查询阈值微秒10000slowlog-max-len慢查询日志最大条数1281.3 查看慢查询日志# 查看慢查询日志 SLOWLOG GET # 查看最近10条慢查询 SLOWLOG GET 10 # 查看慢查询日志条数 SLOWLOG LEN # 清空慢查询日志 SLOWLOG RESET慢查询日志格式1) 1) (integer) 1 # 日志ID 2) (integer) 1703123456 # 执行时间戳 3) (integer) 15000 # 执行耗时微秒 4) 1) KEYS # 执行的命令 2) user:* 5) 127.0.0.1:54321 # 客户端地址 6) client-name # 客户端名称1.4 常见慢查询命令踩坑提醒以下命令在生产环境慎用或禁用。命令时间复杂度说明替代方案KEYSO(N)遍历所有keySCANHGETALLO(N)获取所有字段HSCANSMEMBERSO(N)获取所有成员SSCANLRANGEO(N)获取列表范围分批获取DELO(N)删除大keyUNLINKFLUSHALLO(N)清空所有数据慎用1.5 慢查询优化案例实际场景KEYS命令导致Redis阻塞。问题代码# 危险遍历所有key KEYS user:*优化方案# 使用SCAN命令分批遍历 SCAN 0 MATCH user:* COUNT 100 # 返回下一个游标和匹配的key列表Java代码示例publicListStringscanKeys(Stringpattern){ListStringkeysnewArrayList();ScanOptionsoptionsScanOptions.scanOptions().match(pattern).count(100).build();CursorStringcursorredisTemplate.scan(options);while(cursor.hasNext()){keys.add(cursor.next());}returnkeys;}二、内存优化2.1 内存使用分析经验之谈定期分析Redis内存使用情况及时发现内存问题。# 查看内存使用情况 INFO memory # 关键指标 # used_memory: 已使用内存 # used_memory_rss: 系统分配内存 # used_memory_peak: 内存使用峰值 # mem_fragmentation_ratio: 内存碎片率内存相关指标指标说明理想值used_memoryRedis分配的内存总量-used_memory_rss操作系统分配给Redis的内存-mem_fragmentation_ratio内存碎片率rss/used1.0-1.5used_memory_peak内存使用峰值-2.2 内存碎片问题踩坑提醒内存碎片率过高会浪费内存过低可能导致OOM。内存碎片产生原因频繁的内存分配和释放数据大小不一致Redis的内存分配器jemalloc内存碎片率分析碎片率说明建议 1.0Redis使用了swap检查系统内存1.0-1.5正常无需处理 1.5碎片较多考虑整理内存碎片整理# 开启自动碎片整理 CONFIG SET activedefrag yes # 设置碎片整理阈值 CONFIG SET active-defrag-ignore-bytes 100mb CONFIG SET active-defrag-threshold-lower 102.3 对象编码优化面试高频考点Redis会根据数据类型和大小自动选择编码方式了解编码有助于优化内存。数据类型编码表数据类型编码方式条件内存效率Stringint整数且范围在long内最高Stringembstr字符串长度≤44字节高Stringraw字符串长度44字节中Hashziplist元素数≤512值≤64字节高Hashhashtable不满足ziplist条件中Listquicklist3.2版本默认高Setintset全是整数元素数≤512高Sethashtable不满足intset条件中ZSetskiplist元素数≤128值≤64字节高ZSetskiplistdict不满足条件中查看编码方式# 查看key的编码方式 OBJECT ENCODING mykey2.4 内存优化技巧实际场景存储100万个用户信息如何优化内存占用优化方案对比方案内存占用说明String存储JSON高每个key都有元数据开销Hash存储中多个字段共享一个keyHash ziplist低小对象使用压缩编码优化示例# 方案1String存储不推荐 SET user:1 {id:1,name:张三,age:25} SET user:2 {id:2,name:李四,age:30} # 方案2Hash存储推荐 HSET user:1 id 1 name 张三 age 25 HSET user:2 id 2 name 李四 age 30 # 方案3压缩Hash最优 # 控制字段数量和大小使用ziplist编码 HSET user:1 id 1 name 张三 age 25 # 确保元素数≤512值长度≤64字节内存优化建议优化项建议Key长度尽量短使用缩写数据结构选择合适的编码方式过期策略设置合理的过期时间数据压缩使用压缩编码大key拆分避免存储大对象三、网络优化3.1 Pipeline管道实际场景需要批量插入10000条数据逐条执行太慢如何优化Pipeline原理传统方式 Client → Redis → Client → Redis → Client → Redis 每次请求都需要网络往返 Pipeline方式 Client → Redis → Redis → Redis → Client 一次网络往返执行多个命令Pipeline性能对比方式10000次SET耗时逐条执行约10秒Pipeline约0.1秒提升100倍Java实现PipelinepublicvoidbatchInsert(MapString,Stringdata){redisTemplate.executePipelined((RedisCallbackObject)connection-{data.forEach((key,value)-{connection.set(key.getBytes(),value.getBytes());});returnnull;});}Pipeline注意事项注意点说明批量大小控制每次Pipeline的命令数量建议100-1000原子性Pipeline中的命令不是原子的返回值注意返回值的顺序3.2 Lua脚本优化经验之谈将多个命令封装成Lua脚本减少网络往返。-- 扣减库存Lua脚本localstockredis.call(GET,KEYS[1])iftonumber(stock)0thenredis.call(DECR,KEYS[1])return1elsereturn0endJava调用Lua脚本Stringscriptlocal stock redis.call(GET, KEYS[1]) if tonumber(stock) 0 then redis.call(DECR, KEYS[1]) return 1 else return 0 end;RedisScriptLongredisScriptRedisScript.of(script,Long.class);LongresultredisTemplate.execute(redisScript,Collections.singletonList(stock:product:123));3.3 连接池优化踩坑提醒连接池配置不当可能导致连接泄漏或性能下降。Jedis连接池配置JedisPoolConfigconfignewJedisPoolConfig();// 最大连接数config.setMaxTotal(200);// 最大空闲连接数config.setMaxIdle(50);// 最小空闲连接数config.setMinIdle(10);// 获取连接最大等待时间毫秒config.setMaxWaitMillis(3000);// 连接有效性检查config.setTestOnBorrow(true);config.setTestOnReturn(false);config.setTestWhileIdle(true);JedisPoolpoolnewJedisPool(config,127.0.0.1,6379);Lettuce连接池配置RedisClientclientRedisClient.create(redis://127.0.0.1:6379);StatefulRedisConnectionString,Stringconnectionclient.connect();// Lettuce使用Netty单个连接即可支持高并发// 如需连接池使用ConnectionPoolSupportGenericObjectPoolStatefulRedisConnectionString,StringpoolConnectionPoolSupport.createGenericObjectPool(()-client.connect(),newGenericObjectPoolConfig());连接池配置建议参数建议值说明maxTotal200最大连接数maxIdle50最大空闲连接minIdle10最小空闲连接maxWaitMillis3000获取连接超时testOnBorrowtrue获取时检查连接3.4 网络配置优化Redis配置优化# 绑定IP bind 0.0.0.0 # 保护模式 protected-mode no # TCP端口 port 6379 # TCP连接队列 tcp-backlog 511 # TCP保活 tcp-keepalive 300 # 最大客户端连接数 maxclients 10000 # 输出缓冲区限制 client-output-buffer-limit normal 0 0 0 client-output-buffer-limit replica 256mb 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60四、大key治理4.1 什么是大key踩坑提醒大key是Redis性能杀手必须及时发现和处理。大key定义类型大key标准Stringvalue 10KBHash元素数 5000List元素数 5000Set元素数 5000ZSet元素数 50004.2 大key的危害危害说明内存占用大单个key占用过多内存网络阻塞传输大key阻塞网络过期阻塞删除大key阻塞主线程迁移阻塞大key迁移影响性能4.3 大key发现方法1使用redis-cli --bigkeysredis-cli--bigkeys# 输出示例# -------- summary -------# Sampled 100000 keys in the keyspace!# Biggest string found user:10000 has 10240 bytes# Biggest hash found session:5000 has 10000 fields方法2使用MEMORY USAGE命令# 查看key占用内存 MEMORY USAGE mykey # 返回字节数 # 分析多个key MEMORY USAGE user:1 MEMORY USAGE user:2方法3使用RDB分析工具# 使用rdb-tools分析rdb--commandjson /var/lib/redis/dump.rdbdump.json4.4 大key删除踩坑提醒直接使用DEL删除大key会阻塞Redis主线程。安全删除大key# String类型使用UNLINK异步删除 UNLINK bigkey # Hash类型分批删除 HSCAN bigkey 0 COUNT 100 HDEL bigkey field1 field2 ... # List类型分批删除 LTRIM bigkey 0 -101 LTRIM bigkey 0 -101 # 直到删除完毕 # Set类型分批删除 SSCAN bigkey 0 COUNT 100 SREM bigkey member1 member2 ... # ZSet类型分批删除 ZREMRANGEBYRANK bigkey 0 99Java代码示例// 安全删除Hash大keypublicvoiddeleteBigHash(Stringkey){ScanOptionsoptionsScanOptions.scanOptions().count(100).build();CursorMap.EntryObject,ObjectcursorredisTemplate.opsForHash().scan(key,options);ListObjectfieldsnewArrayList();while(cursor.hasNext()){fields.add(cursor.next().getKey());if(fields.size()100){redisTemplate.opsForHash().delete(key,fields.toArray());fields.clear();}}if(!fields.isEmpty()){redisTemplate.opsForHash().delete(key,fields.toArray());}}4.5 大key预防预防措施说明拆分大key将大key拆分成多个小key控制元素数量Hash/Set/List元素数控制在5000以内控制value大小String类型value控制在10KB以内监控告警定期扫描大key并告警代码审查代码层面禁止写入大key大key拆分示例# 拆分前一个大Hash HSET user:1000:profile name 张三 age 25 city 北京 ... # 拆分后多个小Hash HSET user:1000:basic name 张三 age 25 HSET user:1000:address city 北京 province 北京 HSET user:1000:contact phone 13800138000五、踩坑提醒5.1 KEYS命令在生产环境禁用踩坑提醒KEYS命令会阻塞Redis生产环境绝对禁止使用替代方案# 使用SCAN替代KEYS SCAN 0 MATCH user:* COUNT 1005.2 避免使用SELECT切换数据库# 不推荐使用多个数据库 SELECT 0 SELECT 1 SELECT 2 # 推荐使用key前缀区分 SET user:1:name 张三 SET order:1:id 123455.3 避免大量key同时过期// 不推荐相同过期时间redisTemplate.expire(key1,3600,TimeUnit.SECONDS);redisTemplate.expire(key2,3600,TimeUnit.SECONDS);// 推荐随机过期时间RandomrandomnewRandom();intbaseExpire3600;intrandomExpirerandom.nextInt(600);redisTemplate.expire(key1,baseExpirerandomExpire,TimeUnit.SECONDS);5.4 避免使用阻塞命令命令说明替代方案KEYS遍历所有keySCANHGETALL获取所有字段HSCANSMEMBERS获取所有成员SSCANBLPOP阻塞弹出LPOP 轮询5.5 常见性能问题汇总问题原因解决方案响应慢慢查询分析SLOWLOG内存高内存碎片开启碎片整理CPU高大key操作拆分大key网络阻塞大value压缩或拆分连接超时连接池配置不当优化连接池六、性能监控6.1 关键监控指标指标说明告警阈值used_memory内存使用量 80% maxmemorymem_fragmentation_ratio内存碎片率 1.5connected_clients客户端连接数 maxclients * 0.8blocked_clients阻塞客户端数 10instantaneous_ops_per_sec当前QPS监控趋势slowlog_len慢查询数量 0 告警expired_keys过期key数量监控趋势evicted_keys驱逐key数量 0 告警6.2 监控命令# 查看服务器信息 INFO # 查看内存信息 INFO memory # 查看统计信息 INFO stats # 查看客户端连接 CLIENT LIST # 查看慢查询 SLOWLOG GET 10 # 实时监控命令 MONITOR6.3 监控工具工具说明Redis-cli官方命令行工具RedisInsight官方可视化工具Prometheus Grafana监控告警平台Redis ExporterRedis指标导出器Redis-stat实时监控工具七、面试高频考点7.1 如何排查Redis性能问题答案查看慢查询日志SLOWLOG GET 10检查内存使用INFO memory检查大keyredis-cli--bigkeys检查客户端连接CLIENT LIST检查命令执行情况INFO stats使用MONITOR实时监控MONITOR7.2 Redis内存优化有哪些方法答案选择合适的数据结构使用编码效率高的数据类型控制key长度使用简短的key名使用压缩编码ziplist、intset等设置过期时间及时清理无用数据开启内存碎片整理activedefrag避免大key拆分大key使用Hash替代String多个字段存储在一起7.3 为什么KEYS命令在生产环境禁用答案时间复杂度O(N)需要遍历所有key阻塞主线程Redis单线程模型KEYS执行期间无法处理其他请求影响服务可用性大量key时可能导致服务不可用替代方案使用SCAN命令分批遍历7.4 如何处理大key答案发现大keyredis-cli --bigkeysMEMORY USAGE命令RDB分析工具删除大key使用UNLINK异步删除分批删除HSCAN HDEL预防大key拆分大key控制元素数量代码审查八、参考资料Redis官方文档 - 内存优化Redis官方文档 - 慢查询日志Redis性能优化最佳实践九、互动话题你在生产环境遇到过Redis性能问题吗是如何排查和解决的你们团队是如何监控Redis的使用了哪些工具对于大key治理你有什么好的经验和建议欢迎在评论区分享你的实战经验下期预告Day15我们将进行Redis面试高频考点汇总全面回顾Redis核心知识点为面试做好准备。
【Redis】Redis性能优化Day14(2026年)
发布时间:2026/6/7 11:16:09
写在前面Redis以高性能著称但在实际生产环境中不当的使用方式可能导致性能急剧下降。今天我们来系统学习Redis性能优化的方法包括慢查询分析、内存优化、网络优化和大key治理。文章目录写在前面一、慢查询分析1.1 什么是慢查询1.2 SLOWLOG配置1.3 查看慢查询日志1.4 常见慢查询命令1.5 慢查询优化案例二、内存优化2.1 内存使用分析2.2 内存碎片问题2.3 对象编码优化2.4 内存优化技巧三、网络优化3.1 Pipeline管道3.2 Lua脚本优化3.3 连接池优化3.4 网络配置优化四、大key治理4.1 什么是大key4.2 大key的危害4.3 大key发现4.4 大key删除4.5 大key预防五、踩坑提醒5.1 KEYS命令在生产环境禁用5.2 避免使用SELECT切换数据库5.3 避免大量key同时过期5.4 避免使用阻塞命令5.5 常见性能问题汇总六、性能监控6.1 关键监控指标6.2 监控命令6.3 监控工具七、面试高频考点7.1 如何排查Redis性能问题7.2 Redis内存优化有哪些方法7.3 为什么KEYS命令在生产环境禁用7.4 如何处理大key八、参考资料九、互动话题一、慢查询分析1.1 什么是慢查询实际场景某天运维收到告警Redis响应时间飙升需要排查是哪些命令导致的。慢查询定义执行时间超过指定阈值的命令。1.2 SLOWLOG配置# 查看慢查询配置 CONFIG GET slowlog-* # 设置慢查询阈值微秒 CONFIG SET slowlog-log-slower-than 10000 # 设置慢查询日志最大条数 CONFIG SET slowlog-max-len 128配置说明配置项说明默认值slowlog-log-slower-than慢查询阈值微秒10000slowlog-max-len慢查询日志最大条数1281.3 查看慢查询日志# 查看慢查询日志 SLOWLOG GET # 查看最近10条慢查询 SLOWLOG GET 10 # 查看慢查询日志条数 SLOWLOG LEN # 清空慢查询日志 SLOWLOG RESET慢查询日志格式1) 1) (integer) 1 # 日志ID 2) (integer) 1703123456 # 执行时间戳 3) (integer) 15000 # 执行耗时微秒 4) 1) KEYS # 执行的命令 2) user:* 5) 127.0.0.1:54321 # 客户端地址 6) client-name # 客户端名称1.4 常见慢查询命令踩坑提醒以下命令在生产环境慎用或禁用。命令时间复杂度说明替代方案KEYSO(N)遍历所有keySCANHGETALLO(N)获取所有字段HSCANSMEMBERSO(N)获取所有成员SSCANLRANGEO(N)获取列表范围分批获取DELO(N)删除大keyUNLINKFLUSHALLO(N)清空所有数据慎用1.5 慢查询优化案例实际场景KEYS命令导致Redis阻塞。问题代码# 危险遍历所有key KEYS user:*优化方案# 使用SCAN命令分批遍历 SCAN 0 MATCH user:* COUNT 100 # 返回下一个游标和匹配的key列表Java代码示例publicListStringscanKeys(Stringpattern){ListStringkeysnewArrayList();ScanOptionsoptionsScanOptions.scanOptions().match(pattern).count(100).build();CursorStringcursorredisTemplate.scan(options);while(cursor.hasNext()){keys.add(cursor.next());}returnkeys;}二、内存优化2.1 内存使用分析经验之谈定期分析Redis内存使用情况及时发现内存问题。# 查看内存使用情况 INFO memory # 关键指标 # used_memory: 已使用内存 # used_memory_rss: 系统分配内存 # used_memory_peak: 内存使用峰值 # mem_fragmentation_ratio: 内存碎片率内存相关指标指标说明理想值used_memoryRedis分配的内存总量-used_memory_rss操作系统分配给Redis的内存-mem_fragmentation_ratio内存碎片率rss/used1.0-1.5used_memory_peak内存使用峰值-2.2 内存碎片问题踩坑提醒内存碎片率过高会浪费内存过低可能导致OOM。内存碎片产生原因频繁的内存分配和释放数据大小不一致Redis的内存分配器jemalloc内存碎片率分析碎片率说明建议 1.0Redis使用了swap检查系统内存1.0-1.5正常无需处理 1.5碎片较多考虑整理内存碎片整理# 开启自动碎片整理 CONFIG SET activedefrag yes # 设置碎片整理阈值 CONFIG SET active-defrag-ignore-bytes 100mb CONFIG SET active-defrag-threshold-lower 102.3 对象编码优化面试高频考点Redis会根据数据类型和大小自动选择编码方式了解编码有助于优化内存。数据类型编码表数据类型编码方式条件内存效率Stringint整数且范围在long内最高Stringembstr字符串长度≤44字节高Stringraw字符串长度44字节中Hashziplist元素数≤512值≤64字节高Hashhashtable不满足ziplist条件中Listquicklist3.2版本默认高Setintset全是整数元素数≤512高Sethashtable不满足intset条件中ZSetskiplist元素数≤128值≤64字节高ZSetskiplistdict不满足条件中查看编码方式# 查看key的编码方式 OBJECT ENCODING mykey2.4 内存优化技巧实际场景存储100万个用户信息如何优化内存占用优化方案对比方案内存占用说明String存储JSON高每个key都有元数据开销Hash存储中多个字段共享一个keyHash ziplist低小对象使用压缩编码优化示例# 方案1String存储不推荐 SET user:1 {id:1,name:张三,age:25} SET user:2 {id:2,name:李四,age:30} # 方案2Hash存储推荐 HSET user:1 id 1 name 张三 age 25 HSET user:2 id 2 name 李四 age 30 # 方案3压缩Hash最优 # 控制字段数量和大小使用ziplist编码 HSET user:1 id 1 name 张三 age 25 # 确保元素数≤512值长度≤64字节内存优化建议优化项建议Key长度尽量短使用缩写数据结构选择合适的编码方式过期策略设置合理的过期时间数据压缩使用压缩编码大key拆分避免存储大对象三、网络优化3.1 Pipeline管道实际场景需要批量插入10000条数据逐条执行太慢如何优化Pipeline原理传统方式 Client → Redis → Client → Redis → Client → Redis 每次请求都需要网络往返 Pipeline方式 Client → Redis → Redis → Redis → Client 一次网络往返执行多个命令Pipeline性能对比方式10000次SET耗时逐条执行约10秒Pipeline约0.1秒提升100倍Java实现PipelinepublicvoidbatchInsert(MapString,Stringdata){redisTemplate.executePipelined((RedisCallbackObject)connection-{data.forEach((key,value)-{connection.set(key.getBytes(),value.getBytes());});returnnull;});}Pipeline注意事项注意点说明批量大小控制每次Pipeline的命令数量建议100-1000原子性Pipeline中的命令不是原子的返回值注意返回值的顺序3.2 Lua脚本优化经验之谈将多个命令封装成Lua脚本减少网络往返。-- 扣减库存Lua脚本localstockredis.call(GET,KEYS[1])iftonumber(stock)0thenredis.call(DECR,KEYS[1])return1elsereturn0endJava调用Lua脚本Stringscriptlocal stock redis.call(GET, KEYS[1]) if tonumber(stock) 0 then redis.call(DECR, KEYS[1]) return 1 else return 0 end;RedisScriptLongredisScriptRedisScript.of(script,Long.class);LongresultredisTemplate.execute(redisScript,Collections.singletonList(stock:product:123));3.3 连接池优化踩坑提醒连接池配置不当可能导致连接泄漏或性能下降。Jedis连接池配置JedisPoolConfigconfignewJedisPoolConfig();// 最大连接数config.setMaxTotal(200);// 最大空闲连接数config.setMaxIdle(50);// 最小空闲连接数config.setMinIdle(10);// 获取连接最大等待时间毫秒config.setMaxWaitMillis(3000);// 连接有效性检查config.setTestOnBorrow(true);config.setTestOnReturn(false);config.setTestWhileIdle(true);JedisPoolpoolnewJedisPool(config,127.0.0.1,6379);Lettuce连接池配置RedisClientclientRedisClient.create(redis://127.0.0.1:6379);StatefulRedisConnectionString,Stringconnectionclient.connect();// Lettuce使用Netty单个连接即可支持高并发// 如需连接池使用ConnectionPoolSupportGenericObjectPoolStatefulRedisConnectionString,StringpoolConnectionPoolSupport.createGenericObjectPool(()-client.connect(),newGenericObjectPoolConfig());连接池配置建议参数建议值说明maxTotal200最大连接数maxIdle50最大空闲连接minIdle10最小空闲连接maxWaitMillis3000获取连接超时testOnBorrowtrue获取时检查连接3.4 网络配置优化Redis配置优化# 绑定IP bind 0.0.0.0 # 保护模式 protected-mode no # TCP端口 port 6379 # TCP连接队列 tcp-backlog 511 # TCP保活 tcp-keepalive 300 # 最大客户端连接数 maxclients 10000 # 输出缓冲区限制 client-output-buffer-limit normal 0 0 0 client-output-buffer-limit replica 256mb 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60四、大key治理4.1 什么是大key踩坑提醒大key是Redis性能杀手必须及时发现和处理。大key定义类型大key标准Stringvalue 10KBHash元素数 5000List元素数 5000Set元素数 5000ZSet元素数 50004.2 大key的危害危害说明内存占用大单个key占用过多内存网络阻塞传输大key阻塞网络过期阻塞删除大key阻塞主线程迁移阻塞大key迁移影响性能4.3 大key发现方法1使用redis-cli --bigkeysredis-cli--bigkeys# 输出示例# -------- summary -------# Sampled 100000 keys in the keyspace!# Biggest string found user:10000 has 10240 bytes# Biggest hash found session:5000 has 10000 fields方法2使用MEMORY USAGE命令# 查看key占用内存 MEMORY USAGE mykey # 返回字节数 # 分析多个key MEMORY USAGE user:1 MEMORY USAGE user:2方法3使用RDB分析工具# 使用rdb-tools分析rdb--commandjson /var/lib/redis/dump.rdbdump.json4.4 大key删除踩坑提醒直接使用DEL删除大key会阻塞Redis主线程。安全删除大key# String类型使用UNLINK异步删除 UNLINK bigkey # Hash类型分批删除 HSCAN bigkey 0 COUNT 100 HDEL bigkey field1 field2 ... # List类型分批删除 LTRIM bigkey 0 -101 LTRIM bigkey 0 -101 # 直到删除完毕 # Set类型分批删除 SSCAN bigkey 0 COUNT 100 SREM bigkey member1 member2 ... # ZSet类型分批删除 ZREMRANGEBYRANK bigkey 0 99Java代码示例// 安全删除Hash大keypublicvoiddeleteBigHash(Stringkey){ScanOptionsoptionsScanOptions.scanOptions().count(100).build();CursorMap.EntryObject,ObjectcursorredisTemplate.opsForHash().scan(key,options);ListObjectfieldsnewArrayList();while(cursor.hasNext()){fields.add(cursor.next().getKey());if(fields.size()100){redisTemplate.opsForHash().delete(key,fields.toArray());fields.clear();}}if(!fields.isEmpty()){redisTemplate.opsForHash().delete(key,fields.toArray());}}4.5 大key预防预防措施说明拆分大key将大key拆分成多个小key控制元素数量Hash/Set/List元素数控制在5000以内控制value大小String类型value控制在10KB以内监控告警定期扫描大key并告警代码审查代码层面禁止写入大key大key拆分示例# 拆分前一个大Hash HSET user:1000:profile name 张三 age 25 city 北京 ... # 拆分后多个小Hash HSET user:1000:basic name 张三 age 25 HSET user:1000:address city 北京 province 北京 HSET user:1000:contact phone 13800138000五、踩坑提醒5.1 KEYS命令在生产环境禁用踩坑提醒KEYS命令会阻塞Redis生产环境绝对禁止使用替代方案# 使用SCAN替代KEYS SCAN 0 MATCH user:* COUNT 1005.2 避免使用SELECT切换数据库# 不推荐使用多个数据库 SELECT 0 SELECT 1 SELECT 2 # 推荐使用key前缀区分 SET user:1:name 张三 SET order:1:id 123455.3 避免大量key同时过期// 不推荐相同过期时间redisTemplate.expire(key1,3600,TimeUnit.SECONDS);redisTemplate.expire(key2,3600,TimeUnit.SECONDS);// 推荐随机过期时间RandomrandomnewRandom();intbaseExpire3600;intrandomExpirerandom.nextInt(600);redisTemplate.expire(key1,baseExpirerandomExpire,TimeUnit.SECONDS);5.4 避免使用阻塞命令命令说明替代方案KEYS遍历所有keySCANHGETALL获取所有字段HSCANSMEMBERS获取所有成员SSCANBLPOP阻塞弹出LPOP 轮询5.5 常见性能问题汇总问题原因解决方案响应慢慢查询分析SLOWLOG内存高内存碎片开启碎片整理CPU高大key操作拆分大key网络阻塞大value压缩或拆分连接超时连接池配置不当优化连接池六、性能监控6.1 关键监控指标指标说明告警阈值used_memory内存使用量 80% maxmemorymem_fragmentation_ratio内存碎片率 1.5connected_clients客户端连接数 maxclients * 0.8blocked_clients阻塞客户端数 10instantaneous_ops_per_sec当前QPS监控趋势slowlog_len慢查询数量 0 告警expired_keys过期key数量监控趋势evicted_keys驱逐key数量 0 告警6.2 监控命令# 查看服务器信息 INFO # 查看内存信息 INFO memory # 查看统计信息 INFO stats # 查看客户端连接 CLIENT LIST # 查看慢查询 SLOWLOG GET 10 # 实时监控命令 MONITOR6.3 监控工具工具说明Redis-cli官方命令行工具RedisInsight官方可视化工具Prometheus Grafana监控告警平台Redis ExporterRedis指标导出器Redis-stat实时监控工具七、面试高频考点7.1 如何排查Redis性能问题答案查看慢查询日志SLOWLOG GET 10检查内存使用INFO memory检查大keyredis-cli--bigkeys检查客户端连接CLIENT LIST检查命令执行情况INFO stats使用MONITOR实时监控MONITOR7.2 Redis内存优化有哪些方法答案选择合适的数据结构使用编码效率高的数据类型控制key长度使用简短的key名使用压缩编码ziplist、intset等设置过期时间及时清理无用数据开启内存碎片整理activedefrag避免大key拆分大key使用Hash替代String多个字段存储在一起7.3 为什么KEYS命令在生产环境禁用答案时间复杂度O(N)需要遍历所有key阻塞主线程Redis单线程模型KEYS执行期间无法处理其他请求影响服务可用性大量key时可能导致服务不可用替代方案使用SCAN命令分批遍历7.4 如何处理大key答案发现大keyredis-cli --bigkeysMEMORY USAGE命令RDB分析工具删除大key使用UNLINK异步删除分批删除HSCAN HDEL预防大key拆分大key控制元素数量代码审查八、参考资料Redis官方文档 - 内存优化Redis官方文档 - 慢查询日志Redis性能优化最佳实践九、互动话题你在生产环境遇到过Redis性能问题吗是如何排查和解决的你们团队是如何监控Redis的使用了哪些工具对于大key治理你有什么好的经验和建议欢迎在评论区分享你的实战经验下期预告Day15我们将进行Redis面试高频考点汇总全面回顾Redis核心知识点为面试做好准备。