Redis 大key(bigkey)问题的排查与解决方案

  • bigkey 问题导致Rides集群节点内存资源耗尽
  • 什么是 bigkey ?
  • bigkey 带来了什么危害?
  • 如何排查 Redis 的 bigkey?
  • bigkey 怎么处理?

bigkey 问题导致Rides集群节点内存资源耗尽

业务中遇到一个神奇的问题:Redis的一个key设置过期时间以后,这个key就消失了。通过命令行复现了这个问题:

redis get 01 02 03 查询多个key redis一次性查询多个key_缓存

什么是 bigkey ?

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

bigkey 带来了什么危害?

  1. Redis 阻塞1
  2. 内存空间不均匀1
  3. 过期时可能阻塞1
  4. 导致倾斜2

如何排查 Redis 的 bigkey?

Redis 可以在执行 redis-cli 命令时带上–bigkeys 选项,进而对整个数据库中的键值对大小情况进行统计分析,比如说,统计每种数据类型的键值对个数以及平均大小。此外,这个命令执行后,会输出每种数据类型中最大的 bigkey 的信息,对于 String 类型来说,会输出最大 bigkey 的字节长度,对于集合类型来说,会输出最大 bigkey 的元素个数,如下所示:``。

redis-cli -h xxxxxx.redis.rds.aliyuncs.com -a shiliName:password --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 'comment_video_commentInfos_1480216061_1921681272_19620_104338970_203_55' with 419 bytes
.
.
.
[97.13%] Biggest string found so far 'apiFindSetAll:' with 400577 bytes

-------- summary -------

Sampled 22748641 keys in the keyspace!
Total key length in bytes is 810624573 (avg len 35.63)

Biggest string found 'apiFindSetAll:' has 400577 bytes
Biggest   list found 'bbb/xxx:0' has 9737534 items
Biggest    set found 'vl_mixxx:im:xxx_history_members:live-chat-23201' has 3989 members
Biggest   hash found 'xxx::iblue::group::star::listInfo' has 5063 fields
Biggest   zset found 'xxxx:data_id:260917' has 30649 members

22627532 strings with 4682556354 bytes (99.47% of keys, avg size 206.94)
103 lists with 10110292 items (00.00% of keys, avg size 98158.17)
12668 sets with 36132 members (00.06% of keys, avg size 2.85)
16328 hashs with 44235 fields (00.07% of keys, avg size 2.71)
92010 zsets with 510359 members (00.40% of keys, avg size 5.55)

bigkey 怎么处理?

  1. 删除 bigkey 2

redis-cli -h xxx.redis.rds.aliyuncs.com -a redisName:redisPassword keys “pattern*” | xargs redis-cli -h xxx.redis.rds.aliyuncs.com -a redisName:redisPassword del

  1. 拆分1:有时也可以考虑对 Bigkey 进行拆分,具体方法如下:对于 string 类型的 Bigkey,可以考虑拆分成多个 key-value。对于 hash 或者 list 类型,可以考虑拆分成多个 hash 或者 list。
  2. 不用Redis:Redis对于长文本不是最优的,可考虑文档型数据库如:MongoDB等