4

我正在使用 JBoss EAP 4.3。

当使用内置的 JBoss TreeCache 作为 Hibernate 的二级缓存时,我目前正在研究并发策略的不同选项。我已经设置了它,并且通过查看日志验证了缓存是否正常工作,但我不确定真正使用了什么并发策略以及它是如何工作的。

@Cache对于每个实体,我可以在注释中设置以下“使用”值之一: NONE, READ_ONLY, NONSTRICT_READ_WRITE, READ_WRITE, TRANSACTIONAL

另一方面,在我的JBossTreeCache配置文件中,我可以将IsolationLevel整个缓存设置为以下之一:NONE, READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE(或仅使用OPTIMISTIC)。

一次查看一个配置选项时,文档非常清楚,但我想知道当您组合不同的选项时会发生什么。

例如,如果您@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)为实体设置但配置NONEIsolationLevelJBossTreecache会发生什么?

我也相信JBossTreeCache只支持NONE,READ_ONLYTRANSACTIONAL使用,但IsolationLevel你可以将它们与什么结合起来?如果你使用例如会发生什么NONSTRICT_READ_WRITE

这里总共应该有 5x6 不同的组合,但并非所有组合都有意义..

谁能帮我解决这个问题?

4

1 回答 1

8

隔离级别是一个棘手的问题。

例如,如果您@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)为实体设置但配置NONEIsolationLevelJBossTreecache会发生什么?

大多数情况下,生产中难以发现的错误......你应该明白,通过使用读写缓存,你基本上陷入了分布式事务的所有“优点”。

好的,关于组合:当你的对象不改变时,应该使用 Hibernate 中的只读缓存设置。例如,对于国家/地区字典。缓存并发级别 NONE 或 READ_ONLY 应该与它一起使用。

当缓存对象发生变化时,应该使用非严格读写,但这种情况很少发生,竞争条件的可能性很小。例如,对于时区字典 - 时区可能会偶尔出现/消失,但这种情况可能一年会发生几次。同样,缓存并发级别 NONE 或 READ_ONLY 应该与它一起使用。

现在,来更有趣的组合。

TransactionalHibernate 中的缓存是不安全的,Hibernate 假定缓存更新是事务性的,但没有做任何事情来确保它。所以你必须使用一个成熟的外部 XA(分布式事务)协调器,除非你真的知道你在做什么,否则你真的真的真的不想要它。最有可能的是,您必须使用完整的 EJB3 容器来支持 XA 管理器,尽管可以使用像http://www.atomikos.com/这样的外部事务管理器和普通的 servlet + Spring。显然,您需要使用TRANSACTIONAL缓存。

'READ_WRITE' 是一个有趣的组合。在这种模式下,Hibernate 本身作为一个轻量级的 XA 协调器工作,因此它不需要成熟的外部 XA。对其工作原理的简短描述:

  1. 在这种模式下,Hibernate 自己管理事务。所有数据库操作都必须在事务内,自动提交模式不起作用。
  2. flush()(在事务生命周期中可能出现多次,但通常发生在提交之前)期间,Hibernate 会经历一个会话并搜索更新/插入/删除的对象。然后这些对象首先保存到数据库中,然后在缓存中锁定和更新,因此并发事务既不能更新也不能读取它们。
  3. 如果事务随后被回滚(显式地或由于某些错误),锁定的对象会被简单地释放并从缓存中逐出,因此其他事务可以读取/更新它们。
  4. 如果事务成功提交,则锁定对象被简单地释放,其他线程可以读取/写入它们。

这里有几个要点:

可能的可重复读取冲突。想象一下,我们有事务 A (tA) 和事务 B (tB) 同时启动并且都加载对象 X,tA 然后修改该对象,然后提交 tA。在许多使用快照隔离的数据库(Oracle、PostgreSQL、FireBird)中,如果 tB 再次请求对象 X,它应该收到与事务开始时相同的对象状态。但是,READ_WRITE 缓存可能会违反此条件 - 那里没有快照隔离。Hibernate 尝试通过在缓存对象上使用时间戳来解决它,但在计时器分辨率较差的操作系统(Windows 上为 15.6 毫秒)上,它保证会让一些比赛溜走。

可能的乐观过时对象版本- 如果您非常不幸地在 Windows 上工作,并且有多个事务以相同的时间戳提交,则可能会获得过时的对象版本。

于 2011-02-21T22:21:06.377 回答