Redis 之缓存击穿的防范技巧
什么是缓存击穿
缓存击穿是指在高并发的访问下,当缓存中没有对应的数据,而请求需要频繁访问数据库,从而导致数据库性能下降,甚至瘫痪的现象。这是因为有大量的并发请求同时访问数据库,导致数据库负载过高,无法承受。
缓存击穿的原因
- 热点数据:热点数据即指被大量访问的数据,如果热点数据没有被缓存,那么就没有发挥 Redis 的缓存优势,并且大量的数据访问可能导致缓存数据被秒杀。
- 缓存穿透:缓存穿透是指查询缓存和数据库中都不存在的数据,导致每次都需要查询数据库,此时会发生大量的 "缓存穿透" 请求,而数据库无法承受这么多请求而导致宕机。
- DNS攻击:恶意攻击者可能利用大量的虚假请求占用缓存服务器上的资源,使得正常请求无法得到处理,从而导致了缓存穿透。
解决方案
1. 互斥锁
在发起查询请求之前,首先会尝试获取互斥锁,如果获取失败,则等待,直至成功获取互斥锁,在获取成功之后再开始查询。为查询加上互斥锁相当于串行进行查询,从而避免了并发查询请求的发起,从而有效防止了缓存击穿问题。这种方式有一定的弊端,效率可能会降低,因为串行查询需要等待锁的释放。
示例代码:
-- -------------------- ---- ------- ------ ------ -------------- ---- - -- ----- ------ ------- - ------ - ---- ------ --------- - ----------------------------- ------- --------- - ------------------------------------------------ ---------- --- ------------------ -- ----------- - -- ----- ------ ----- - ------------------------------------- -- ------ -- ----- - ------ -------- ------ - -- ------ ------ ------ - -------------------- -- ---- ------------------------------------ ------- ---- ------------------ -- --- ------ ------------ - ----------------------------------------- -- ------------- -- ---- -- ------------------------------- - ------------------------------ - ------ ------- - ---- - --- - -- ---- ------------------ - ----- --------------------- -- - -------------------- - ------ ------------- - -
2. 提前预热
提前预热其实就是在 Redis 中主动将热点数据预先加载。使用这种方式的前提是能够确定热点数据,在缓存中主动预加载这些数据,从而在后续访问中减少了对数据库的访问次数。这种方式能够有效地缓解缓存击穿的问题。
示例代码:
-- -------------------- ---- ------- -------------- ------ ---- ------ - -------- ---- - -------- ------- ------- ----- --- ------- --- - ----- - -- ----- ------ ------ - ---------------------------- -- ---- ------------------------------------ ------- ---- ------------------ - -
3. 布隆过滤器
布隆过滤器是一种数据结构,可以用于缓存穿透的问题。将所有可能的数据哈希到一个足够大的 bit 数组中,如果某些位都为 1,那么该数据就可能存在,这样即使查询请求中的 key 不存在,但是在经过哈希之后能够得到 bit 数组中的某几个标志位都是 1,这样就可以初步判断请求中的 key 不存在缓存中,直接返回 null,不再对数据库进行查询,从而避免大量的数据库查询请求。
示例代码:
-- -------------------- ---- ------- ------ ------ ----- ---------------- - ------- ------ ----- --- ------------ - - -- --- -- ---------- --- - ------------------------------------ -- ------- ------ ----- ----- ----- - --- ----- - -- -- --- --- --- --- -- -- ------- ------ ------ ------ - --- --------------------- --- - ---------------------- -- ------- ------ ----- --------------- ---- - ----- ------ - --- ------------------ --- ---- - - -- - - ------------- ---- - --- -------- - ----------------------- - ---------- --------- - -------- - ------------- - ------ ------- - ------ ------ ---- ---------- ---- - ----- ------ - -------------- --- ---- ----- - ------- - ----------------- ------ - - ------ ------ ------- --------------- ---- - ----- ------ - -------------- --- ---- ----- - ------- - -- -------------------- - ------ ------ - - ------ ----- - -
总结
缓存击穿是 Redis 中一个相对常见的问题,但是针对不同的业务场景,应有针对性地采取不同的解决方案。本文介绍了互斥锁、提前预热以及布隆过滤器几种解决方案,这些方案都能够有效地缓解缓存击穿的问题,使用时需要权衡方案的优点和弊端,选择适合自己业务场景的方案。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6468355e968c7c53b08653eb