剖析 Redis:应对雪崩、穿透和击穿的实战秘籍

前言

用户的数据通常存储在数据库中,而数据库的数据存放在磁盘上。
磁盘的读写速度在计算机硬件中可以说是最慢的。
如果用户的所有请求都直接访问数据库,当请求数量增多时,数据库很容易崩溃。因此,为了避免用户直接访问数据库,会使用 Redis 作为缓存层。
因为 Redis 是内存数据库,我们可以将数据库中的数据缓存在 Redis 里,相当于把数据缓存在内存中。内存的读写速度比硬盘快好几个数量级,这样能大大提高系统性能。

引入缓存层后,就会出现缓存异常的三个问题,即缓存雪崩、缓存击穿和缓存穿透。

缓存雪崩(Cache Avalanche)

雪崩是指在Redis缓存中,大量的key在同一时间过期(失效),导致大量请求直接打到后端数据库,数据库短时间内承受巨大压力,可能导致数据库崩溃,进而影响整个应用系统的性能甚至可用性。例如,在一个电商系统中,有很多热门商品的缓存设置了相同的过期时间,当这些缓存同时过期时,大量查询热门商品的请求就会涌向数据库。

image

应对措施

  • 设置随机过期时间:避免大量key同时过期。可以在设置过期时间时,给每个key的过期时间加上一个小的随机值,使key在一段时间内分散过期。比如原计划10分钟过期的key,设置为10分钟 + 随机数(0 - 2分钟)过期。
  • 构建多级缓存:在Redis缓存之前再设置一层缓存,如本地缓存(如Guava Cache等)。当Redis中的数据过期,本地缓存可以继续提供服务,减轻数据库压力。同时,本地缓存的过期时间可以设置得稍长一些。
  • 服务熔断与降级:当检测到数据库压力过大时,启用熔断机制,暂时停止对数据库的访问,直接返回默认值或者缓存中的旧数据。当数据库压力恢复正常后再重新允许访问。对于一些非核心功能,可以进行服务降级,优先保证核心业务的正常运行。

缓存击穿(Hotspot Invalid)

击穿是指一个热点key(非常频繁被访问的key)在缓存中突然失效,而此时大量的并发请求同时访问这个key,这些请求会直接穿透到数据库,造成数据库瞬间压力过大。例如,在一个热门商品秒杀活动中,该商品的缓存突然过期,大量用户同时请求这个商品的信息,就会导致击穿现象。

应对措施

  • 永不过期 + 后台更新:对于热点key,可以设置为永不过期,然后在后台异步地更新这个key对应的缓存值。这样可以避免热点key突然过期导致的击穿问题。
  • 互斥锁:当发现热点key失效时,使用互斥锁来控制只有一个请求去数据库查询数据并更新缓存,其他请求等待。可以使用Redis的SETNX(SET if Not eXists)命令来实现互斥锁。当一个请求查询发现缓存中热点key不存在时,尝试使用SETNX命令设置一个锁标识,如果设置成功(表示获取到锁),则去数据库查询数据并更新缓存,然后释放锁;如果设置失败(表示锁已被其他请求占用),则等待一段时间后再次尝试查询缓存。

缓存穿透(Cache Penetration)

穿透是指查询一个根本不存在的数据,由于缓存中没有,每次请求都会穿透到数据库。如果攻击者恶意利用这种情况,不断发起对不存在数据的查询,会给数据库带来很大的压力。例如,有人恶意构造大量不存在的用户ID去查询用户信息,这些请求会不断地绕过缓存直接访问数据库。

应对措施

  • 布隆过滤器:在缓存之前增加布隆过滤器。布隆过滤器可以快速判断一个数据是否可能存在于数据库中。如果布隆过滤器判断数据不存在,那么直接返回,不再查询缓存和数据库。虽然布隆过滤器存在一定的误判率(将存在判断为不存在),但可以大大减少不必要的数据库查询。
  • 缓存空对象:当查询数据库发现数据不存在时,在缓存中缓存一个空对象,并设置较短的过期时间。这样下次再查询相同的数据时,直接从缓存中获取空对象,而不必再查询数据库。但是要注意空对象可能会占用一定的缓存空间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程点滴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值