也许这有点学术性,但如果我实现缓存来加速应用程序,我应该如何最好地处理缓存未命中?(在我的例子中,语言将是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永远不会是有效的结果......
第一个是过度的,我认为并不是很好用于例外.你是否期望会有缓存命中?高速缓存未命中是我认为的相当正常的事件,因此异常变为简单的流控制.不好imho.
第二是竞争条件.在检查高速缓存条目的存在与查询之间存在时间延迟.这可能会导致各种各样的麻烦.
在一般意义上,返回null可能是合适的,但是它带有一些资格.
首先,它是什么类型的缓存?理想情况下,你要与一个直读缓存交谈,在这种情况下,如果它不在缓存中,它只是从源头获取它,这不是你在那里写的代码风格.
其次,get get插入是另一种竞争条件.查看界面以ConcurrentHashMap获得处理此类事物的一般方法.最值得注意的是,putIfAbsent()调用是一个原子操作,相当于你的第三次调用.