0

Caffeine AsyncLoadingCache 上的 .get() 是否通过延迟调用 .get() 的后续线程直到第一个线程完成来防止并发加载?或者它可以配置为在发生自填充负载请求时返回一个陈旧的值?

这样可以通过使用缓存来防止雷鸣般的羊群。

我看到的行为表明即使我正在使用缓存,也没有处理雷鸣般的牛群。

我像这样创建缓存:

val queryResponseCache: AsyncLoadingCache<Request, Response> = Caffeine.newBuilder()
            .maximumSize(1000)
            .expireAfterWrite(5, TimeUnit.SECONDS)
            .recordStats()
            .buildAsync(queryLoader)

并将其与 redis 中的 L2 缓存一起使用,如下所示(kotlin elvis 运算符):

queryResponseCache.getIfPresent(key) ?: fetchFromRedis(key) ?: queryResponseCache.get(key)

我知道 getIfPresent 是并发的,但是最终调用 fetchFromRedis() / get() 的后续调用似乎有问题。我想将其fetchFromRedis移入asyncLoad()函数可能对负载容限更好。

4

1 回答 1

1

通过缓存加载时支持缓存踩踏。在您使用getIfPresent和加载值的示例中,我假设您将其显式放入缓存中fetchFromRedis. 无论哪种方式,由于绕过缓存,除非在 Redis 中不存在,否则您将确保一个活泼的 get-load-put。

如果您将逻辑移入asyncLoad,正如您所推测的那样,它将让缓存处理踩踏事件。redis 查找、数据库查询和存储回 redis 都可以作为异步任务链执行,其中最终的未来返回到asyncLoad. 然后缓存将计算一次未来并将其返回给所有后续调用,直到条目被驱逐。

于 2020-03-18T21:13:11.497 回答