Skip to content

Redis:多大的 key 算大?如何查找?如何拆分?

🏷️ Redis

多大的 key 算大 ?

关于 Redis 中多大的 key 算大,这个貌似没有统一的定义。下面是摘自几篇博客中的关于大 key 的定义:

定义一:[1]

  1. 单个简单的 key 存储的 value 很大;
  2. HashSetZSetList 中存储过多的元素(以万为单位);
  3. 一个集群存储了上亿的 key , key 本身过多也带来了更多的空间占用;

定义二:[2]

  1. value 是 String 类型时, size 超过 10KB ;
  2. value 是 ZSetHashListSet 等集合类型时,它的成员数量超过 1w 个。

上述的定义并不绝对,主要是根据 value 的成员数量和字节数来确定,业务可以根据自己的场景也确定标准。

定义三:[3]

  1. String 类型的 key 对应的 value 超过 10MB。
  2. ListSetHashZSet 等集合类型,集合元素个数超过 5000 个。

定义四:[4]

  1. 合理的 key 中 value 的字节大小,推荐小于 10 KB;

可以看到每位作者的标准都不太一样,有的差别还比较大。

单个 String key 有的定义是 > 10KB,有的是 > 10MB 。虽然差别比较大,但可以取一个中间的数量级 320KB 或者取个整 500KB 作为参考。

集合类型的元素数量倒是差别不算很大,基本上在万这个数量级上就认为是大 key 了。

如何查找?

我自己参加的项目大都使用的是云上的 Redis ,其管理后台都提供了类似的诊断、分析工具,甚至可以自动告警。不仅是大 key ,热 key 和慢查询的检测一般也都支持。

自建 Redis 服务器的就只能自己分析了,下面是两种常用的查找方法:

  1. 使用 BIGKEYS 命令

    shell
    redis-cli --bigkeys

    使用这个命令的缺点就是它会阻塞 Redis ,生产环境慎用。

  2. 使用 redis-rdb-tools 工具扫描 rdb 快照文件

    虽然实时性差一点,但不影响使用。

如何拆分?

对于大 key 问题,比较普遍的解决方法就是拆分:将过大的 key 拆分成合适大小的小 key 。

印象中之前看过一篇性能测试,说是 Redis 的集合中元素数量在 1500 左右的时候性能最高(印象中是这个数字,但是具体的文章没有找到),所以我编码的时候经常以 1500 为标准拆分集合。

至于如何拆分可以根据业务自己决定,类似于数据的分表,定义好合适的规则就可以了。总之目标就是尽量平均拆分,且每个 key 里的元素不会太多。

最常用的拆分方法就是将 key 的哈希值 mod 一个合适的数值(分片的数量):

java
(key.hashCode() & Integer.MAX_VALUE) % N

对于 String 类型的大 key ,比较常用的则是压缩。

比如,如果使用的是 JDK 默认的序列化(Serializable)或者是 XML 格式的序列化,可以考虑改为使用 JSON 格式。 JSON 格式由于比较紧凑,一般占用的空间相对比较小。另外还可以基于序列化之后的结果进行压缩,比如 GZIPSnappy ,再次减少 Redis 内存空间的占用。[5] 需要注意的是,这些都是通过消耗服务器的时间来减少 Redis 空间的占用,也就是时间换空间,所以需要结合实际的场景决定是否需要压缩。


  1. Redis 大 key 多 key 拆分方案 ↩︎

  2. 解决了 Redis 大 key 问题 ↩︎

  3. Redis 中的 BigKey 问题:排查与解决思路 ↩︎

  4. Redis 排查大 key 的4种方法,优化必备 ↩︎

  5. Sprintboot redis 采用gzip和Snappy compress压缩数据 ↩︎