如何保持运行两个 Java 应用程序的 Hibernate 缓存一致性?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/48733/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 10:50:36  来源:igfitidea点击:

How to maintain Hibernate cache consistency running two Java applications?

javahibernatecaching

提问by Chris Kimpton

Our design has one jvm that is a jboss/webapp (read/write) that is used to maintain the data via hibernate (using jpa) to the db. The model has 10-15 persistent classes with 3-5 levels of depth in the relationships.

我们的设计有一个 jvm,它是一个 jboss/webapp(读/写),用于通过休眠(使用 jpa)将数据维护到数据库。该模型有 10-15 个持久类,关系有 3-5 个深度级别。

We then have a separate jvm that is the server using this data. As it is running continuously we just have one long db session (read only).

然后我们有一个单独的 jvm,它是使用这些数据的服务器。由于它持续运行,我们只有一个很长的数据库会话(只读)。

There is currently no intra-jvm cache involved - so we manually signal one jvm from the other.

目前不涉及内部 jvm 缓存 - 因此我们手动从另一个 jvm 发出信号。

Now when the webapp changes some data, it signals the server to reload the changed data. What we have found is that we need to tell hibernate to purge the data and then reload it. Just doing a fetch/merge with the db does not do the job - mainly in respect of the objects several layers down the hierarchy.

现在,当 webapp 更改某些数据时,它会向服务器发出信号以重新加载更改的数据。我们发现我们需要告诉 hibernate 清除数据然后重新加载它。只是对数据库进行提取/合并并不能完成这项工作 - 主要是针对层次结构中几层的对象。

Any thoughts on whether there is anything fundamentally wrong with this design or if anyone is doing this and has had better luck with working with hibernate on the reloads.

关于此设计是否存在根本性错误的任何想法,或者是否有人这样做并且在重新加载时使用 hibernate 有更好的运气。

Thanks, Chris

谢谢,克里斯

回答by Binil Thomas

A Hibernate session loads all data it reads from the DB into what they call the first-level cache. Once a row is loaded from the DB, any subsequent fetches for a row with the same PK will return the data from this cache. Furthermore, Hibernate gaurentees reference equality for objects with the same PK in a single Session.

一个 Hibernate 会话将从 DB 读取的所有数据加载到它们所谓的第一级缓存中。从 DB 加载一行后,对具有相同 PK 的行的任何后续提取都将从该缓存返回数据。此外,Hibernate gaurentees 在单个会话中引用具有相同 PK 的对象的相等性。

From what I understand, your read-only server application never closes its Hibernate session. So when the DB gets updated by the read-write application, the Session on read-only server is unaware of the change. Effectively, your read-only application is loading an in-memory copy of the database and using that copy, which gets stale in due course.

据我了解,您的只读服务器应用程序永远不会关闭其 Hibernate 会话。因此,当读写应用程序更新数据库时,只读服务器上的 Session 不知道更改。实际上,您的只读应用程序正在加载数据库的内存副本并使用该副本,该副本在适当的时候会过时。

The simplest and best course of action I can suggest is to close and open Sessions as needed. This sidesteps the whole problem. Hibernate Sessions are intended to be a window for a short-lived interaction with the DB. I agree that there is a performance gain by not reloading the object-graph again and again; but you need to measure it and convince yourself that it is worth the pains.

我可以建议的最简单和最好的行动方案是根据需要关闭和打开会话。这回避了整个问题。Hibernate Sessions 旨在成为与 DB 进行短期交互的窗口。我同意不一次又一次地重新加载对象图会提高性能;但你需要衡量它并说服自己,这是值得的。

Another option is to close and reopen the Session periodically. This ensures that the read-only application works with data not older than a given time interval. But there definitely is a window where the read-only application works with stale data (although the design guarantees that it gets the up-to-date data eventually). This might be permissible in many applications - you need to evaluate your situation.

另一种选择是定期关闭并重新打开会话。这可确保只读应用程序处理不早于给定时间间隔的数据。但是肯定有一个窗口,只读应用程序可以在其中处理陈旧数据(尽管设计保证它最终会获得最新数据)。这在许多应用程序中可能是允许的 - 您需要评估您的情况。

The third option is to use a second level cacheimplementation, and use short-lived Sessions. There are various caching packages that work with Hibernate with relative merits and demerits.

第三种选择是使用二级缓存实现,并使用短期会话。有各种缓存包可以与 Hibernate 一起使用,但各有优缺点。

回答by erickson

Chris, I'm a little confused about your circumstances. If I understand correctly, you have a both a web app (read/write) a standalone application (read-only?) using Hibernate to access a shared database. The changes you make with the web app aren't visible to the standalone app. Is that right?

克里斯,我对你的情况有点困惑。如果我理解正确,您有一个使用 Hibernate 访问共享数据库的 Web 应用程序(读/写)和一个独立应用程序(只读?)。您对 Web 应用程序所做的更改对独立应用程序不可见。是对的吗?

If so, have you considered using a different second-level cache implementation? I'm wondering if you might be able to use a clustered cache that is shared by both the web application and the standalone application. I believe that SwarmCache, which is integrated with Hibernate, will allow this, but I haven't tried it myself.

如果是这样,您是否考虑过使用不同的二级缓存实现?我想知道您是否可以使用由 Web 应用程序和独立应用程序共享的集群缓存。我相信与 Hibernate 集成的 SwarmCache 会允许这样做,但我自己还没有尝试过。

In general, though, you should know that the contents of a given cache will never be aware of activity by another application (that's why I suggest having both apps share a cache). Good luck!

但是,一般而言,您应该知道给定缓存的内容永远不会知道另一个应用程序的活动(这就是我建议让两个应用程序共享缓存的原因)。祝你好运!

回答by Andrey Vityuk

From my point of view, you should change your underline Hibernate cache to that one, which supports clustered mode. It could be a JBoss Cacheor a Swarm Cache. The first one has a better support of data synchronization (replication and invalidation) and also supports JTA.

在我看来,您应该将下划线的 Hibernate 缓存更改为支持集群模式的缓存。它可以是JBoss CacheSwarm Cache。第一个更好的支持数据同步(复制和失效),也支持JTA。

Then you will able to configure cache synchronization between webapp and server. Also look at isolation level if you will use JBoss Cache. I believe you should use READ_COMMITTEDmode if you want to get new data on a server from the same session.

然后您将能够配置 webapp 和服务器之间的缓存同步。如果您将使用 JBoss 缓存,还要查看隔离级别。如果您想从同一会话中获取服务器上的新数据,我相信您应该使用READ_COMMITTED模式。

回答by Nicolas Zozol

The most used practice is to have a Container-Managed Entity Managerso that two or more applications in the same container (ie Glassfish, Tomcat, Websphere) can share the same caches. But if you don't use an Application container, because you use Play! for instance, then I would build some webservices in the primary Applicationto read/write consistently in the cache.

最常用的做法是拥有一个容器管理的实体管理器,以便同一容器中的两个或多个应用程序(即 Glassfish、Tomcat、Websphere)可以共享相同的缓存。但是如果你不使用 Application 容器,因为你使用的是 Play!例如,然后我将在主应用程序中构建一些 Web 服务以在缓存中一致地读/写。

I think using stale data is an open door for disaster. Just like Singletons become Multitons, read-only applications are often a write sometimes.

我认为使用陈旧数据是灾难的大门。就像 Singletons 变成 Multitons 一样,只读应用程序有时通常是写入

Belt and braces:)

腰带和背带:)