我们的设计有一个jvm,它是一个jboss / webapp(读/写),用于通过hibernate(使用jpa)维护数据到db。该模型有10-15个持久化类,关系中有3-5个深度级别。
然后我们有一个单独的jvm,它是使用这些数据的服务器。当它连续运行时,我们只有一个长db会话(只读)。
目前没有涉及jvm内部缓存 - 所以我们手动发信号通知另一个jvm。
现在,当webapp更改某些数据时,它会通知服务器重新加载已更改的数据。我们发现我们需要告诉hibernate清除数据然后重新加载它。只是对数据库进行提取/合并不起作用 - 主要是关于层次结构中几层的对象。
对于这个设计是否存在任何根本性错误的任何想法,或者是否有人这样做,并且在重新加载时使用hibernate有更好的运气。
谢谢, 克里斯
答案 0 :(得分:11)
Hibernate会话将从DB读取的所有数据加载到他们称之为第一级缓存的数据中。从DB加载行后,具有相同PK的行的任何后续提取都将从此缓存返回数据。此外,Hibernate gaurentees在单个Session中引用具有相同PK的对象的相等性。
据我所知,您的只读服务器应用程序永远不会关闭其Hibernate会话。因此,当读写应用程序更新数据库时,只读服务器上的会话不知道更改。实际上,您的只读应用程序正在加载数据库的内存副本并使用该副本,该副本将在适当的时候失效。
我建议的最简单和最好的做法是根据需要关闭并打开Sessions。这避免了整个问题。 Hibernate Sessions旨在成为与DB短暂交互的窗口。我同意不再一次又一次地重新加载对象图表会带来性能提升;但你需要衡量它并说服自己,这是值得的。
另一个选择是定期关闭并重新打开会话。这可确保只读应用程序使用不早于给定时间间隔的数据。但肯定有一个窗口,其中只读应用程序使用陈旧数据(虽然设计保证它最终获得最新数据)。在许多应用程序中这可能是允许的 - 您需要评估您的情况。
第三个选项是使用二级缓存实现,并使用短期会话。有各种缓存包与Hibernate一起使用,具有相对优点和缺点。
答案 1 :(得分:3)
如果是这样,您是否考虑过使用不同的二级缓存实现?我想知道您是否可以使用Web应用程序和独立应用程序共享的群集缓存。我相信与Hibernate集成的SwarmCache将允许这样做,但我自己没有尝试过。
但是,一般情况下,您应该知道给定缓存的内容永远不会知道另一个应用程序的活动(这就是为什么我建议让两个应用程序共享缓存)。祝你好运!
答案 2 :(得分:2)
从我的角度来看,您应该将下划线Hibernate缓存更改为支持群集模式的缓存。它可以是JBoss Cache或Swarm Cache。第一个更好地支持数据同步(复制和失效),并且还支持JTA。
然后,您将能够在webapp和服务器之间配置缓存同步。如果您将使用JBoss Cache,还要查看隔离级别。如果您想从同一会话中获取服务器上的新数据,我相信您应该使用 READ_COMMITTED 模式。
答案 3 :(得分:1)
最常用的做法是拥有Container-Managed Entity Manager,以便同一容器中的两个或多个应用程序(即Glassfish,Tomcat,Websphere)可以共享相同的缓存。 但是如果你不使用Application容器,因为你使用Play!例如,然后我将在主应用程序中构建一些web服务,以便在缓存中一致地读/写。
我认为使用陈旧数据是灾难的一扇门。就像Singletons成为Multitons一样,只读应用程序通常是有时写。
腰带和牙套:)