美文网首页架构与思维
超高并发下,Redis热点数据风险破解

超高并发下,Redis热点数据风险破解

作者: Hello_Brand | 来源:发表于2024-03-20 09:38 被阅读0次

Redis24篇集合

1 介绍

作者是互联网一线研发负责人,所在业务也是业内核心流量来源,经常参与 <font color="#f00" > 业务预定、积分竞拍、商品秒杀等工作。</font>
近期参与多场新员工的面试工作,经常就 『超高并发场景下热点数据』 可用性保障与候选人进行讨论。
本文聚焦一些关键点技术进行讨论,并总结一些热点场景的处理经验。

2 业务基础架构简图(假设)

image.png

3 超高并发下热点数据的稳定性保障

3.1 命题背景

1000w+请求同时投向后端,如果缓存未建立、失效,甚至缓存服务故障,就会透过缓存层直接投向数据库。
可能会造成整体击穿/雪崩,怎么破?

3.2 各种业务场景及应对方案

3.2.1 规律性热点数据预热

无论是聚集式热key,还是散列式热key,只要是有一定规律性的,均可以做<font color="#f00" > 预热</font>。
既然是热Key,那就想办法尽可能让它不进入MySQL,就不会对数据库造成伤害,。
这种场景最常见的就是对一些字典数据做预热,因为他们不容易改变,修改频次较低,但又很容易在高峰期被群蜂请求(突发式的批量请求)。
电商领域比如:<font color='#f00'> 商品种类、品牌类型、折扣规则。</font>
办公/教学领域比如:<font color='#f00'>学校、年段、班级、学科、考试科目等。</font>

<font color="#f00" >一般来说如果10点是峰值期,那么可以预先在8~10点期间,可以逐渐的把大部分缓存建立起来。</font>如图:


image.png

3.2.2 非规律性热点数据预热

Redis + 应用层 加探测器,预判热Key,并将探测到的热Key进行预热。
1、baidu实时热搜

image.png

2. taobao商品排行

image.png

<font color='#f00'>这种额外的开销就是有一个实时计算的独立组件,因为热点新闻、热点数据都有急剧突变的特性。比如weibo多次因为突发热点新闻导致网站崩溃。</font>

3.2.3 破解过期时间一致性问题

缓存的建立过程都是散列的,但是如果长时间静待都会被逐渐释放。
比如钉钉、飞书的办公场景,遇到夜晚低峰期、周末节假日,缓存Key被逐步释放之后。很容易在第二个工作日的早高峰造成大量创建缓存,流量井喷。
<font color='#f00'> 解决方案除了前面我们提到的缓存预热之外,错峰过期时间也是常规操作。</font>
可以给缓存设置过期时间时加上一个随机值时间,使得每个key的过期时间分布开来,不会集中在同一时刻失效。
随机值我们团队的做法是:n * 3/4 + n * random() 。所以,比如你原本计划对一个缓存建立的过期时间为8小时,那就是6小时 + 0~2小时的随机值。
这样保证了均匀分布在 6~8小时之间。如图:


image.png

3.2.4 过滤垃圾请求

一般情况下,我们取数先从缓存中Get Key,不存在的时候再从数据库中去获取,但这很容易给攻击者提供漏洞。
<font color='#f00'>他可以疯狂模拟一些不存在的Key,让你进入数据库去取数,这样就可以拖垮你的数据库,实现击溃你系统的目的。</font>
有效的办法是在服务层先判断这个Key的是否符合标准(比如滴滴的订单数据缓存包含时间戳+用户ID的序列化),这样可以过滤一部分无效攻击。
但是如果他能够破解你key的规则,依旧可以钻漏洞。你可以在缓存层上加一层过滤器,帮你Filter掉那些不合理的攻击。
详细可以参考我这篇《Redis系列16:聊聊布隆过滤器(原理篇)

image.png

3.2.5 消息队列和削峰

如果一个缓存不存在(不存在、过期、被误删都有可能),但是同时有千万请求投奔过来。
<font color='#f00'>这时候关心是不是及时拿回正确数据已经不重要了,保住你的缓存和数据库不被击穿才是关键。</font>
队列的目的是让并行变成串行,这一定程度上降低系统处理用户请求的吞吐能力,但是却能很好的缓解你服务的压力和风险。


image.png

如上图:第一个请求B从数据库中取,后面的C、A就是从缓存服务中取了,压力变小很多。

3.2.6 适当加锁

分布式锁场景,在访问key之前,采用SETNX(set if not exists)来设置另一个短期key来锁住当前key的访问,访问结束再删除该短期key。
这种现象是多个线程同时去查询数据库的这条数据,那么我们可以在第一个查询数据的请求上使用一个 互斥锁来锁住它。
<font color='#f00'>其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后做缓存。后面的线程进来发现已经有缓存了,就直接走缓存。</font>
锁不好的地方就是在其他线程在拿不到锁的时候就等待,<font color='#f00'>这个会造成系统整体吞吐量降低,用户体验度也不好。</font>
<font color='#f00'>这算是一种简单明了的降级策略了。</font>

3.2.7 限流策略

<font color='#f00'>一样是一种在流量井喷时保住服务不雪崩的有效方法,限流一般是从服务层去实现的。</font>
Java服务的话可以使用 Hystrix进行限流 + 降级 ,比如一下子来了1W个请求,超过当前系统的吞吐承受能力,假设单秒TPS的能力只能是 5000个,那么剩余的 5000 请求就可以走限流逻辑。
可以设置一些默认值,然后调用我们自己降级逻辑去FallBack,保护最后的 MySQL 不会被大量的请求挂起。 除了Hystrix之外,阿里的Sentinel 和 Google的RateLimiter 都是不错的选择。
Sentinel 漏桶算法

image.png

RateLimiter 令牌桶算法

image.png

3.2.8 降级策略(备选缓存)

你的缓存层存在主备场景,他们之间定时异步同步,所以允许存在短暂数据不一致的情况。
当你的主服务挂了之后,降级去读备服务,数据时效性没那么高,但是也避免了数据库被打穿的情况发生。


image.png

3.2.9 降级策略(客户端缓存)

参考Redis 6.0的 Client Side Cache,看我这篇《追求性能极致:客户端缓存带来的革命》。
类似4.5做法,客户端缓存时效性会差一点,毕竟存在订阅跟同步的过程,数据没那么新。但是避免大量的请求直接上缓存服务,又因无效的缓存服务又把压力转移给数据库。

image.png

3.2.10 降级策略之空初始值

这是一种短效的降级方式:
如果一个缓存失效的时候,有无数个请求狂奔而来,而第一个请求从进入缓存池,判空,再到数据库检索,再查询出结果并返回设置缓存的这个过程里,缓存是不存在的。
这个就很危险,超高并发下这个短暂的过程足已让千千万万请求投向数据库。更别提这可能是个慢查询,整个过程可能长达2s以上,那对数据库是一种非常大的伤害。
业内有一种做法叫做空初始值,短暂的局部降级来保证整个数据库系统不被击穿。大概流程如下:


image.png

可以看出,整个过程中我们牺牲了A、B、C、D的请求,他们拿回了一个空值或者默认值,但是这局部的降级却保证整个数据库系统不被拥堵的请求击穿。

3.2.11 高可用集群和自动扩缩容

集群模式和自动扩缩容模式从服务到缓存到数据层都应该具备,否则无法根据流量来进行弹性伸缩,保持高可用。
如下图, <font color="#6C8EBF" > 蓝色部件</font>是扩容的部分,每一分层都有自己的动态扩容机制。

image.png
详细可以参考笔者这几篇文章。
云原生:使用HPA和VPA实现集群扩缩容
数据库系列:数据库高可用及无损扩容

3.2.12 雪崩之后的恢复

如果最终导致了缓存雪崩,那么重启后快速的数据恢复也是我们核心的目标。
刚刚恢复重启的缓存服务,这时候数据都是空的,大量的请求流量带来的缓存重建(进而拉动数据库流量)势必会带来压力甚至二次雪崩。
这时候最好的办法就是能够有工具进行缓存恢复,而不是从数据库中去获取数据来重建,这样的过程漫长而负重。
这块可以参考笔者的这两篇文章:
Redis系列:RDB内存快照提供持久化能力
Redis稳定性之战:AOF日志支撑数据持久化

4 总结

扩展阅读:缓存雪崩、击穿、穿透
架构与思维:一次缓存雪崩的灾难复盘
架构与思维:再聊缓存击穿,面试是一场博弈

相关文章

  • 模拟实验 | Redis分布式锁问题&踩坑&解决方案

    1. 模拟场景和环境说明 模拟高并发下卖电影票场景 使用SpringBoot编写卖票的业务,Redis存储热点数据...

  • redis高级功能-队列

    redis队列实现高并发下数据ID读取 id数据预生成id数据预生成:根据业务逻辑,预生成ID数据,通过redis...

  • MI 2021-07-09

    一面 问的设计题偏多 Redis 缓存热点数据 热点数据指的是什么? Redis缓存数据量关注过吗? 如果全部缓存...

  • 6.4-小滴课堂官网-高并发下-商品首页热点数据开发实战—小滴课

    小滴课堂官网-高并发下-商品首页热点数据开发实战 简介:高并发商品首页热点数据开发实战 热点数据 经常会被查询,但...

  • 如何用redis做缓存

    redis缓存 在互联网应用中经常需要用redis来缓存热点数据。 redis数据在内存,可以保证数据读取的高效,...

  • Redis进阶系列一(数据类型-上)

    Redis进阶系列一(数据类型介绍) 秒杀,618,双十一,排队买票热点数据:新闻,投票排名 1.Redis的数据...

  • 1.MySQL导读

    一:影响数据库的性能因素1、超高的QPS与TPS风险:效率低下的sql2、大量的并发和超高的CPU使用率风险:大量...

  • Redis经典使用场景

    redis使用场景 一、热点数据的缓存 由于redis访问速度块、支持的数据类型比较丰富,所以redis很适合用来...

  • Redis高并发下使用及注意事项

    Redis高并发下使用及注意事项 Redis 数据失效导致的雪崩 因为 缓存失效,从而导致大量请求 操作数据库:1...

  • 热点数据

    MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据相关知识:red...

网友评论

    本文标题:超高并发下,Redis热点数据风险破解

    本文链接:https://www.haomeiwen.com/subject/pvkxtjtx.html