Guava缓存与异步加载,用于非阻塞获取

huangapple go评论64阅读模式
英文:

Guava cache with async loading for non-blocking get

问题

I'm trying to use Guava cache with async loading of values and have non-blocking get(). Because I do load values from DB so it is pretty expensive, it would be OK to serve temporally out-dated data until new data is loaded in the background but not OK to block when trying to read from cache.

我正在尝试使用Guava缓存以异步方式加载值并使用非阻塞的get()。因为我从数据库加载值,所以这是相当昂贵的操作,所以在后台加载新数据之前,提供临时过时的数据是可以接受的,但在尝试从缓存读取时阻塞是不可接受的。

I first tried using refreshAfterWrite with expireAfterWrite but it does not seem to achieve what I'm looking to do. It seems from the documentation of refreshAfterWrite, entries needed refresh will not be remove until read which makes the call to cache.get() blocking!

我首先尝试使用refreshAfterWriteexpireAfterWrite,但似乎无法实现我想要的效果。根据refreshAfterWrite的文档,需要刷新的条目直到被读取之前都不会被移除,这会导致调用cache.get()时出现阻塞!

Automatically timed refreshing can be added to a cache using CacheBuilder.refreshAfterWrite(long, TimeUnit). In contrast to expireAfterWrite, refreshAfterWrite will make a key eligible for refresh after the specified duration, but a refresh will only be actually initiated when the entry is queried.

可以使用CacheBuilder.refreshAfterWrite(long, TimeUnit)将自动定时刷新添加到缓存中。与expireAfterWrite不同,refreshAfterWrite将使键在指定的持续时间后有资格进行刷新,但只有在查询条目时才会实际启动刷新。

This is how I'm creating the cache, I define a loader like this:

这是我创建缓存的方式,我定义了一个类似这样的加载器:

class DbCacheLoader() extends CacheLoader[K, V] {
  override def load(key: K): V = {
    // read from DB
  }
}

Then, I tried using the refreshOnWrite option to build the cache like this

然后,我尝试使用refreshOnWrite选项来构建缓存,如下所示:

val syncLoader = new DbCacheLoader()
val val cacheLoader = CacheLoader.asyncReloading(syncLoader, threadPool)
val cache: LoadingCache[K, V] = CacheBuilder.newBuilder()
  .refreshAfterWrite(timeout, TimeUnit.MILLISECONDS)  // timeout
  .expireAfterWrite(hardTimeout, TimeUnit.MILLISECONDS) // hard timeout
  .concurrencyLevel(threadPoolSize * 10)
  .recordStats()
  .build[K, V](cacheLoader)

How can I have non-blocking get() with Guava cache?

我如何在Guava缓存中实现非阻塞的get()操作?

英文:

I'm trying to use Guava cache with async loading of values and have non-blocking get(). Because I do load values from DB so it is pretty expensive, it would be OK to serve temporally out-dated data until new data is loaded in the background but not OK to block when trying to read from cache.

I first tried using refreshAfterWrite with expireAfterWrite but it does not seem to achieve what I'm looking to do. It seems from the documentation of refreshAfterWrite, entries needed refresh will not be remove until read which makes the call to cache.get() blocking!

> Automatically timed refreshing can be added to a cache using CacheBuilder.refreshAfterWrite(long, TimeUnit). In contrast to expireAfterWrite, refreshAfterWrite will make a key eligible for refresh after the specified duration, but a refresh will only be actually initiated when the entry is queried.

This is how i'm creating the cache, I define a loader like this:

class DbCacheLoader() extends CacheLoader[K, V] {
  override def load(key: K): V = {
    // read from DB
  }
}

Then, I tried using the refreshOnWrite option to build the cache like this

val syncLoader = new DbCacheLoader()
val val cacheLoader = CacheLoader.asyncReloading(syncLoader, threadPool)
val cache: LoadingCache[K, V] = CacheBuilder.newBuilder()
  .refreshAfterWrite(timeout, TimeUnit.MILLISECONDS)  // timeout
  .expireAfterWrite(hardTimeout, TimeUnit.MILLISECONDS) // hard timeout
  .concurrencyLevel(threadPoolSize * 10)
  .recordStats()
  .build[K, V](cacheLoader)

How can I have non-blocking get() with Guava cache?

答案1

得分: 1

你尝试过在 CacheLoader 上实现 refresh 方法吗?这个实现同步地委托给了 load(K)。建议在使用 CacheBuilder.refreshAfterWrite(long, java.util.concurrent.TimeUnit) 时,用异步实现进行重写。看起来这可能是你所寻求的行为所需的。

英文:

Have you tried implementing the refresh method on CacheLoader?

> This implementation synchronously delegates to load(K). It is recommended that it be overridden with an asynchronous implementation when using CacheBuilder.refreshAfterWrite(long, java.util.concurrent.TimeUnit).

Seems like it might be required for the behavior you're seeking.

huangapple
  • 本文由 发表于 2023年5月21日 02:02:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76296669.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定