我在网络应用程序中使用 cache2k 与通读来加载博客帖子 on demand 。但是,我担心读取功能的阻止。例如,如果多个线程(请求)要求缓存提供相同的密钥,是否可以多次调用 read through 方法来加载< / em>缓存中的相同键/值?
我从读取功能的文档中获取展示 阻止对同一密钥的并发请求,直到加载已经完成,但我可能误读了文档。我只是想检查一下这是行为。
初始化缓存的方法如下所示:
private void initializeURItoPostCache()
{
final CacheLoader<String, PostImpl> postFileLoader = new CacheLoader<String, PostImpl>(){
@Override public PostImpl load(String uri)
{
// Fetch the data and create the post object
final PostImpl post = new PostImpl();
//.. code omitted
return post;
}
};
// Initialize the cache with a read-through loader
this.cacheUriToPost = new Cache2kBuilder<String, PostImpl>(){}
.name("cacheBlogPosts")
.eternal(true)
.loader(postFileLoader)
.build();
}
以下方法用于从缓存中请求帖子:
public Post getPostByURI(final String uri)
{
// Check with the index service to ensure the URI is known (valid to the application)
if(this.indexService.isValidPostURI(uri))
{
// We have a post associated with the given URI, so
// request it from the cache
return this.cacheUriToPost.get(uri);
}
return EMPTY_POST;
}
非常感谢,祝大家新年快乐和繁荣。
答案 0 :(得分:2)
当对同一个键的多个请求将引发缓存加载器调用时,cache2k将仅调用一次加载器。其他线程一直等到负载完成。此行为称为阻止读取。引用Java Doc:
阻止:如果
Cache.get(K)
或其他允许透明访问的方法调用加载器,则同一个密钥上的并发请求将被阻塞,直到加载完成。对于过期值,可以通过启用Cache2kBuilder.refreshAhead(boolean)
来避免阻塞。无法保证一次仅为一个密钥调用加载程序。例如,在调用Cache.clear()
之后,一个键的加载操作可能会重叠。
此行为对缓存非常重要,因为它可以防御Cache stampede。例如:高流量网站每秒收到1000个请求。一个资源需要很长时间才能生成,大约100毫秒。当高速缓存未在高速缓存未命中时阻止多个请求时,将至少有100个请求命中加载器以获得相同的密钥。 “至少”是轻描淡写,因为你的机器可能无法以相同的速度处理100个请求。
请记住,缓存没有硬性保证。当同时调用相同的密钥时,加载程序仍必须能够正确执行。例如,阻止通读和Cache.clear()
会导致竞争要求。 Cache.clear()
应该很快,这意味着我们不想等待正在进行的加载操作完成。