JBoss TreeCache 作为二级 Hibernate 缓存的并发策略配置
我正在使用 JBoss EAP 4.3。
我目前正在研究使用内置 JBoss TreeCache 作为 Hibernate 二级缓存时的并发策略的不同选项。我已经设置了它,并且通过查看日志验证了缓存是否正在工作,但我不确定真正使用的并发策略是什么以及它是如何工作的。
对于每个实体,我可以在 @Cache 注释中设置以下“使用”值之一:NONE、READ_ONLY、NONSTRICT_READ_WRITE 、READ_WRITE
、事务
。
另一方面,在我的 JBossTreeCache
配置文件中,我可以将整个缓存的 IsolationLevel
设置为以下之一:NONE
、READ_UNCOMMITTED
、READ_COMMITTED
、REPEATABLE_READ
、SERIALIZABLE
(或仅使用OPTIMISTIC
)。
当一次查看一个配置选项时,文档非常清楚,但我想知道当您组合不同的选项时会发生什么。
例如,如果您为实体设置 @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
,但为 JBossTreecache 配置
,会发生什么?NONE
作为 IsolationLevel
我还相信 JBossTreeCache
仅支持 NONE
、READ_ONLY
和 TRANSACTIONAL
使用,但是 IsolationLevel
code> 你可以将它们结合起来吗?如果您使用例如 NONSTRICT_READ_WRITE
会发生什么?
这里总共应该有 5x6 种不同的组合,但并非所有组合都有意义..
有人可以帮我解决这个问题吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
隔离级别是一个棘手的问题。
大多数情况下,在生产中很难发现错误......您应该明白,通过使用读写缓存,您实际上使自己陷入了分布式事务及其所有“优点”中。
好的,关于组合:
当对象不改变时,应该使用 Hibernate 中的只读缓存设置。例如,对于国家/地区词典。缓存并发级别 NONE 或 READ_ONLY 应与其一起使用。
当缓存对象发生更改时,应使用非严格读写,但这种情况很少发生,并且出现竞争条件的可能性很小。例如,对于时区字典 - 时区可能偶尔会出现/消失,但这种情况可能每年发生几次。同样,缓存并发级别 NONE 或 READ_ONLY 应该与它一起使用。
现在,更多有趣的组合。
Hibernate 中的事务性缓存并不安全,Hibernate 假定缓存更新是事务性的,但没有采取任何措施来确保这一点。因此,您必须使用成熟的外部 XA(分布式事务)协调器,并且您真的真的真的不想要它,除非您真的知道自己在做什么。最有可能的是,您必须使用完整的 EJB3 容器来支持 XA 管理器,尽管可以使用外部事务管理器,例如 http://www。 atomikos.com/ 带有普通的 servlet + Spring。显然,您需要使用
TRANSACTIONAL
缓存。“READ_WRITE”是一个有趣的组合。在这种模式下,Hibernate 本身充当轻量级 XA 协调器,因此它不需要成熟的外部 XA。其工作原理的简短描述:
这里有几个要点:
可能的可重复读取违规。想象一下,我们有事务 A (tA) 和事务 B (tB),它们同时启动,并且都加载对象 X,tA 然后修改该对象,然后提交 tA。在许多使用快照隔离的数据库(Oracle、PostgreSQL、FireBird)中,如果 tB 再次请求对象 X,它应该收到与事务开始时相同的对象状态。但是,READ_WRITE 缓存可能会违反此条件 - 那里没有快照隔离。 Hibernate 试图通过在缓存对象上使用时间戳来解决这个问题,但在计时器分辨率较差的操作系统上(Windows 上为 15.6 毫秒),它肯定会让一些竞争溜走。
可能的乐观过时对象版本 - 如果您非常不幸在 Windows 上工作,并且有多个事务以相同的时间戳提交,则有可能获得过时的对象版本。
Isolation level is a tricky issue.
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 useTRANSACTIONAL
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:
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.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.