繁体   English   中英

涉及逐出时,Spring的缓存注释是否可以安全使用?

[英]Are Spring's cache annotations safe to use when evictions are involved?

我正在使用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;
}

在两种不同的情况下执行以下三个步骤-首先从控制器方法中删除缓存注释,然后再将其添加回

  1. 造访/incrementcounter
  2. 在一个浏览器选项卡中,访问/viewcounter ,然后在发起此请求后立即在另一个选项卡中访问/incrementcounter
  3. 造访/viewcounter

检测结果

Expected result: 2
Actual result without caching: 2
Actual result with caching: 1

缓存结果是错误的,是吗?

缓存抽象中没有锁定。 不是第一个要求它的人 ,我们已经在内部进行了广泛的头脑风暴,以讨论支持它的成本。 事实证明,它远非简单,以这种抽象方式使用锁可能非常棘手,尤其是以“通用”方式。 同样,缓存供应商花费大量资源来支持此类用例,这是有原因的。

目前,我最好的猜测是,如果您想要这些功能,则需要缓存进行事务处理。 但是,将其与抽象配合使用时有些陷阱,请特别检查目前正在研究的SPR-11540

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM