这是一位同学今年秋招参加得物 JAVA 一面遇到的问题,完整面经如下:
这个问题在面试中还是比较容易遇到的,尤其是在考察 redis 性能优化相关知识点的时候。
通常情况下,问了 bigkey(大 Key)还会继续问 hotkey(热 Key)。即使不准备面试也建议看看,实际开发中也能够用到。
hotkey 相关的内容会在下一篇文章中提问,同样会收录在 《Java 常见面试题详解》 这个面试题专辑中。
简单来说,如果一个 key 对应的 value 所占用的内存比较大,那这个 key 就可以看作是 bigkey。具体多大才算大呢?有一个不是特别精确的参考标准:
bigkey 判定标准
bigkey 通常是由于下面这些原因产生的:
bigkey 除了会消耗更多的内存空间和带宽,还会对性能造成比较大的影响。
在 Redis 常见阻塞原因总结[1]这篇文章中我们提到:大 key 还会造成阻塞问题。具体来说,主要体现在下面三个方面:
大 key 造成的阻塞问题还会进一步影响到主从同步和集群扩容。
综上,大 key 带来的潜在问题是非常多的,我们应该尽量避免 Redis 中存在 bigkey。
1、使用 Redis 自带的 --bigkeys 参数来查找。
# redis-cli -p 6379 --bigkeys
# Scanning the entire keyspace to find biggest keys as well as
# average sizes per key type. You can use -i 0.1 to sleep 0.1 sec
# per 100 SCAN commands (not usually needed).
[00.00%] Biggest string found so far '"ballcat:oauth:refresh_auth:f6cdb384-9a9d-4f2f-af01-dc3f28057c20"' with 4437 bytes
[00.00%] Biggest list found so far '"my-list"' with 17 items
-------- summary -------
Sampled 5 keys in the keyspace!
Total key length in bytes is 264 (avg len 52.80)
Biggest list found '"my-list"' has 17 items
Biggest string found '"ballcat:oauth:refresh_auth:f6cdb384-9a9d-4f2f-af01-dc3f28057c20"' has 4437 bytes
1 lists with 17 items (20.00% of keys, avg size 17.00)
0 hashs with 0 fields (00.00% of keys, avg size 0.00)
4 strings with 4831 bytes (80.00% of keys, avg size 1207.75)
0 streams with 0 entries (00.00% of keys, avg size 0.00)
0 sets with 0 members (00.00% of keys, avg size 0.00)
0 zsets with 0 members (00.00% of keys, avg size 0.00
从这个命令的运行结果,我们可以看出:这个命令会扫描(Scan) Redis 中的所有 key ,会对 Redis 的性能有一点影响。并且,这种方式只能找出每种数据结构 top 1 bigkey(占用内存最大的 String 数据类型,包含元素最多的复合数据类型)。然而,一个 key 的元素多并不代表占用内存也多,需要我们根据具体的业务情况来进一步判断。
在线上执行该命令时,为了降低对 Redis 的影响,需要指定 -i 参数控制扫描的频率。redis-cli -p 6379 --bigkeys -i 3 表示扫描过程中每次扫描后休息的时间间隔为 3 秒。
2、使用 Redis 自带的 SCAN 命令
SCAN 命令可以按照一定的模式和数量返回匹配的 key。获取了 key 之后,可以利用 STRLEN、HLEN、LLEN等命令返回其长度或成员数量。
数据结构命令复杂度结果(对应 key)StringSTRLENO(1)字符串值的长度HashHLENO(1)哈希表中字段的数量ListLLENO(1)列表元素数量SetSCARDO(1)集合元素数量Sorted SetZCARDO(1)有序集合的元素数量
对于集合类型还可以使用 MEMORY USAGE 命令(Redis 4.0+),这个命令会返回键值对占用的内存空间。
3、借助开源工具分析 RDB 文件。
通过分析 RDB 文件来找出 big key。这种方案的前提是你的 Redis 采用的是 RDB 持久化。
网上有现成的代码/工具可以直接拿来使用:
4、借助公有云的 Redis 分析服务。
如果你用的是公有云的 Redis 服务的话,可以看看其是否提供了 key 分析功能(一般都提供了)。
这里以阿里云 Redis 为例说明,它支持 bigkey 实时分析、发现,文档地址:https://www.alibabacloud.com/help/zh/apsaradb-for-redis/latest/use-the-real-time-key-statistics-feature 。
阿里云Key分析
bigkey 的常见处理以及优化办法如下(这些方法可以配合起来使用):