缓存

作者: CoderZzbJohn | 来源:发表于2020-04-06 17:54 被阅读0次

    缓存类别

    1.线程级缓存:ThreadLocal
    适用场景:同个线程内需要多次请求耗时接口,例如需要根据权限范围查询具体数据,多次查权限。
    2.单机缓存:GuavaCache
    适用场景:数据量较少,请求频率高。
    3.分布式缓存:Redis
    适用场景:

    缓存遇到的问题

    缓存并发

    现象:热点key并发量高。当key过期时,同一时刻会有多个请求打到db,影响db性能。
    解决方案:
    1.当key不存在需要查询db时加锁,获取到锁的线程才能查db。其余线程自旋等待。
    2.GuavaCache中expireAfterWrite当某个key失效时,第一个线程会锁住当前key所在的segment,其余线程等待,容易造成多线程阻塞。可以通过refreshAfterWrite解决,定时更新缓存。当缓存失效时,只有第一个线程从db捞数据,其余线程直接返回旧数据。

    缓存雪崩

    现象:在同一时刻缓存中有多个key失效时,多个请求直接打到db,导致db负载过高。
    解决方案:初始化缓存时,过期时间设置成定时+随机时间,避免大量key同一时刻失效。

    缓存穿透

    现象:当请求缓存中不存在的key值,请求直接打到了db。
    解决方案:初始化缓存或者查询缓存时,如果数据不存在,则缓存中设置空值。(疑问:初始化时,如何给不存在的key设置空值)

    缓存更新策略(一致性)

    1.Cache-Aside

    1.先更新缓存在更新数据库。
    存在问题:
    -缓存更新成功,数据库更新失败,缓存中的值为旧值。
    2.先更新数据库在更新缓存。
    存在问题:
    -key不存在时。线程1读取数据库旧值,线程2更新db,线程2将值放入缓存,线程1将值再次放入缓存,缓存中为旧值
    -key不存在时。线程1更新db,线程2更新db,线程2将值放入缓存,线程1将值再次放入缓存,缓存中为旧值


    image.png

    3.先更新数据库,再失效缓存
    存在问题:
    -key失效,线程1读取db旧值,线程2更新db,线程2失效缓存,线程1将db旧值放入缓存。


    image.png

    产生条件
    1.读操作读缓存失效
    2.有个并发的写操作
    3.读操作早于写操作进入数据库,晚于写操作更新缓存

    2.Cache-As-SoR systemOfRecord 有cache组件统一更新缓存与db,客户端无感知。

    1.Read-through
    2.Write-through
    3.Wtire-behind

    缓存淘汰策略

    1.LRU最近最少使用:map中记录访问次数
    2.FIFO先进先出。

    缓存过期策略

    1.定期清理
    2.查询时判断key是否过期
    3.结合1+2

    相关文章

      网友评论

          本文标题:缓存

          本文链接:https://www.haomeiwen.com/subject/tggbphtx.html