如何处理缓存未命中:NotFoundException,contains()或`if(null == result)`?

Han*_*etz 4 java coding-style

也许这有点学术性,但如果我实现缓存来加速应用程序,我应该如何最好地处理缓存未命中?(在我的例子中,语言将是Java,但也许答案可能更普遍.)

抛出异常:

ResultType res;
try {
    res = Cache.resLookup(someKey);
} catch (NotFoundException e) {
    res = Cache.resInsert(someKey, SlowDataSource.resLookup(someKey));
}
Run Code Online (Sandbox Code Playgroud)

提取之前询问:

ResultType res;
if (Cache.contains(someKey) {
    res = Cache.resLookup(someKey);
} else {
    res = Cache.resInsert(someKey, SlowDataSource.resLookup(someKey));
}
Run Code Online (Sandbox Code Playgroud)

返回null:

ResultType res;
res = Cache.resLookup(someKey);
if (null == res) {
    res = Cache.resInsert(someKey, SlowDataSource.resLookup(someKey));
}
Run Code Online (Sandbox Code Playgroud)

抛出异常似乎是错误的,毕竟这不是错误.让Cache查找contains()然后再次检索数据似乎很浪费,特别是每次都会发生这种情况.null当然,检查要求null永远不会是有效的结果......

cle*_*tus 6

第一个是过度的,我认为并不是很好用于例外.你是否期望会有缓存命中?高速缓存未命中是我认为的相当正常的事件,因此异常变为简单的流控制.不好imho.

第二是竞争条件.在检查高速缓存条目的存在与查询之间存在时间延迟.这可能会导致各种各样的麻烦.

在一般意义上,返回null可能是合适的,但是它带有一些资格.

首先,它是什么类型的缓存?理想情况下,你要与一个直读缓存交谈,在这种情况下,如果它不在缓存中,它只是从源头获取它,这不是你在那里写的代码风格.

其次,get get插入是另一种竞争条件.查看界面以ConcurrentHashMap获得处理此类事物的一般方法.最值得注意的是,putIfAbsent()调用是一个原子操作,相当于你的第三次调用.