Redis 的大 key 如何处理
介绍
大key 并不是指 key 的值很大,而是 key 对应的 value 很大(非常占内存)
一般而言,下面这两种情况被称为大 key:
- String 类型的值大于 10 KB;
- Hash、List、Set、ZSet 类型的元素的个数超过 5000个;
为什么会出现大key
-
数据结构不合理:当使用 Redis 的字符串类型存储较大的数据时,如果没有合适地切分数据,就会导致一个 Key 的值过大。例如,将整个文本内容存储在一个字符串类型的 Key 中。
-
批量写入数据:在进行大规模写入操作时,如果将大量的数据一次性写入到一个 Key 中,就会导致大 Key 的问题。这种情况常见于批量导入数据或者数据迁移的场景。缓存数据失效策略不当:
-
如果缓存的数据失效策略不合理,导致某个Key的数据长时间没有被清除,就可能导致该Key变得很大。这可能是由于没有设置合理的过期时间或没有及时删除过期的数据。
大 key 会带来以下四种影响:
- 客户端超时阻塞。由于 Redis 执行命令是单线程处理,然后在操作大 key 时会比较耗时,那么就会阻塞 Redis,从客户端这一视角看,就是很久很久都没有响应。
- 引发网络阻塞。每次获取大 key 产生的网络流量较大,如果一个 key 的大小是 1 MB,每秒访问量为 1000,那么每秒会产生 1000MB 的流量,这对于普通千兆网卡的服务器来说是灾难性的。
- 阻塞工作线程。如果使用 del 删除大 key 时,会阻塞工作线程,这样就没办法处理后续的命令。
- 内存分布不均。集群模型在 slot 分片均匀情况下,会出现数据和查询倾斜情况,部分有大 key 的 Redis 节点占用内存多,QPS 也会比较大。
如何找到大 key
使用 RdbTools 工具查找大 key
使用 RdbTools 第三方开源工具,可以用来解析 Redis 快照(RDB)文件,找到其中的大 key。
比如,下面这条命令,将大于 10 kb 的 key 输出到一个表格文件。
rdb dump.rdb -c memory --bytes 10240 -f redis.csv
如何删除大 key
这个过程本身需要一定时间,而且会阻塞当前释放内存的应用程序
这里给出两种方法:
- 分批次删除
- 异步删除(Redis 4.0版本以上):用 unlink 命令代替 del 来删除
为了解决大 Key 问题,可以采取以下几种方式:
-
分割大 Key:将一个大 Key 的值分割成多个小 Key,然后分别存储。例如,将一个大的字符串分割为多个小的字符串片段,然后分别以不同的 Key 存储。这样可以避免一个大 Key 导致的性能问题。
-
使用 Hash 数据结构:将大 Key 的值存储在 Hash 数据结构中,其中 Hash 的 field 作为子 Key,value 作为 value。这样可以将大 Key 分割成多个子 Key,每个子 Key 在 Hash 中都是独立的,这样可以减少对单个 Key 的访问。
-
使用 Redis 的分布式特性:通过使用 Redis 的分片或者集群功能,将大 Key 的数据分布到不同的 Redis 实例或节点上。这样可以利用多个实例或节点的性能来处理大 Key,减少单个实例或节点的负载。