Redis击穿、雪崩与穿透

78 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第30天,点击查看活动详情

什么是击穿?

缓存中没有,但是数据库中有的数据,假如是热点数据,那key在缓存过期的一刻,同时有大量的请求,这些请求都会击穿到数据库,造成瞬时数据库请求量大、压力增大。

预防方案:

  1. 设置热点数据不过期

  2. 定时任务定时更新缓存

  3. 设置互斥锁

SpringCache解决方案:

缓存的同步syn 
sync可以指示底层将缓存锁住,使只有一个线程可以进入计算,而其他线程阻塞,知道返回结果更新到缓存中

示例代码:

@Cacheable(value = {"product"},key = "#root.args[0]", cacheManager = "customCacheManager", sync=true)

什么是雪崩?

大量的key设置了相同的过期时间,导致缓存的数据在同一时刻全部失效,造成瞬时数据库请求量大、压力骤增,引起雪崩

预防方案:

  1. 存数据的过期时间设置随机,防止同一时间大量数据过期现象发生\

  2. 设置热点数据永远不过期,定时任务定时更新

SpringCache解决方案:

  1. 设置差别的过时时间

  2. 比如CacheManager配置多个过期时间维度

  3. 配置文件 time-to-live 配置

    cache:
    #使用的缓存类型
     type: redis
    #过时时间
     redis:
       time-to-live: 3600000
       # 开启前缀,默以为true
       use-key-prefix: true
       # 键的前缀,默认就是缓存名cacheNames
       key-prefix: XD_CACHE
       # 是否缓存空结果,防止缓存穿透,默以为true
       cache-null-values: true
    

什么是穿透?

缓存穿透即查询不存在的数据,如果从存储层查不到数据则不写入缓存这将导致这个不存在的数据每次请求都要到储存层去查询,失去了缓存的意义。存在大量查询不存在的数据,可能数据库就挂掉了\

预防方案:

  1. 接口层增加校验,数据合理性校验

  2. 缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,设置短点的过期时间,防止同个key被一直攻击

SpringCache解决方案:

空结果也缓存,默认不配置condition或者unless就行

cache:
   #使用的缓存类型
    type: redis
   #过时时间
    redis:
      time-to-live: 3600000
      # 开启前缀,默以为true
      use-key-prefix: true
      # 键的前缀,默认就是缓存名cacheNames
      key-prefix: XD_CACHE
      # 是否缓存空结果,防止缓存穿透,默以为true
      cache-null-values: true