我正在使用Spring 4.0.3,并利用了由EhCache 2.8.1支持的Cache Abstraction功能。
我担心方法级别的注释,@Cacheable
并且@CacheEvict
在编辑高速缓存时可能无法正确锁定高速缓存,从而导致线程安全问题。我在下面的测试似乎证实了这一点。我的问题是,我是在滥用框架还是在误解测试结果?还是我得出的结论是,注解不会导致缓存被正确锁定,因此使用@CacheEvict
不能保证将来的读取有效吗?
测试:
创建数据库表以存储计数器值
create table counter
(
counter integer
);
insert into counter values(0);
在ehcache.xml中创建一个条目以缓存计数器值
<cache name="counter"
eternal="true"
maxElementsInMemory="1"/>
在Spring控制器中创建两种请求映射方法-一种读取计数器的值并在长时间延迟后返回,另一种递增该值然后快速返回
@RequestMapping("/viewcounter")
@ResponseBody
@Cacheable(value = "counter", key = "1")
public int readCounter() {
int count = dao.selectInteger("select counter from counter");
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
return count;
}
@RequestMapping("/incrementcounter")
@ResponseBody
@CacheEvict(value = "counter", key = "1")
public int incrementCounter() {
dao.update("update counter set counter = counter + 1");
int count = dao.selectInteger("select counter from counter");
return count;
}
在两种不同的情况下执行以下三个步骤-首先从控制器方法中删除缓存注释,然后再将其添加回
/incrementcounter
/viewcounter
,然后在发起此请求后立即/incrementcounter
在另一个标签中访问/viewcounter
检测结果
Expected result: 2
Actual result without caching: 2
Actual result with caching: 1
缓存结果是错误的,是吗?
缓存抽象中没有锁定。您不是第一个要求它的人,我们已经在内部进行了广泛的头脑风暴,以讨论支持它的成本。事实证明,它远非简单,以这种抽象方式使用锁可能非常棘手,尤其是以“通用”方式。同样,缓存供应商花费大量资源来支持此类用例,这是有原因的。
目前,我最好的猜测是,如果您想要这些功能,则需要缓存进行事务处理。但是,将其与抽象一起使用时有些陷阱,请特别检查目前正在研究的SPR-11540。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句