Java 是春天';当涉及逐出时,是否可以安全使用缓存注释?
我使用的是Spring4.0.3,并利用了由Ehcache2.8.1支持的缓存抽象特性 我担心方法级注释Java 是春天';当涉及逐出时,是否可以安全使用缓存注释?,java,spring,caching,spring-cache,Java,Spring,Caching,Spring Cache,我使用的是Spring4.0.3,并利用了由Ehcache2.8.1支持的缓存抽象特性 我担心方法级注释@Cacheable和@cacheexecute在编辑缓存时可能无法正确锁定缓存,从而导致线程安全问题。我下面的测试似乎证实了这一点。我的问题是,我是否误用了这个框架或者误解了我的测试结果?或者我的结论正确吗?注释不会导致缓存被正确锁定,因此使用@cacheexecute不能保证将来的读取是有效的 测试: 创建数据库表以存储计数器值 create table counter ( cou
@Cacheable
和@cacheexecute
在编辑缓存时可能无法正确锁定缓存,从而导致线程安全问题。我下面的测试似乎证实了这一点。我的问题是,我是否误用了这个框架或者误解了我的测试结果?或者我的结论正确吗?注释不会导致缓存被正确锁定,因此使用@cacheexecute
不能保证将来的读取是有效的
测试:
创建数据库表以存储计数器值
create table counter
(
counter integer
);
insert into counter values(0);
<cache name="counter"
eternal="true"
maxElementsInMemory="1"/>
在ehcache.xml中创建一个条目以缓存计数器值
create table counter
(
counter integer
);
insert into counter values(0);
<cache name="counter"
eternal="true"
maxElementsInMemory="1"/>
在两种不同的场景下遵循这三个步骤——首先从控制器方法中删除缓存注释,然后将它们添加回
/incrementcounter
/viewcounter
,然后在启动此请求后,立即访问另一个选项卡中的/incrementcounter
/viewcounter
Expected result: 2
Actual result without caching: 2
Actual result with caching: 1
with缓存结果错误,是吗?缓存抽象中没有锁定。你是,我们已经在内部就支持它的成本进行了重要的头脑风暴。事实证明,它远不是简单的,在这种抽象中使用锁可能非常棘手,尤其是以“通用”的方式。此外,缓存供应商花费大量资源来支持此类用例,这是有原因的
目前我的最佳猜测是,如果您想要这些功能,您需要使缓存具有事务性。不过,在将其与抽象结合使用时会遇到一些问题,请特别检查目前正在进行的工作。不,这是我所期望的。选择时的
计数
为1(之后更新)。该值被返回,因此被缓存。@M.Deinum我认为您讨论的是步骤2的结果。是的,此时,/viewcounter应显示值1。但我说的是第三步的结果。在对/incrementcounter执行两次调用之前,该请求不会启动,因此正确的结果应该是值2。对于步骤3,该值仍然是1,因为这是缓存的值。@M.Deinum我理解为什么会看到1,但我将其称为并发错误。我认为reads应该始终返回启动读取时的实际值。如果第2步中的读写操作已被锁定以防止交错,则第3步将显示正确的结果。我的观点是,我假设缓存注释会为我实现这种锁定,而这种假设似乎是错误的。我仍然没有看到问题。如果调用一个方法,则查询结果为1。在这两者之间,执行数据库更新和缓存逐出。线程仍在等待。。。然后它返回,这就是缓存结果的点。对/viewcounter
的第二次调用返回缓存的结果。如何处理(或不处理)锁定取决于使用的缓存实现。Spring只委托给底层机制,它只是一个包装器,不添加功能。