有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Ehcache与数据库不同步

在使用CMT的JavaEE服务器上,我使用ehcache在业务对象层(EJB)和数据访问层(使用JDBC的POJO)之间实现一个缓存层。在使用自填充Ehcache时,我似乎遇到了访问同一记录的两个线程之间的争用情况。缓存是在记录的主键上键入的

情况是:

  1. 第一个线程更新数据库中的记录并从缓存中删除该记录(但数据库提交不一定立即发生-可能会有其他查询跟进)
  2. 第二个线程读取记录,导致缓存被重新填充
  3. 第一个线程提交事务

这一切都发生在一瞬间。它会导致缓存与数据库不同步,随后对记录的读取会返回过时的缓存数据,直到执行另一次更新,或者缓存中的条目过期为止。我可以在短时间内(事务的典型长度)处理陈旧数据,但不能在几分钟内处理,这是我希望缓存对象的时间

有什么建议可以避免这种情况吗

更新:

在事务提交后清除缓存当然是理想的。问题是,在使用CMT的J2EE环境中,当缓存层夹在业务层(无状态会话EJB)和数据访问层之间时,如何做到这一点

为了明确这一限制,所讨论的方法调用可能与之前或之后发生的其他方法调用在同一事务中,也可能不在同一事务中。我不能强制提交(或在单独的事务中执行此操作),因为这会改变客户机代码所期望的事务边界。任何后续异常都不会回滚整个事务(在这种情况下,不必要地清除缓存是可以接受的副作用)。我无法控制事务的入口点,因为它本质上是一个客户端可以使用的API。将清除缓存的责任推给客户端应用程序是不合理的

我希望能够延迟任何缓存清除操作,直到整个事务由EJB容器提交,但我没有找到方法连接到该逻辑并使用无状态会话bean运行我自己的代码

更新#2:

到目前为止,最有希望的解决方案是使用ehcache 2.0的JTA支持:http://ehcache.org/documentation/apis/jta,而不是进行重大的设计更改

这意味着升级到ehcache 2。x和为数据库启用XA事务,这可能会产生负面的副作用。但这似乎是“正确”的方式


共 (1) 个答案

  1. # 1 楼答案

    您正在使用事务-在commit之后删除缓存更有意义,也就是在真正发生更改时

    这样,您只能在事务期间看到旧数据,之后的所有读取都具有最新视图

    更新:因为这是特定于CMT的,所以应该查看SessionSynchronization接口,以及它的afterCompletion()方法。这显示在this tutorial.