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

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

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

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

什么是 bigkey ?

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

bigkey 带来了什么危害?

  1. Redis 阻塞^1 :因为 Redis 单线程特性,如果操作某个 Bigkey 耗时比较久,则后面的请求会被阻塞。
  2. 内存空间不均匀^1 :比如在 Redis cluster 或者 codis 中,会造成节点的内存使用不均匀。
  3. 过期时可能阻塞^1 :如果 Bigkey 设置了过期时间,当过期后,这个 key 会被删除,假如没有使用 Redis 4.0 的过期异步删除,就会存在阻塞 Redis 的可能性,并且慢查询中查不到(因为这个删除是内部循环事件)。
  4. 导致倾斜^2 :某个实例上正好保存了 bigkey。bigkey 的 value 值很大(String 类型),或者是 bigkey 保存了大量集合元素(集合类型),会导致这个实例的数据量增加,内存资源消耗也相应增加。实例的处理压力就会增大,速度变慢,甚至还可能会引起这个实例的内存资源耗尽,从而崩溃。

如何排查 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 4.0 以后才有的功能,如果你使用的是 4.0 之前的版本,当你遇到 bigkey 删除时,我给你个小建议:先使用集合类型提供的 SCAN 命令读取数据,然后再进行删除。因为用 SCAN 命令可以每次只读取一部分数据并进行删除,这样可以避免一次性删除大量 key 给主线程带来的阻塞。例如,对于 Hash 类型的 bigkey 删除,你可以使用 HSCAN 命令,每次从 Hash 集合中获取一部分键值对(例如 200 个),再使用 HDEL 删除这些键值对,这样就可以把删除压力分摊到多次操作中,那么,每次删除操作的耗时就不会太长,也就不会阻塞主线程了
  2. 拆分 ^1:有时也可以考虑对 Bigkey 进行拆分,具体方法如下:对于 string 类型的 Bigkey,可以考虑拆分成多个 key-value。对于 hash 或者 list 类型,可以考虑拆分成多个 hash 或者 list。
  3. 不用Redis:Redis对于长文本不是最优的,可考虑文档型数据库如:MongoDB等

原文发表在CSDN:Redis 大key(bigkey)问题的排查与解决方案

本作品采用《CC 协议》,转载必须注明作者和本文链接
相信时间和变化
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!