[线上问题]删除大key导致redis短暂超时

背景:今天系统多个服务突然告警,限制响应时间超时,原本不到400ms的接口响应时间,好多都变成2s左右,但是过了2分钟就恢复正常

分析:根据查看监控显示,一个使用的第三方的redis超时导致。

结论:删除了一个大key

1.什么是大key?\color{red}{不是指key值很长,而是指该key下面的value值过大}

业务场景中经常会有各种大key的情况, 比如:
(1)单个简单的key存储的value很大
(2)hash、set、zset、list中存储过多的元素(以万为单位)

2.大key的风险?

(1).读写大key会导致超时严重,甚至阻塞服务。

(2).如果删除大key,DEL命令可能阻塞Redis进程数十秒,使得其他请求阻塞,对应用程序和Redis集群可用性造成严重的影响。\color{red}{why?可以了解一下redis单线程的原理,以及优点}

(3).建议每个key不要超过M级别。

3.存储优化方案

由于redis是单线程运行的,如果一次操作的value很大会对整个redis的响应时间造成负面影响,应该想办法把这些大key化整为零。
首先是第一种情况
(1)单个简单的key存储的value很大

该对象需要每次都整存整取
可以尝试将对象分拆成几个key-value, 使用multiGet获取值,这样分拆的意义在于分拆单次操作的压力,将操作压力平摊到多个redis实例中,降低对单个redis的IO影响;

该对象每次只需要存取部分数据
可以像第一种做法一样,分拆成几个key-value,也可以将这个存储在一个hash中,每个field代表一个具体的属性,使用hget,hmget来获取部分的value,使用hset,hmset来更新部分属性

(2)hash、set、zset、list 中存储过多的元素
类似于场景一中的第一个做法,可以将这些元素分拆。
以hash为例,原先的正常存取流程是:
hget(hashKey, field);
hset(hashKey, field, value)

现在,固定一个桶的数量,比如10000,每次存取的时候,先在本地计算field的hash值,模除10000,确定该field落在哪个key上。
newHashKey = hashKey + (hash(field) % 10000);
hset(newHashKey, field, value);
hget(newHashKey, field)

set, zset, list 也可以类似上述做法。
但也有些不适合的场景,比如要保证lpop的数据的确是最早push到list中去的,这个就需要一些附加的属性,或者是在key的拼接上做一些工作(比如list按照时间来分拆)。

4.如何优雅地删除各类大Key

从Redis2.8版本开始支持scan命令,通过m次时间复杂度为O(1)的方式,遍历包含n个元素的大key.这样避免单个O(n)的大命令,导致Redis阻塞。

5.Redis Lazy Free

应该从3.4版本开始,Redis会支持lazy delete free的方式,删除大键的过程不会阻塞正常请求。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 本文为笔者对在学习Redis过程中所收集资料的一个总结,目的是为了以后方便回顾相关的知识,大部分为非原创内容。特此...
    EakonZhao阅读 14,627评论 0 9
  • 一、Redis 1、概述 Redis是速度非常快的非关系型内存键值数据库,可以存储键和物种不同类型的值之间的映射。...
    落地生涯阅读 839评论 0 3
  • 第二部分 redis Redis官网 https://redis.ioRedis 中国镜像Redis中国用户组(C...
    霄峰阅读 610评论 0 4
  • Redis是啥 Redis是一个开源的key-value存储系统,由于拥有丰富的数据结构,又被其作者戏称为数据结构...
    一凡呀阅读 1,230评论 0 5
  • NOSQL类型简介键值对:会使用到一个哈希表,表中有一个特定的键和一个指针指向特定的数据,如redis,volde...
    MicoCube阅读 4,149评论 2 27

友情链接更多精彩内容