0
点赞
收藏
分享

微信扫一扫

缓存详解

书坊尚 2021-09-29 阅读 95
随笔

1.缓存

2.缓存算法

  1. LRU(least recentlty used,最近最少使用)算法
  2. LFU(least Frequently used,最不经常使用)
  3. FIFO(first in first out,先进先出)

3.缓存穿透

存储穿透:是指查询一个一定不存在的数据,由于缓存是不命中时被动写,并且处于容错考虑,如果从DB查不到数据就不写入缓存,这将导致这个不存在的数据一直去请求DB,是去缓存的意义。

如何解决?

  1. 方案一,缓存空对象。

  2. 方案二,BloomFilter布隆过滤器

    在缓存服务的基础上,构建BloomFilter数据结构。在BloomFilter中存储对应的key是否存在,如果存在,再说明该key的值不为空,逻辑如下:

    为什么BloomFilter不存储Key是不存在的情况?

    缓存空对象 BloomFilter
    使用场景 1.数据命中率不高;2.保证一致性 1.数据命中不高。2数据相对固定,实时性低
    维护成本 1.代码维护简单;2.需要过多的缓存空间;3.数据不一致 1.代码维护复杂;2.缓存空间占用少

4.缓存雪崩

概念

缓存雪崩,是指缓存由于某些原因无法提供服务(比如缓存挂了),所有的请求到达DB,导致DB负荷增大,最终挂掉的情况。

如何解决

  1. 缓存高可用

  2. 本地缓存

  3. 请求DB限流

    • 有一部分用户任然可以使用该系统。
    • 缓存服务恢复后,立即可以使用。不用再去管理DB服务

    被限流的请求,我们可以通过服务降级,提供一些默认的值,比如空白页面、友情提示等到。我们可以通过Sentinel、Hystrix等来实现。

引入本地缓存的问题

  • 本地缓存实时性如何保证
    • 引入消息队列。在数据更新时,发布数据更新的消息;而进程中有相应的消费者消费该消息,从而更新本地缓存;
    • 设置较短的过期时长,请求从DB拉取数据;
    • 通过手动过期
  • 每个进程可能会在本地缓存相同的数据,导致资源浪费?
    • 需要配置本地的缓存过期策略和缓存数量上限。

5.缓存击穿

概念

如何解决

  1. 方案一,使用互斥锁

    • 1获取分布式锁,直到成功或者超时。如果超时则抛出异常,成功,继续向下执行
    • 2、获取缓存,如果存在值,直接返回,如果不存在,继续。
    • 3、查询DB,更新到缓存,返回值。
  2. 方案二,手动过期

    • 1、获取缓存,通过value中的时间来比较是否过期。如果未过期,直接返回,如果过期,继续向下执行。
    • 2、通过一个后台的异步线程进行缓存的构建,也就是“手动过期”。通过后台的异步线程,保证只有一个线程查询DB。
    • 3、同时,虽然Value还是过期,但还是直接返回。通过这样的方式保证了服务的可用性,但是损失了一定的实效性。

6.缓存与DB一致性保持

产生不一致的原因

  1. 并发场景下,导致老的DB数据写入到缓存中。

  2. 缓存和DB的操作不在同一个事物中,可能DB操作成功,二cache操作失败,这样会导致不一致

解决方案

  1. 将缓存可能出现的并行写,实现串行写

    1. 在写请求前,先淘汰缓存之前,先获取分布式锁。

      写-->获取锁-->delete cache-->update db ---> write cache

    2. 在读请求时,如果缓存不存在,先去获取分布式锁

      读-->读cache,如果null-->获取锁-->查询cache,如果null-->查db-->write cache

  2. 实现缓存的最终一致性。

    1. 先淘汰缓存,在写数据库。

    2. 先写数据库,在更新缓存

      基于定时任务来实现

      • 首先,写入数据库
      • 然后在写入数据库所在的事物中,插入一个记录的任务表,该记录表存储需要存入cache中的key和value
      • 【异步】遍历任务表,写入cache

      基于消息队列来实现

      • 首先,写入数据库
      • 然后发送带我缓存key和value的事物消息。
      • 【异步】消费者消费该消息,写入缓存

      基于数据库的binlog日志

      • 应用直接将数据写入数据库
      • 数据库会更新binlog日志
      • 利用Cannal中间件读取binlog日志
      • Cannal借助于限流主键按频率将数据发送到MQ中
      • 应用监控MQ渠道,将MQ的数据缓存到cache中

7.缓存预热

启动时,先将热点数据缓存到缓存中

如何实现

  1. 数据量不大的时候,项目启动,自动进行初始化
  2. 通过修复脚本,执行脚本
  3. 写管理页面,手动操作

7.缓存淘汰策略

  1. 定时清理
  2. 当用户请求过来的时候,去判断是否过期,过期的话就去底层系统获取数据,进行更新

举报

相关推荐

0 条评论