Guava Cache 实现非阻塞 get() 的异步刷新最佳实践

花韻仙語

花韻仙語

2026-07-10

445人浏览

原创

Guava Cache 实现非阻塞 get() 的异步刷新最佳实践

本文详解如何通过重写 CacheLoader.reload() 方法,结合 refreshAfterWrite 与 asyncReloading,在 Guava Cache 中实现真正的非阻塞读取——请求直接返回旧值,后台异步加载新数据,避免 DB 查询阻塞主线程。

本文详解如何通过重写 `cacheloader.reload()` 方法,结合 `refreshafterwrite` 与 `asyncreloading`,在 guava cache 中实现真正的非阻塞读取——请求直接返回旧值,后台异步加载新数据,避免 db 查询阻塞主线程。

Guava Cache 原生的 refreshAfterWrite 并不自动提供非阻塞语义:当条目触发刷新条件后,首次 get() 调用仍会同步执行 reload()(默认委托给 load()),导致线程阻塞。要实现“立即返回旧值 + 后台异步更新”,关键在于显式重写 CacheLoader.reload(K, V) 方法,并确保其返回 ListenableFuture ——而非依赖 asyncReloading() 的封装。

以下是正确实现步骤:

Seedance
Seedance

字节跳动 Seed 团队自研的多模态 AI 视频生成大模型

下载

✅ 正确做法:重写 reload() 方法(核心)

import com.google.common.cache.{CacheLoader, LoadingCache}
import com.google.common.util.concurrent.{ListenableFuture, MoreExecutors, Futures}
import scala.concurrent.ExecutionContext

class AsyncDbCacheLoader[K, V](dbExecutor: ExecutionContext) extends CacheLoader[K, V] {
  // 必须重写 reload:返回 Future,且不阻塞调用线程
  override def reload(key: K, oldValue: V): ListenableFuture[V] = {
    // 在独立线程池中异步加载新值
    val future = scala.concurrent.Future {
      // ⚠️ 这里执行实际的 DB 查询(耗时操作)
      loadFromDatabase(key)
    }(dbExecutor)

    // 将 Scala Future 转为 Guava ListenableFuture
    Futures.transform(future, (v: V) => v, MoreExecutors.directExecutor())
  }

  // load() 仅用于初始加载(首次 get),可同步实现
  override def load(key: K): V = {
    loadFromDatabase(key)
  }

  private def loadFromDatabase(key: K): V = {
    // 模拟 DB 查询逻辑(如 JDBC/ORM 调用)
    ???
  }
}

✅ 构建缓存:启用 refresh + 禁用自动 asyncReloading

val dbThreadPool = Executors.newFixedThreadPool(8)
val dbEc = ExecutionContext.fromExecutor(dbThreadPool)

val cacheLoader = new AsyncDbCacheLoader[String, User](dbEc)
val cache: LoadingCache[String, User] = CacheBuilder.newBuilder()
  .refreshAfterWrite(30, TimeUnit.SECONDS)   // 触发后台刷新的阈值
  .expireAfterWrite(5, TimeUnit.MINUTES)     // 硬过期兜底(防止 stale 数据永久存在)
  .concurrencyLevel(4)
  .recordStats()
  .build(cacheLoader) // ❌ 不要再 wrap with CacheLoader.asyncReloading(...)

? 关键点:不要使用 CacheLoader.asyncReloading()。该工具仅对 load() 做异步包装,但 refreshAfterWrite 机制优先调用 reload();若 reload() 未重写,它将回退到同步 load(),彻底失效。

✅ 使用方式:get() 完全非阻塞

// 立即返回当前缓存值(即使已过 refresh 时间),绝不阻塞
val user: User = cache.get("user-123") 

// 后台已在 reload() 中发起异步 DB 查询,成功后自动更新缓存
// 下次 get() 将拿到新值(或仍为旧值,直到 reload 完成)

⚠️ 注意事项与最佳实践

  • reload() 必须返回 ListenableFuture:这是 Guava 判断是否支持异步刷新的唯一依据。返回 null 或抛异常会导致刷新失败并降级为同步加载。
  • 线程安全:reload() 可被并发调用(同一 key 多次 get 触发),需确保 DB 加载逻辑线程安全,或依赖数据库连接池/ORM 自身并发控制。
  • 错误处理:建议在 reload() 中捕获 DB 异常并记录日志,避免抛出异常(否则 Guava 会保留旧值并静默失败);可通过 Futures.withFallback 提供降级逻辑。
  • 监控与调试:启用 .recordStats() 后,检查 cache.stats().evictionCount() 和 cache.stats().loadExceptionCount() 可验证刷新行为是否符合预期。
  • 替代方案考虑:若项目已迁移到 Java 11+,推荐评估 Caffeine —— 其 refreshAfterWrite 默认异步且 API 更简洁,Guava 已停止积极维护。

通过精准重写 reload(),你就能获得真正低延迟、高吞吐的缓存读取体验:用户请求毫秒级响应,数据新鲜度由后台刷新保障,彻底解耦 I/O 与业务逻辑。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

3891

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

2861

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

2900

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

638

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

602

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

728

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1318

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

18866

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

647

8

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.4万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 131.8万人学习