JBoss TreeCache的并发策略配置作为第二级Hibernate缓存 [英] Concurrency strategy configuration for JBoss TreeCache as 2nd level Hibernate cache

查看:162
本文介绍了JBoss TreeCache的并发策略配置作为第二级Hibernate缓存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用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),但配置 NONE 作为 IsolationLevel 用于 JBossTreecache ,会发生什么?

我也相信 JBossTreeCache 只支持 NONE READ_ONLY TRANSACTIONAL 使用情况,但允许 IsolationLevel 将它们与?如果你使用例如 NONSTRICT_READ_WRITE



会发生什么情况,总共应该有5x6种不同的组合,但不能所有这些都是有道理的。



任何人都可以帮我整理出来吗? div>

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


例如,如果您设置了 @Cache = CacheConcurrencyStrategy.TRANSACTIONAL),但将 NONE 配置为 IsolationLevel c $ c> JBossTreecache ,会发生什么?

大多数情况下,在生产中很难找到缺陷......您应该明白,通过使用读写缓存,在分布式事务中处理它们的所有细节。

好吧,关于组合:
当对象不变时,应该使用Hibernate中的只读缓存设置。例如,对于国家字典。缓存并发级别应为NONE或READ_ONLY。



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



现在,更多有趣的组合。 Hibernate中的Transactional 缓存是不安全的,Hibernate假定缓存更新是事务性的,但没有做任何事情来确保它。所以你必须使用一个全面的外部XA(分布式事务)协调器,除非你真的知道自己在做什么,否则你确实真的不需要它。很可能,您必须使用完整的EJB3容器才能支持XA-manager,尽管可以使用外部事务管理器,如 http:// www。 atomikos.com/ 与普通的servlets + 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.6ms),它可以保证让某些种族滑过。



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


I am using JBoss EAP 4.3.

I'm currently looking into the different options for concurrency strategy when using the built-in JBoss TreeCache as a second level cache for Hibernate. I have set it up and I have verified that the cache is working by looking into the logs, but I am not sure what concurrency strategy is really used and how it is intended to work.

For each Entity, I can set one of the following "usage" values in the @Cache annotation: NONE, READ_ONLY, NONSTRICT_READ_WRITE, READ_WRITE, TRANSACTIONAL.

On the other hand, in my JBossTreeCache configuration file I can set IsolationLevel to one of the following for the entire cache: NONE, READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE (or just use OPTIMISTIC).

When looking into the configuration options one at a time, the documentation is quite clear, but I wonder what happens when you combine the different options.

For example, if you set @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL) for an entity but configure NONE as IsolationLevel for the JBossTreecache, what happens?

I also believe that JBossTreeCache only supports NONE, READ_ONLY and TRANSACTIONAL usage, but what IsolationLevel are you allowed to combine them with? And what happens if you use for example NONSTRICT_READ_WRITE?

Alltogether there should be like 5x6 different combinations here, but not all of them makes sense..

Can anyoone help me sorting this out?

解决方案

Isolation level is a tricky issue.

For example, if you set @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL) for an entity but configure NONE as IsolationLevel for the JBossTreecache, what happens?

Mostly, hard-to-find bugs in production... You should understand that by using read-write cache you essentially mire yourself in distributed transactions with all their 'niceties'.

Ok, about combinations: Read-only cache setting in Hibernate should be used when your objects do not change. For example, for a country dictionary. Cache concurrency level NONE or READ_ONLY should be used with it.

Non-strict-read-write should be used when your cached objects change, but that happens rarely and chances for race conditions are small. For example, for a timezone dictionary - timezones might appear/disappear occasionally, but that happens may be a couple times a year. Again, cache concurrency level NONE or READ_ONLY should be used with it.

Now, to more interesting combinations.

Transactional caches in Hibernate are NOT safe, Hibernate assumes that cache updates are transactional but does nothing to ensure it. So you MUST use a full-blown external XA (distributed transactions) coordinator, and you really really really do not want it unless you really really know what you're doing. Most likely, you'll have to use the full EJB3 container for XA-manager support though it's possible to use external transaction manager like http://www.atomikos.com/ with plain servlets + Spring. Obviously, you need to use TRANSACTIONAL caches with it.

'READ_WRITE` is an interesting combination. In this mode Hibernate itself works as a lightweight XA-coordinator, so it doesn't require a full-blown external XA. Short description of how it works:

  1. In this mode Hibernate manages the transactions itself. All DB actions must be inside a transaction, autocommit mode won't work.
  2. During the flush() (which might appear multiple time during transaction lifetime, but usually happens just before the commit) Hibernate goes through a session and searches for updated/inserted/deleted objects. These objects then are first saved to the database, and then locked and updated in the cache so concurrent transactions can neither update nor read them.
  3. If the transaction is then rolled back (explicitly or because of some error) the locked objects are simply released and evicted from the cache, so other transactions can read/update them.
  4. If the transaction is committed successfully, then the locked objects are simply released and other threads can read/write them.

There are couple of fine points here:

Possible repeatable read violation. Imagine that we have Transaction A (tA) and Transaction B (tB) which start simultaneously and both load object X, tA then modifies this object and then tA is committed. In a lot of databases which use snapshot isolation (Oracle, PostgreSQL, FireBird), if tB requests object X again it should receive the same object state as in the beginning of the transaction. However, READ_WRITE cache might violate this condition - there's no snapshot isolation there. Hibernate tries to work around it by using timestamps on cached objects but on OSes with poor timer resolution (15.6ms on Windows) it is guaranteed to let some races slip through.

Possible optimistic stale object versions - it IS possible to get stale object versions if you're very unlucky to work on Windows, and have several transactions commit with the same timestamp.

这篇关于JBoss TreeCache的并发策略配置作为第二级Hibernate缓存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆