每日小知识-redis热点key还能这么处理?

点击上方名片关注我,为你带来更多踩坑案例

78f56f0f7773c7be2e0e5e8b2dd99578.png

引导

22b952b90a4247137b626478c51bd4ba.gif

当你没时间阅读厚厚的书籍

或者厌倦了长篇大论的面经

那么这个系列适合你

只需要在地铁上、吃饭时、厕所里,几分钟的时间就可以获得一个小知识

每天一点小进步,日积月累之下你会感谢自己

请关注我,持续为您带来更新

小知识

d0611a8f7e62a8c7862582a50aeea087.gif

不管是在面试的时候,还是在日常工作中,很多人都会用到redis

而redis的大部分用法都是日常缓存,用来减少数据库的读压力

但是即便是redis如此的高性能,也会面临高并发场景的考验

虽然我们大部分人的项目中是不会遇到的如此高的并发的........有个几百qps顶天了

但是还是要了解这种场景

也就是我们今天要说的热点key问题

为什么会出现热点key?

7885dde812b4e5afc884111dcd6ceb98.gif

出现端:该场景主要是出现在C端,B端的流量一是不高,二是可预知且可控

当一个C端产品,比如电商系统中某个商品的定时抢购

或者是新闻系统中的某条新闻爆炸之类的

甚至有人恶意访问

都会导致某个key的访问量剧增到几十万几百万甚至更多

哪怕我们部署了redis集群,但是往往都是采用hash固定分片

同一个key的请求还是会访问到同一台redis机器

这个时候这台redis机器就很有可能因为短时间流量过于集中而出现问题

甚至出现缓存击穿到后端db,导致性能较低的db宕机,从而引发一系列问题。

(当然,这里只是虚拟一个场景,真实业务场景中,比如新闻类系统,完全可以使用性能更强大的es索引之类的,不可能都放在redis中去缓存)

怎么发现热点key呢?

34daf66c4e83a4e3976e6736119bc5fd.gif

既然我们知道了热点key会带来很多问题

那么怎么发现呢?

这个其实不同的业务场景不同的技术架构,处理办法也不同,我们不能一概而论

大致分为提前发现实时处理
-->提前发现,就是对于一些促销活动场景,或者是具有固定时间固定业务,比如财务月结就是在一个月固定的几天,这就是能提前发现的热点key。

但其实很大部分都是一些不可预知的热点key,比如新闻热搜之类的

-->那实时处理的这部分我们怎么处理呢?

大家可以有这么一个思路,既然是实时的,那肯定需要实时计算统计才能知道

无非就是这个计算是谁来做

  1. redis来做,redis新版中自带了流量统计工具,加入指定参数即可,但是这种方法不推荐,因为会影响redis的性能,在设计的时候我们还是尽量让redis的功能单一一些。

  2. 服务端来做,类似redis的方式,在业务服务端自己写一个sdk来做流量的实时统计。这个也不是很推荐,一是服务端数量太多,一个key平均分散下来即便是热key也不热了,检测不灵敏(当然也可以降低阈值,不过还是会损失一些灵敏度),二是也会给服务端带来压力

  3. 高性能中间件来做,比如kafka,在请求redis之前做一个代理,发送到异步的redis-key队列,最后推给单独的流量统计系统来计算,然后流量达到某一个阈值的时候,判定为热点key,推送给服务端去处理,这种方法比较推荐(当然还是要看具体场景,有没有必要这么折腾)

怎么处理热点key呢?

dc56e625be802f218f5293743a2700fa.gif

不管是提前发现也好,实时计算判定出来也罢,我们发现热点key之后怎么处理呢?

1. 利用服务端JVM缓存,也就是二级缓存,请求来的时候,如果是热点key,直接去内存中拿;或者说所有请求来了,都先去内存中取,取不到再去redis。虽然这样也会有一些问题,比如二级缓存和redis缓存数据不一致怎么办?这个也要具体问题具体分析,比如要考虑缓存的时效性、不根据缓存去做逻辑判断等。

2. 从redis上下手,redis读写分离,可以减少一部分并发,其次热点key复制到多个redis从库读的实例上,热点key的请求就完全可以采取随机访问一台,方便扩容。但是这样也有缺点,维护起来不方便。

redis写热点怎么处理?

e7381314012d176a42d9af61722dcac6.gif

可能有朋友发现了,以上都是针对redis读热点的处理办法

因为我们redis的场景大部分也是一个读多写少的场景

但是也有一些场景,比如抢购商品的库存扣减,也会存在一个热点key,而且是写热点,在读写分离的前提下,我们还可以做一些优化来解决热点key。

1.如果是不同的商品,我们可以根据商品id等把它请求打散到不同的redis实例

2.这个时候可以通过消息中间件等,先做一个请求的限流,超出来的流量可以让用户同步等待或者有一个其他的提示方式。

3.大部分秒杀场景对用户的感知是没那么强烈的,就是你看着还有库存,但实际扣除的时候其实没有了。所以扣除操作完全可以以数据库为准,只不过可以批量扣除来减少并发,然后异步去更新redis缓存,可以容忍一定的缓存延迟。

总而言之就是具体场景具体分析,具体组件具体分析,这种性能优化之类的方案,没有角度的好坏,只有适不适合

猜你喜欢

转载自blog.csdn.net/qq_31363843/article/details/128014912