0

Scala 应用程序用例:

我们有一个基于 Scala 的模块,它从全局缓存(Redis)读取数据并将其保存到本地缓存(Scaffine)中。由于我们希望这些数据异步刷新,因此我们使用 LoadingCache 并将 refreshAfterWrite 持续时间设置为 2.second 的刷新窗口。

问题:

在本地缓存中设置值时,我们需要设置不同的过期时间,具体取决于 redis(全局缓存)中是否存在键。

例如 ,如果键不存在于全局缓存中,我们希望将相同的键保存在本地缓存中,默认值刷新窗口设置为 5.minutes。如果全局缓存中存在键,我们希望将其存储在本地缓存中,并将实际值和刷新窗口设置为 30.minute

示例代码

object LocalCache extends App {

  // data being stored in the cache
  class DataObject(data: String) {
    override def toString: String = {
      "[ 'data': '" + this.data + "' ]"
    }
  }

  // loader helper
  private def loaderHelper(key: Int): Future[DataObject] = { 
    // this method will replace to read the data from Redis Cache
    // for now, returns different values per key

    if (key == 1) Future.successful(new DataObject("LOADER_HELPER_1"))
    else if (key == 2) Future.successful(new DataObject("LOADER_HELPER_2"))
    else Future.successful(new DataObject("LOADER_HELPER"))
  }

  // async loader
  private def loader(key: Int): DataObject = {
      Try {
        Await.result(loaderHelper(key), 1.seconds)
      } match {
        case Success(result) =>
          result
        case Failure(exception: Exception) =>
          val temp: DataObject = new DataObject("LOADER")
          temp
      }
  }

  // initCache
  private def initCache(maximumSize: Int): LoadingCache[Int, DataObject] =
    Scaffeine()
      .recordStats()
      .expireAfterWrite(2.second)
      .maximumSize(maximumSize)
      .build(loader)

  // operations on the cache.
  val cache: LoadingCache[Int, DataObject] = initCache(maximumSize = 500)
  cache.put(1, new DataObject("foo"))
  cache.put(2, new DataObject("hoo"))

  println("sleeping for 3 sec\n")
  Thread.sleep(3000)
  println(cache.getIfPresent(1).toString)
  println(cache.getIfPresent(2).toString)
  println(cache.get(3).toString)

  println("sleeping for 10 sec\n")
  Thread.sleep(10000)
  println("waking up from 10 sec sleep")

  println(cache.get(1).toString)
  println(cache.get(2).toString)
  println(cache.get(3).toString)

  println("\nCache Stats: "+ cache.stats())
}

我看到许多可用于覆盖 expiryAfter 策略(expiryAfterWrite/Update/Access)的 custom.policy,但无法找到异步刷新数据的 refreshAterWrite 策略。任何帮助都将是可观的。

PS 我是在 Scala 上工作并探索咖啡因的新手。

4

1 回答 1

2

不幸的是,还不支持变量刷新。提供该功能存在一个未解决的问题。

目前到期可以自定义每个条目,但自动刷新是固定的。LoadingCache.refresh(key)如果您想自己管理手动刷新,可能会由 触发。例如,您可以定期迭代条目(通过asMap()视图)并根据自定义条件手动刷新。

AsyncLoadingCache可能很有用,而不是阻塞缓存加载器中的未来缓存将返回正在运行的未来,在值实现之前不会使其过期,如果失败则将其删除。请注意,该synchronous()视图对于异步缓存访问更多操作非常有用。

通过测试,您可能会发现 Guava 的假股票代码对模拟时间很有用。

于 2021-07-16T20:04:37.017 回答