是指当 Redis 的字符串类型过大,非字符串类型元素过多。

影响
  • Redis 阻塞 :因为 Redis 单线程特性,如果操作某个 Bigkey 耗时比较久,则后面的请求会被阻塞。

  • 内存空间不均匀 :比如在 Redis cluster 或者 codis 中,会造成节点的内存使用不均匀。

  • 过期时可能阻塞 :如果 Bigkey 设置了过期时间,当过期后,这个 key 会被删除,假如没有使用 Redis 4.0 的过期异步删除,就会存在阻塞 Redis 的可能性,并且慢查询中查不到(因为这个删除是内部循环事件)。

  • 导致倾斜 :某个实例上正好保存了 bigkey。bigkey 的 value 值很大(String 类型),或者是 bigkey 保存了大量集合元素(集合类型),会导致这个实例的数据量增加,内存资源消耗也相应增加。实例的处理压力就会增大,速度变慢,甚至还可能会引起这个实例的内存资源耗尽,从而崩溃。

排查工具

BIGKEYS 命令

redis-cli --bigkeys

Debug Object

debug object 【key】

输出:

  • Value at:0xb6838d20:key 所在的内存地址。

  • refcount:1:引用计数,表示该对象被引用的次数。

  • encoding:raw:编码类型。

  • serializedlength:9:序列化后的长度。

  • lru:283790:LRU (Least Recently Used)信息,即最近最少使用算法的相关信息,在内存淘汰策略中会用到。

  • lru_seconds_idle:150:该 key 已空闲多久(单位为秒),也就是自从最后一次访问已经过去多少秒

memory usage

在 Redis 4.0 之前,只能通过DEBUG OBJECT命令估算key的内存使用(字段 serializedlength),但 DEBUG OBJECT 命令是存在误差的。4.0 版本及以上,更推荐使用memory usage命令。

# 默认 SAMPLES 为 5
memory usage 【key】
​
# 指定更大抽样个数,获取较精确的内存值
memory usage 【key】SAMPLES 1000

redis-rdb-tools

一个 python 的解析 rdb 文件的工具,在分析内存的时候,用它生成内存快照。可以把 rdb 快照文件生成 CSV 或 JSON 文件,也可以导入到 MySQL 生成报表来分析。

pip install rdbtools
​
rdb -c memory dump.rdb > memory.csv

解决
  • 分割

    将 Big Key 拆分成多个小 key。或者尝试将 Big Key 转换成其他数据结构。例如,将 Big Key 转换成 Hash,List 或者 Set 等数据结构。

  • 对象压缩

    如果大 key 的产生原因主要是由于对象序列化后的体积过大,我们可以考虑使用压缩算法来减小对象的大小。需要在客户端使用一些压缩算法对数据进行压缩和解压缩操作,例如 LZF、Snappy 等。

  • 直接删除

    如果使用的是 Redis 4.0+ 的版本,可以直接使用 unlink命令去异步删除大 key。4.0 以下的版本 可以考虑使用 scan命令,分批次删除。

我也放荡不羁爱自由!