关于Redis大key问题

什么是大key?

我们从[空间复杂性]和访问它的[时间复杂度]两个方面来定义大键。
前者主要表示Redis键的占用内存大小;
后者表示Redis集合数据类型(set/hash/list/sorted set)键,所含有的元素个数。举例:

1个大小200MB的String键(String Object最大512MB);内存空间角度占用较大
1个包含100000000(1kw)个字段的Hash键,对应访问模式(如hgetall)时间复杂度高。

内存空间复杂性处理耗时都非常小,测试 del 200MB String键耗时约1毫秒,
而删除一个含有1kw个字段的Hash键,却会阻塞Redis进程数十秒。

大Key会带来哪些问题?

  • 当value过大时,可能会导致以下问题:
    • 内存使用不均匀:当slot分配均匀的时候,大key的出现会导致redis内存使用的不均。
    • 网络拥塞:每次获取bigkey产生的网络流量比较大。涉及到大key的操作,尤其是使用hgetall、lrange 0 -1、get、hmget 等操作时,网卡可能会成为瓶颈,也会到导致堵塞其它操作,qps 就有可能出现突降或者突升的情况,趋势上看起来十分不平滑,严重时会导致应用程序连不上,实例或者集群在某些时间段内不可用的状态。假设一个bigkey为1MB,每秒访问量为1000,那么每秒产生1000MB的流量。
  • 当元素个数过多时,会导致以下问题:
    (元素个数过多针对的是key为集合类型set,sorted set,list和hash)
    • 超时阻塞:Redis是单线程处理。单个耗时过大命令,导致阻塞其他命令,容易引起应用程序雪崩或Redis集群发生故障切换。所以避免在生产环境中使用耗时过大命令。

优雅的删除大key

Redis是单线程处理。
单个耗时过大命令,导致阻塞其他命令,容易引起应用程序雪崩或Redis集群发生故障切换。所以避免在生产环境中使用耗时过大命令。

DEL命令在删除单个集合类型的Key时,命令的时间复杂度是O(M),其中M是集合类型Key包含的元素个数。

Redis删除大的集合键的耗时, 测试估算,


image.png
  • 脚本+删除命令:
    hash: 使用 hscan + hdel
    set : 使用 sscan + srem
    zset : 使用 zremrangebyrank
    list : 使用 scan + ltrim
  • lazy delete free:
    3.4版本开始,Redis会支持lazy delete free的方式,删除大键的过程不会阻塞正常请求。

scan 命令

SCAN 命令:用于迭代当前数据库中的数据库键。跟keys命令返回全部的数据库键不同,它每次执行都只会返回少量元素,所以可以用于生产环境。
SCAN 命令是一个基于游标的迭代器(cursor based iterator): SCAN 命令每次被调用之后, 都会向用户返回一个新的游标, 用户在下次迭代时需要使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程。

使用示例:

172.30.127.3:9200> scan 0
1) "851968"
2)  1) "rand:41834283"
    2) "rand:23627572"
    3) "rand:53205379"
    4) "LESSON_STUDENT_CNTS_222500"
    5) "rand:72655133"
    6) "ltwx1:wxserver:fans:info:wx85dd92cd24d7e29e:o_aiL0dqLx92iwu48nqjWp7xOhFg"
    7) "rand:39536088"
    8) "rand:89380089"
    9) "rand:25366977"
   10) "V1_SJ_EXAM_DB_RELATION_BINDID_206773_BINDTYPE_0_RELATIONTYPE_9"
   11) "rand:27227021"
172.30.127.3:9200> scan 851968

第一次使用 scan 0 返回一个列表,列表分为两部分1) 下一次的游标,2) 列表。
第二次使用第一次返回的游标继续请求,知道返回的游标是0表示结束遍历了。

删除bigkey
使用del命令删除bigkey通常来说会阻塞Redis服务器,在生产环境中要尽量避免。
当bigkey对应的value越来越大,删除的时间也会随着增加。除了string类型删除时一般不产生阻塞,其他四种数据结构的删除都有可能产生阻塞。
删除bigkey要使用渐进式遍历的方式,利用sscan、hscan、zscan命令将若干个键拿出来。

Redis 4.0支持lazy delete free模式,删除bigkey不会阻塞Redis。

实际中如何避免bigkey:

尽量把大key进行拆分
尽量避免使用hgetall 这样的命令

如何统计大key?

发现bigkey的两种方式:

redis sdk中增加大key使用的监控报警:在框架的Redis sdk中修改,当set了大key时,通过打印日志,对接监控报警系统。
脚本定时扫描:在流量低峰时,通过定时任务执行。使用scan命令渐进的扫描出所有的key,分别计算每个key的serializedlength,找到对应的bigkey进行相应的处理和报警,这种方式比较推荐。在scan + debug object的命令,如果怀疑存在bigkey,可以

其他一些查看大key的方法:

在redis实例上执行bgsave,然后我们对dump出来的rdb文件进行分析,找到其中的大KEY
redis-cli 原生自带 –bigkeys 功能,统计bigkey的分布。

➜  goApp redis-cli -h 172.30.127.3 -p 9200 -a Zyb-Test --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 'rand:41834283' with 8 bytes
[00.00%] Biggest hash   found so far 'LESSON_STUDENT_CNTS_222500' with 33 fields
[00.00%] Biggest string found so far 'docker_nuke_session:78379868-7a34-4c24-9f17-58b4a5a4cdc1' with 25 bytes
[00.00%] Biggest string found so far 'FUDAO_ELIVE_USER_EXT_DATA_227543_2000024247' with 35 bytes
[00.01%] Biggest string found so far 'cwTask7480' with 51 bytes
[00.01%] Biggest string found so far 'ACLS2_COURSE_INFO_201940' with 1899 bytes
[00.03%] Biggest zset   found so far 'TARGET_CALC_RANKING_L_236412' with 5 members
[00.03%] Biggest zset   found so far 'TEACHER_MESSAGE_2000076523' with 19 members
[00.06%] Biggest string found so far 'teacher_kv_id_2298403389' with 3284 bytes
[00.09%] Biggest string found so far 'billing_course_kv_228486' with 8876 bytes
[00.33%] Biggest string found so far 'ACLS2_QUESTION_INFO_240405_0_9' with 9323 bytes

可见redis在计算大key的时候不是以key的占用内存大小来计算的,string是使用STRLEN方法来计算,list是llen,hash是使用HLEN来计算。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,188评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,464评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,562评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,893评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,917评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,708评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,430评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,342评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,801评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,976评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,115评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,804评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,458评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,008评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,135评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,365评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,055评论 2 355

推荐阅读更多精彩内容