Redis 之缓存击穿的防范技巧

阅读时长 6 分钟读完

Redis 之缓存击穿的防范技巧

什么是缓存击穿

缓存击穿是指在高并发的访问下,当缓存中没有对应的数据,而请求需要频繁访问数据库,从而导致数据库性能下降,甚至瘫痪的现象。这是因为有大量的并发请求同时访问数据库,导致数据库负载过高,无法承受。

缓存击穿的原因

  • 热点数据:热点数据即指被大量访问的数据,如果热点数据没有被缓存,那么就没有发挥 Redis 的缓存优势,并且大量的数据访问可能导致缓存数据被秒杀。
  • 缓存穿透:缓存穿透是指查询缓存和数据库中都不存在的数据,导致每次都需要查询数据库,此时会发生大量的 "缓存穿透" 请求,而数据库无法承受这么多请求而导致宕机。
  • DNS攻击:恶意攻击者可能利用大量的虚假请求占用缓存服务器上的资源,使得正常请求无法得到处理,从而导致了缓存穿透。

解决方案

1. 互斥锁

在发起查询请求之前,首先会尝试获取互斥锁,如果获取失败,则等待,直至成功获取互斥锁,在获取成功之后再开始查询。为查询加上互斥锁相当于串行进行查询,从而避免了并发查询请求的发起,从而有效防止了缓存击穿问题。这种方式有一定的弊端,效率可能会降低,因为串行查询需要等待锁的释放。

示例代码:

-- -------------------- ---- -------
------ ------ -------------- ---- -
    -- -----
    ------ ------- - ------ - ----
    ------ --------- - -----------------------------
    ------- --------- - ------------------------------------------------ ---------- --- ------------------
    -- ----------- -
        -- -----
        ------ ----- - -------------------------------------
        -- ------ -- ----- -
            ------ -------- ------
        -
        -- ------
        ------ ------ - --------------------
        -- ----
        ------------------------------------ ------- ---- ------------------
        -- ---
        ------ ------------ - -----------------------------------------
        -- ------------- -- ---- -- ------------------------------- -
            ------------------------------
        -
        ------ -------
    - ---- -
        --- -
            -- ----
            ------------------
        - ----- --------------------- -- -
            --------------------
        -
        ------ -------------
    -
-

2. 提前预热

提前预热其实就是在 Redis 中主动将热点数据预先加载。使用这种方式的前提是能够确定热点数据,在缓存中主动预加载这些数据,从而在后续访问中减少了对数据库的访问次数。这种方式能够有效地缓解缓存击穿的问题。

示例代码:

-- -------------------- ---- -------
--------------
------ ---- ------ -
    -------- ---- - -------- ------- ------- -----
    --- ------- --- - ----- -
        -- -----
        ------ ------ - ----------------------------
        -- ----
        ------------------------------------ ------- ---- ------------------
    -
-

3. 布隆过滤器

布隆过滤器是一种数据结构,可以用于缓存穿透的问题。将所有可能的数据哈希到一个足够大的 bit 数组中,如果某些位都为 1,那么该数据就可能存在,这样即使查询请求中的 key 不存在,但是在经过哈希之后能够得到 bit 数组中的某几个标志位都是 1,这样就可以初步判断请求中的 key 不存在缓存中,直接返回 null,不再对数据库进行查询,从而避免大量的数据库查询请求。

示例代码:

-- -------------------- ---- -------
------ ------ ----- ---------------- -
    ------- ------ ----- --- ------------ - - -- --- -- ----------
    ---
     - ------------------------------------
     --
    ------- ------ ----- ----- ----- - --- ----- - -- -- --- --- --- --- -- --
    ------- ------ ------ ------ - --- ---------------------

    ---
     - ----------------------
     --
    ------- ------ ----- --------------- ---- -
        ----- ------ - --- ------------------
        --- ---- - - -- - - ------------- ---- -
            --- -------- - ----------------------- - ----------
            --------- - -------- - -------------
        -
        ------ -------
    -

    ------ ------ ---- ---------- ---- -
        ----- ------ - --------------
        --- ---- ----- - ------- -
            ----------------- ------
        -
    -

    ------ ------ ------- --------------- ---- -
        ----- ------ - --------------
        --- ---- ----- - ------- -
            -- -------------------- -
                ------ ------
            -
        -
        ------ -----
    -
-

总结

缓存击穿是 Redis 中一个相对常见的问题,但是针对不同的业务场景,应有针对性地采取不同的解决方案。本文介绍了互斥锁、提前预热以及布隆过滤器几种解决方案,这些方案都能够有效地缓解缓存击穿的问题,使用时需要权衡方案的优点和弊端,选择适合自己业务场景的方案。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6468355e968c7c53b08653eb

纠错
反馈