缓存的更新有两种方法:

  • 被动更新:先从缓存获取,没有则回源获取,再更新缓存;
  • 主动更新:发现数据改变后直接更新缓存(在分布式场景下,不容易实现)

在高并发环境,被动回源是需要注意的。 问题:高并发场景下,大量请求在同一时间回源,大量的请求同一时间穿透到后端,容易引起后端服务崩溃(也容易引起并发问题)。

guava cache解决办法: guava cache保证单线程回源,对于同一个key,只让一个请求回源load,其他线程阻塞等待结果。同时,在Guava里可以通过配置expireAfterAccess/expireAfterWrite设定key的过期时间,key过期后就单线程回源加载并放回缓存。

这样通过Guava Cache简简单单就较为安全地实现了缓存的被动更新操作。

但是如果对于同一时间大量不同的key同时过期,造成大量不同的key同时回源,这种怎么解决呢?

guava cache实现类似ConcurrentHashMap,维护segment数组,每个segment独享一个锁,ConcurrentHashMap是通过这种机制来实现分段锁,ConcurrentHashMap默认分了16个segment; guava Cache默认是4个segment,故guava cache的并发级别默认是4个,也就是说默认情况下,即便是大量不同的key同时过期,最多只也有4个线程并发回源,理论上不会给后端造成过大的压力。

guava refresh和expire刷新机制

  • expireAfterAccess: 当缓存项在指定的时间段内没有被读或写就会被回收。
  • expireAfterWrite:当缓存项在指定的时间段内没有更新就会被回收。
  • refreshAfterWrite:当缓存项上一次更新操作之后的多久会被刷新。

仅仅使用 expireAfterWrite或者expireAfterAccess就可以实现缓存定时过期,但是频繁的过期会造成频繁的单线程回源,然而guava cache回源的时候会独占一个segment的锁,对于同一个segment的其他的读操作 处于loading状态的则会继续等待,value expire或者为null的key则会阻塞等待segment的锁。

expireAfterWrite或者expireAfterAccess的实现在数据回源的时候会让请求block住,以获取最新的值。数据实时性保证的较好,但是阻塞住请求对于一些响应要求严苛的业务可能是没办法接受的。那有没有解决的办法呢?

我们且看refreshAfterWrite:

refreshAfterWrite通过定时刷新可以让缓存项保持可用。缓存项只有在被检索时才会真正刷新(如果CacheLoader.refresh实现为异步,那么检索不会被刷新拖慢)。也是保证同一个segment的单线程回源,但是与expireAfterWrite不同的是:其他线程访问loading状态的key时,仅仅稍微等一会,没有等到就返回旧值,整个请求就比较平滑。 与此同时,也引入了一个问题,refreshAfterWrite策略下,如果一个key长期没有被访问,就有可能会访问到很久之前的旧值。例如refreshAfterWrite(5),5s刷新一次,如果1min内,这个key都没有被访问,那么1min之后访问这个key,仍然有可能访问到旧数据,尽管我们设置了5s刷新一次。(guava cache并没单独的线程来处理刷新的逻辑,而是通过读操作来触发清理工作)

对于这个问题有没有这种的办法呢? guava cache支持我们同时使用expireAfterWrite&refreshAfterWrite,我们既可以通过组合的策略既保证性能,又保证不要读取到太旧的数据。 比如我们有需求:要求请求必须平滑,而且不能读到5s之前的旧数据。

我们可以如下设置来满足需求:

1
2
3
4
5
LoadingCache<String, String> cache = CacheBuilder.newBuilder().refreshAfterWrite(4L, TimeUnit.SECONDS).expireAfterWrite(5L, TimeUnit.SECONDS).build(loader);

expireAfterWrite(5L, TimeUnit.SECONDS)能保证不会读到5s之前的旧数据,refreshAfterWrite(4L, TimeUnit.SECONDS)能保证大部分请求都在4s左右被刷新,小部分访问量较少的在5s的时候通过expireAfterWrite策略重新被回源。

guava后台异步刷新

refreshAfterWrite的刷新调用的是reload,reload的默认实现是在当前线程里面reload,也会造成一些卡顿,如果希望异步reload,需要重载这个方法。

1
2
3
4
5
6
 public ListenableFuture<V> (K key, V oldValue) throws Exception {checkNotNull(key);checkNotNull(oldValue);return Futures.immediateFuture(load(key));//当前线程调用load,会造成当前线程的卡顿,如果不接受卡顿,需要重载这个方法} 

转载:https://www.dazhuanlan.com/2019/10/06/5d99928eb6380/

Guava Cache 过期回源相关推荐

  1. CDN 二级回源实现

    随着Cache节点数量的增加,大量的图片回源,导致图片源站的压力在不断增加.源站load飙高.IO飙高.由于图片源站上还有其他业务,必须使源站的压力降下来: 1.更改Cache 的回源策略(每天都有新 ...

  2. ATS 6.2.1中缓存文件过期并不回源校验的“坑”

    事先说明 标题说是"坑",并没有说是"bug",也就是多半是玩的姿势不对. 线上问题 我司(lecloud)目前线上大小文件都是使用的ATS 6.2.1版本,昨 ...

  3. Google guava cache源码解析1--构建缓存器(3)

    此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 下面介绍在LocalCache(CacheBuilder, CacheLoader)中调用的一些方法: Ca ...

  4. guava cache reload返回新旧值解析

    1.调用guava cache的get方法,如果对应的key为空,那么会调用loader的load方法去加载对象并放置到cache中然后返回load方法返回的值 2.当比如设置expireAfterW ...

  5. Ehcache与Guava Cache的介绍

    Ehcache和Guava Cache一样都是本地缓存,也同为很成熟的JVM级别的缓存,可以满足绝大多数情况的需求.下面分别介绍一下这两种缓存技术 Ehcache Ehcache是一个用Java实现的 ...

  6. 重新认识下JVM级别的本地缓存框架Guava Cache——优秀从何而来

    Guava Cache初识 Guava是Google提供的一套JAVA的工具包,而Guava Cache则是该工具包中提供的一套完善的JVM级别的高并发缓存框架.其实现机制类似ConcurrentHa ...

  7. [由零开始]Guava Cache介绍和用法

    Guava Cache介绍 Guava是Google提供的一套Java工具包,而Guava Cache是一套非常完善的本地缓存机制(JVM缓 存). Guava cache的设计来源于CurrentH ...

  8. Guava Cache的使用方式

    maven依赖 <!--Guava Cache--><dependency><groupId>com.google.guava</groupId>< ...

  9. 是什么让 Spring5 放弃了使用 Guava Cache?

    来源:https://albenw.github.io/posts/a4ae1aa2/ 概要 Caffeine是一个高性能,高命中率,低内存占用,near optimal 的本地缓存,简单来说它是Gu ...

  10. 学习Guava Cache知识汇总

    (一)MapMaker 在软件开发中,Cache缓存技术一直是非常重要的主题,不管我们正在进行任何简单的编程工作,我们总能在编程过程中找到一些缓存机制,即使是你使用一个 Map获取静态的值,它也是缓存 ...

最新文章

  1. 每年“骗”马云10亿,被骂大忽悠,他却当选中国工程院院士?
  2. React学习笔记3:React脚手架
  3. 网页左下角蒲公英动画
  4. Web群集与日志管理Haproxy搭建
  5. 解决 No projects are available for deployment to this server!
  6. 201671010139 2016-2017-2 JAVA 和C语言的语法区别
  7. python中math.log注意点
  8. 数据结构与算法(转)
  9. mysql主主同步机制+keepalived实现MySQL高可用
  10. Java 定时任务JOB
  11. 【Red Hat7创建/扩容/删除逻辑卷 #步骤非常非常详细】
  12. 数据结构 - 环形队列
  13. 小甲鱼主讲—P41—指针03
  14. 如何注册可以群发邮件的邮箱?群发邮件怎么发送呢?
  15. 1.1 行列式(1)
  16. KOLO是如何赋能NFT音乐行业?
  17. 网络运维与管理2013超值精华本
  18. C# AForge的简单使用
  19. 关于今天的劳动仲裁说明
  20. 太极链_区块链将成为保险行业的新环境

热门文章

  1. Android 10去除电池图标以及设置
  2. 高速公路收费标准c语言,c语言课程设计报告-高速公路收费系统
  3. 解决用友固定资产出现的“不能月末结账,可能月末未结账”的处理办法
  4. 安全算法-对称加密与非对称加密
  5. 未转变者服务器怎么弄指令权限,» 未转变者 unturned管理员指令
  6. 如何使用微信公众平台测试号进行系统开发
  7. 微信支付失败-1彻底扫坑
  8. 物理计算机主机ip在哪,查看电脑的物理地址_查看电脑的物理ip地址
  9. 个人邮箱如何进行群发邮件?
  10. 小米C++开发笔试真题