redis 内存使用率高居高不下,如何分析 key占用情况

发布于:2025-08-14 ⋅ 阅读:(12) ⋅ 点赞:(0)

Redis内存使用率居高不下,开发要求帮提供下Redis内存占用的key的占比的信息,运维如何处理呢?

当Redis内存使用率过高时,分析key的占用情况可以按以下步骤进行,结合Redis内置命令和第三方工具定位问题:

一、先了解整体内存状态

首先通过 INFO memory 命令查看Redis整体内存使用情况,重点关注以下指标:

redis-cli info memory

关键指标解析:

  • used_memory:Redis实际使用的内存(字节)
  • used_memory_peak:内存使用峰值
  • used_memory_lua:Lua脚本引擎使用的内存
  • mem_fragmentation_ratio:内存碎片率(理想值1.0~1.5,过高说明碎片严重)
  • maxmemory:配置的最大内存限制(若为0则无限制)
  • expired_keys:已过期的key数量(判断是否有大量过期key未清理)

内存使用率高,有可能是“大key”占用的多,也有可能是小key的数量多导致的,需要根据实际情况分析。

二、定位“大key”(占用内存多的key)

大key是导致内存过高的常见原因(如超大字符串、包含百万级元素的哈希/集合等)。

1. 用redis-cli的–bigkeys快速扫描

Redis自带的 redis-cli 提供 --bigkeys 选项,可扫描所有key,按类型统计最大的key(字符串按字节数,集合/哈希等按元素数):

redis-cli --bigkeys -i 0.1  # -i 0.1表示每扫描100个key休息0.1秒,降低对Redis的影响

输出示例:

# 字符串最大key(字节数)
Biggest string found 'user:1000' has 1048576 bytes

# 哈希最大key(字段数)
Biggest hash   found 'products' has 50000 fields

注意

  • 此命令会遍历所有key,可能阻塞Redis(尤其是大实例),建议在低峰期执行。
  • 仅统计“元素数”或“字节数”,不直接返回内存占用(但可作为大key的初步筛选)。
2. 用MEMORY USAGE命令精确查看单个key的内存

--bigkeys 筛选出的可疑key,用 MEMORY USAGE 命令查看其实际占用的内存(包括数据结构本身的开销):

# 查看key为"user:1000"的内存占用(字节)
redis-cli memory usage "user:1000"

说明:内存占用不仅包含数据本身,还包括Redis内部的元数据(如key名称、过期时间、数据结构的指针等)。

3. 批量扫描所有key并统计内存(适合脚本自动化)

若需批量分析大量key,可结合 SCAN 命令(非阻塞遍历)和 MEMORY USAGE 批量统计:

# 示例:用bash脚本扫描并记录内存超过1MB的key
redis-cli scan 0 MATCH "*" COUNT 1000 | while read -r key; do
  size=$(redis-cli memory usage "$key")
  if [ "$size" -gt 1048576 ]; then  # 1MB = 1048576字节
    echo "Key: $key, Size: $size bytes" >> big_keys.txt
  fi
done

注意SCANCOUNT 参数可调整(默认10),值越大扫描越快但消耗资源越多。

三、离线分析RDB文件 - Redis 7.0 以下版本(更全面,不影响在线服务)

如果Redis开启了RDB持久化(默认开启),可通过解析RDB文件获取所有key的内存详情(推荐用 redis-rdb-tools 工具)。

redis-rdb-tools 是一个 python 的解析 rdb 文件的工具。 源码地址: https://github.com/sripathikrishnan/redis-rdb-tools/

1. 安装redis-rdb-tools
pip install rdbtools python-lzf
2. 解析RDB文件生成内存报告
# 导出所有key的内存信息(包括类型、大小、过期时间等)
rdb -c memory /var/lib/redis/dump.rdb > redis_memory_report.csv

生成的CSV文件包含以下字段:

  • database:所属数据库
  • type:key的类型(string/hash/list等)
  • key:key名称
  • size_in_bytes:总内存占用(字节)
  • expiry:过期时间(时间戳,-1表示永不过期)
3. 分析报告

用Excel或命令行筛选排序,找出内存占用最高的key:

# 按内存占用降序排序,取前100条
sort -t ',' -k 4nr redis_memory_report.csv | head -n 100

四、离线分析RDB文件 - Redis 7.0 以上版本(更全面,不影响在线服务)

可惜的是redis-rdb-tools 工具,后期没有新的更新,基于Redis 7.0 版本生成的 rdb文件解析会报错:
Exception: ('verify_version', 'Invalid RDB version number 10')

在这里插入图片描述

对于Redis7版本的rdb文件,可以使用 golang版本的工具:
https://github.com/HDT3213/rdb

RDB 文件的整体结构:
https://www.cnblogs.com/Finley/p/16251360.html

五、分析key的分布与过期情况

除了大key,还需关注:

  • 是否有大量无过期时间的key:导致内存持续增长。
    SCAN 结合 TTL 命令统计:

    # 统计永不过期的key数量(TTL为-1)
    redis-cli scan 0 MATCH "*" COUNT 1000 | while read -r key; do
      ttl=$(redis-cli ttl "$key")
      if [ "$ttl" -eq -1 ]; then
        echo "$key" >> no_expire_keys.txt
      fi
    done
    
  • key的类型分布:某些类型(如未压缩的哈希)可能比其他类型更耗内存。
    INFO keyspace 查看各类型key的数量:

    redis-cli info keyspace
    

六、总结与优化建议

  1. 清理大key:对非必要的大key直接删除,或拆分(如将大哈希拆分为多个小哈希)。
  2. 设置合理的过期时间:对临时数据(如缓存)通过 EXPIRE 设置过期时间,利用Redis自动清理。
  3. 优化数据结构
    • 字符串:若存储JSON等结构化数据,可改用哈希(hash)节省内存。
    • 哈希/集合:启用压缩列表(ziplist)配置(如 hash-max-ziplist-entries 512),小数据更高效。
  4. 处理内存碎片:若 mem_fragmentation_ratio 过高(如>1.5),可重启Redis(需提前做好持久化)。

网站公告

今日签到

点亮在社区的每一天
去签到