前言

做一些C端业务,不可避免的要引入一级缓存来代替数据库的压力并且减少业务响应时间,其实每次引入一个中间件来解决问题的同时,必然会带来很多新的问题需要注意,比如上篇文章《数据库与缓存一致性实战》中提到的如何做缓存的一致性。那么其实还会有一些其他问题比如使用Redis作为一级缓存时可能带来的热key、大key等问题,本文我们就热key(hot key)问题来讨论,如何合理的解决热key问题。

正文

背景

热key是什么问题,如何导致的?

一般来说,我们使用的缓存Redis都是多节点的集群版,对某个key进行读写时,会根据该key的hash计算出对应的slot,根据这个slot就能找到与之对应的分片(一个master和多个slave组成的一组redis集群)来存取该K-V。但是在实际应用过程中,对于某些特定业务或者一些特定的时段(比如电商业务的商品秒杀活动),可能会发生大量的请求访问同一个key。所有的请求(且这类请求读写比例非常高)都会落到同一个redis server上,该redis的负载就会严重加剧,此时整个系统增加新redis实例也没有任何用处,因为根据hash算法,同一个key的请求还是会落到同一台新机器上,该机器依然会成为系统瓶颈2,甚至造成整个集群宕掉,若此热点key的value 也比较大,也会造成网卡达到瓶颈,这种问题称为 “热key” 问题。

如下图1、2所示,分别是正常redis cluster集群和使用一层proxy代理的redis 集群key访问。

如上所说,热key会给集群中的少部分节点带来超高的负载压力,如果不正确处理,那么这些节点宕机都有可能,从而会影响整个缓存集群的运作,因此我们必须及时发现热key、解决热key问题。

1.热key探测

热key探测,看到由于redis集群的分散性以及热点key带来的一些显著影响,我们可以通过由粗及细的思考流程来做热点key探测的方案。

1.1 集群中每个slot的qps监控

热key最明显的影响是整个redis集群中的qps并没有那么大的前提下,流量分布在集群中slot不均的问题,那么我们可以最先想到的就是对于每个slot中的流量做监控,上报之后做每个slot的流量对比,就能在热key出现时发现影响到的具体slot。虽然这个监控最为方便,但是粒度过于粗了,仅适用于前期集群监控方案,并不适用于精准探测到热key的场景。

1.2 proxy的代理机制作为整个流量入口统计

如果我们使用的是图2的redis集群proxy代理模式,由于所有的请求都会先到proxy再到具体的slot节点,那么这个热点key的探测统计就可以放在proxy中做,在proxy中基于时间滑动窗口,对每个key做计数,然后统计出超出对应阈值的key。为了防止过多冗余的统计,还可以设定一些规则,仅统计对应前缀和类型的key。这种方式需要至少有proxy的代理机制,对于redis架构有要求。

1.3 redis基于LFU的热点key发现机制

redis 4.0以上的版本支持了每个节点上的基于LFU的热点key发现机制,使用redis-cli –hotkeys即可,执行redis-cli时加上–hotkeys选项。可以定时在节点中使用该命令来发现对应热点key。

如下所示,可以看到redis-cli –hotkeys的执行结果,热key的统计信息,这个命令的执行时间较长,可以设置定时执行来统计。

1.4 基于Redis客户端做探测

由于redis的命令每次都是从客户端发出,基于此我们可以在redis client的一些代码处进行统计计数,每个client做基于时间滑动窗口的统计,超过一定的阈值之后上报至server,然后统一由server下发至各个client,并且配置对应的过期时间。

这个方式看起来更优美,其实在一些应用场景中并不是那么合适,因为在client端这一侧的改造,会给运行的进程带来更大的内存开销,更直接的来说,对于Java和goLang这种自动内存管理的语言,会更加频繁的创建对象,从而触发gc导致接口响应耗时增加的问题,这个反而是不太容易预料到的事情。

最终可以通过各个公司的基建,做出对应的选择。

2.热key解决

通过上述几种方式我们探测到了对应热key或者热slot,那么我们就要解决对应的热key问题。解决热key也有好几种思路可以参考,我们一个一个捋一下。

2.1 对特定key或slot做限流

一种最简单粗暴的方式,对于特定的slot或者热key做限流,这个方案明显对于业务来说是有损的,所以建议只用在出现线上问题,需要止损的时候进行特定的限流。

2.2 使用二级(本地)缓存

本地缓存也是一个最常用的解决方案,既然我们的一级缓存扛不住这么大的压力,就再加一个二级缓存吧。由于每个请求都是由service发出的,这个二级缓存加在service端是再合适不过了,因此可以在服务端每次获取到对应热key时,使用本地缓存存储一份,等本地缓存过期后再重新请求,降低redis集群压力。以java为例,guavaCache就是现成的工具。以下示例:

    //本地缓存初始化以及构造private static LoadingCache<String, List<Object>> configCache= CacheBuilder.newBuilder().concurrencyLevel(8)  //并发读写的级别,建议设置cpu核数.expireAfterWrite(10, TimeUnit.SECONDS)  //写入数据后多久过期.initialCapacity(10) //初始化cache的容器大小.maximumSize(10)//cache的容器最大.recordStats()// build方法中可以指定CacheLoader,在缓存不存在时通过CacheLoader的实现自动加载缓存.build(new CacheLoader<String, List<Object>>() {@Overridepublic List<Object> load(String hotKey) throws Exception {}});//本地缓存获取Object result = configCache.get(key);

本地缓存对于我们的最大的影响就是数据不一致的问题,我们设置多长的缓存过期时间,就会导致最长有多久的线上数据不一致问题,这个缓存时间需要衡量自身的集群压力以及业务接受的最大不一致时间。

2.3 拆key

如何既能保证不出现热key问题,又能尽量的保证数据一致性呢?拆key也是一个好的解决方案。

我们在放入缓存时就将对应业务的缓存key拆分成多个不同的key。如下图所示,我们首先在更新缓存的一侧,将key拆成N份,比如一个key名字叫做"good_100",那我们就可以把它拆成四份,“good_100_copy1”、“good_100_copy2”、“good_100_copy3”、“good_100_copy4”,每次更新和新增时都需要去改动这N个key,这一步就是拆key。

对于service端来讲,我们就需要想办法尽量将自己访问的流量足够的均匀,如何给自己即将访问的热key上加入后缀。几种办法,根据本机的ip或mac地址做hash,之后的值与拆key的数量做取余,最终决定拼接成什么样的key后缀,从而打到哪台机器上;服务启动时的一个随机数对拆key的数量做取余。

2.4 本地缓存的另外一种思路 配置中心

对于熟悉微服务配置中心的伙伴来讲,我们的思路可以向配置中心的一致性转变一下。拿nacos来举例,它是如何做到分布式的配置一致性的,并且相应速度很快?那我们可以将缓存类比配置,这样去做。

长轮询+本地化的配置。首先服务启动时会初始化全部的配置,然后定时启动长轮询去查询当前服务监听的配置有没有变更,如果有变更,长轮询的请求便会立刻返回,更新本地配置;如果没有变更,对于所有的业务代码都是使用本地的内存缓存配置。这样就能保证分布式的缓存配置时效性与一致性。

2.5 其他可以提前做的预案

上面的每一个方案都相对独立的去解决热key问题,那么如果我们真的在面临业务诉求时,其实会有很长的时间来考虑整体的方案设计。一些极端的秒杀场景带来的热key问题,如果我们预算充足,可以直接做服务的业务隔离、redis缓存集群的隔离,避免影响到正常业务的同时,也会可以临时采取更好的容灾、限流措施。

一些整合的方案

目前市面上已经有了不少关于hotKey相对完整的应用级解决方案,其中京东在这方面有开源的hotkey工具,原理就是在client端做洞察,然后上报对应hotkey,server端检测到后,将对应hotkey下发到对应服务端做本地缓存,并且这个本地缓存在远程对应的key更新后,会同步更新,已经是目前较为成熟的自动探测热key、分布式一致性缓存解决方案,京东零售热key。

总结

以上就是笔者大概了解或实践过的的如何应对热key的一些方案,从发现热key到解决热key的两个关键问题的应对。每一个方案都有优缺点,比如会带来业务的不一致性,实施起来较为困难等等,可以根据目前自身业务的特点、以及目前公司的基建去做对应的调整和改变。

明天就是农历虎年的第一个工作日了,希望大家都能今年身体健康,升职加薪。

Redis缓存热key问题常用解决方案相关推荐

  1. redis的热key、大key

    目录 1.概述 2.查找方法 2.1.知道具体哪个key有问题 2.2.不知道具体哪个key有问题 3.处理方法 3.1.大key的处理方法 3.2.热key的处理方法 1.概述 大key: 含有较大 ...

  2. 谈谈redis的热key问题如何解决

    谈谈redis的热key问题如何解决 参考文章: (1)谈谈redis的热key问题如何解决 (2)https://www.cnblogs.com/leeego-123/p/11588429.html ...

  3. redis一般用来干嘛_谈谈redis的热key问题如何解决

    公众号:孤独烟 ,作者:孤独烟 引言 今天我们来写redis方面的内容,谈谈热key问题如何解决. 其实热key问题说来也很简单,就是瞬间有几十万的请求去访问redis上某个固定的key,从而压垮缓存 ...

  4. redis缓存存在的隐患及其解决方案

    redis缓存 1.缓存穿透 1>.什么是缓存穿透? 业务系统需要查训的数据根本不存在,当业务系统查询时, 首先会在缓存中查训,由于缓存中不存在,然后在往数据 库中查,由于该数据在数据库中也不存 ...

  5. 缓存击穿和雪崩常用解决方案

    目录 1 抢红包排行查询 2 击穿现象分析 3 击穿解决方案 3.1 定时器 3.2 多级缓存 3.3 分布式锁 3.4 队列术 4 缓存雪崩介绍 1 抢红包排行查询 上面案例我们实现了某个用户抢红包 ...

  6. 【原创】谈谈redis的热key问题如何解决

    ps:hot key和big key问题,大家一定要有所了解. 本文预计分为如下几个部分 热key问题 如何发现 业内方案 正文 – 热Key问题 上面提到,所谓热key问题就是,突然有几十万的请求去 ...

  7. redis 缓存预热_Redis异常问题解决方案:缓存雪崩、预热、穿透、击穿、降解方案分析...

    不管你在工作中还是面试中,Redis异常问题的解决方案都是不得不去学习了解的,下面来细品一下! 一.缓存雪崩 1.什么是缓存雪崩? 如果缓存集中在一段时间内失效,发生大量的缓存穿透,所有的查询都落在数 ...

  8. redis数据类型为key的常用命令

    redis默认自带16个库 select 7切换到redis第8个数据库 dbsize查看reids有几个key keys *查看所有k,v clear清空控制台 FLUSHDB清空当前数据库的kv ...

  9. Redis 热 Key 发现以及解决办法

    背景介绍 最近在技术交流微信群里看大家讨论技术,其中有谈到 Redis 热 Key 的一些问题解决方案,我也仔细思考了一下我们目前系统中 Redis 的使用场景,我们是不是也存在热 Key 问题,或者 ...

最新文章

  1. Eclipse中SVN的安装步骤(两种)和用法
  2. css 让div 的高度和屏幕的高度一样
  3. java swingworker_Java中的SwingWorker
  4. [转]Flex与.NET互操作(三):基于WebService的数据访问(下)
  5. redis中不同value类型的存取操作方式
  6. 退休后你和原工作单位还有联系吗?
  7. 一张图学会python-一张图让你学会Python
  8. 年审是当月还是当天_汽车年检提前检车的日期是按原始的还是按检车当月的?...
  9. Java 基础 匿名对象
  10. Java多线程系列---“基础篇”13之 乐观锁与悲观锁
  11. 舍伍德算法解决线性时间选择
  12. 学习类APP如何规范?
  13. Make sure that the latest NVIDIA driver is installed and running.
  14. java接口自动化测试-导入xslx模板进行批量检索
  15. 3dmax如何进行网络渲染?网渲云渲染渲染农场怎么用?
  16. 【从0开始入门python】一个半月的三万字学习笔记汇总!!!
  17. nyoj 1238 最少换乘(spfa)
  18. 微信小程序如何添加业务域名
  19. 我的2019“木桶插曲”——三个月考上研
  20. 算法设计与分析: 4-11 硬币找钱问题

热门文章

  1. 了解python编程语言_《了》字意思读音、组词解释及笔画数 - 新华字典 - 911查询...
  2. HP Proliant Gen9服务器重装系统出现RIP addressout of range报错
  3. @RequestBody
  4. 手机自带计算机的功能,Win10自带手机投屏功能,80%的人居然都不知道
  5. linux:~$,/$,~#,/#的区别与含义
  6. 对话一代知名站长,卢松松解答网友的15条深度提问!
  7. 智能足球裁判,能否突破专业运动的技术瓶颈
  8. CSDN 博客备份工具
  9. 文盘Rust——领域交互模式如何实现
  10. 2020A证(安全员)实操考试视频及A证(安全员)操作证考试