Scaffeine:如何为默认值设置不同的过期时间
Scaffeine: how to set different expiration time for default value
Scala 应用程序用例:
我们有一个基于 Scala 的模块从全局缓存 (Redis) 读取数据并将其保存到本地缓存 (Scaffeine)。由于我们希望异步刷新此数据,因此我们使用 LoadingCache 并将 refreshAfterWrite 持续时间设置为刷新 window of 2.second.
问题:
在本地缓存中设置值时,我们需要根据键是否存在于 redis(全局缓存)中来设置不同的到期时间。
例如
如果 key 不存在 在全局缓存中,我们想在本地缓存中保存相同的键 默认值 和 刷新 window 设置为 5.minutes。
如果 key 在全局缓存中存在 ,我们希望将其与实际值存储在本地缓存中,并且 刷新 window 设置为 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())
}
我看到很多 custom.policy 可用于覆盖 expiryAfter 策略 (expiryAfterWrite/Update/Access),但找不到异步刷新数据的 refreshAterWrite 策略。任何帮助都将不胜感激。
P.S.
我是 Scala 的新手,也想探索 Scaffeine。
不幸的是,尚不支持变量刷新。有一个 open issue 可以提供该功能。
目前可以自定义每个条目的过期时间,但自动刷新是固定的。如果您想自己管理,LoadingCache.refresh(key)
可能会触发手动刷新。例如,您可以定期迭代条目(通过 asMap()
视图)并根据自定义条件手动刷新。
AsyncLoadingCache 可能会很有用,而不是阻塞缓存加载程序中的未来。缓存将 return 飞行中的未来,在值实现之前不会使其过期,如果失败则将其删除。请注意,synchronous()
视图对于异步缓存访问更多操作非常有用。
通过测试,您可能会发现 Guava 的假代码对 simulate time 很有用。
Scala 应用程序用例:
我们有一个基于 Scala 的模块从全局缓存 (Redis) 读取数据并将其保存到本地缓存 (Scaffeine)。由于我们希望异步刷新此数据,因此我们使用 LoadingCache 并将 refreshAfterWrite 持续时间设置为刷新 window of 2.second.
问题:
在本地缓存中设置值时,我们需要根据键是否存在于 redis(全局缓存)中来设置不同的到期时间。
例如 如果 key 不存在 在全局缓存中,我们想在本地缓存中保存相同的键 默认值 和 刷新 window 设置为 5.minutes。 如果 key 在全局缓存中存在 ,我们希望将其与实际值存储在本地缓存中,并且 刷新 window 设置为 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())
}
我看到很多 custom.policy 可用于覆盖 expiryAfter 策略 (expiryAfterWrite/Update/Access),但找不到异步刷新数据的 refreshAterWrite 策略。任何帮助都将不胜感激。
P.S. 我是 Scala 的新手,也想探索 Scaffeine。
不幸的是,尚不支持变量刷新。有一个 open issue 可以提供该功能。
目前可以自定义每个条目的过期时间,但自动刷新是固定的。如果您想自己管理,LoadingCache.refresh(key)
可能会触发手动刷新。例如,您可以定期迭代条目(通过 asMap()
视图)并根据自定义条件手动刷新。
AsyncLoadingCache 可能会很有用,而不是阻塞缓存加载程序中的未来。缓存将 return 飞行中的未来,在值实现之前不会使其过期,如果失败则将其删除。请注意,synchronous()
视图对于异步缓存访问更多操作非常有用。
通过测试,您可能会发现 Guava 的假代码对 simulate time 很有用。