JPA 缓存是最新的,具有对数据库的并发访问

Posted

技术标签:

【中文标题】JPA 缓存是最新的,具有对数据库的并发访问【英文标题】:JPA cache up-to-dateness with concurrent access to the database 【发布时间】:2009-10-09 10:58:35 【问题描述】:

基于 JPA 实现其持久性的服务层可以从由 JPA 提供者(例如 Hibernate、Toplink/Toplink Essentials 等)透明管理的二级缓存中获得巨大收益。当这个缓存被激活时,一旦它们第一次从数据库中加载,它就会保存持久类的实例。可能有供应商特定的扩展来配置缓存行为。

JPA 标准还通过具有时间戳或版本字段来支持乐观锁定,用于避免发生并发更新时的数据损坏。由于这种机制依赖于数据库中包含的数据,因此它也可以在其他应用程序或服务想要更新数据时使用 - 只需在更新中包含记录的版本字段即可。

当涉及到缓存时,行为似乎是JPA 提供者(至少是Toplink Essentials)没有注意到数据库中的变化 不使用 EntityManager 执行。

这真的是默认行为吗?更新/无效 JPA 提供程序缓存的责任取决于应用程序吗?如果是的话,这似乎与大多数数据库被许多不同的应用程序使用的事实相悖。

【问题讨论】:

【参考方案1】:

这种行为也适用于 Hibernate (19.2. The Second Level Cache):

请注意,缓存不知道其他应用程序对持久存储所做的更改。但是,它们可以配置为定期使缓存数据过期。

这听起来很合理。如果另一个应用程序不使用缓存,您的缓存应该如何知道另一个应用程序所做的任何更改?留给缓存/JPA 提供者的唯一可能性是监视数据库(所有表、所有数据)的更改并相应地更新。这确实不可行。

我还了解到,由于上述原因,当多个应用程序更改数据库中的相同数据时,强烈建议不要使用二级缓存。

【讨论】:

当然,我了解监控整个数据库对性能的影响。我想知道如果将用于乐观锁定(版本字段)的机制用于“悲观缓存”,即比较缓存中对象的版本与数据库并从数据库重新加载它们,这是否是一个很好的权衡如有必要,在应用程序要求时立即...【参考方案2】:

我们已成功使用 PostgreSQL LISTEN/NOTIFY 来使我们的二级(客户端)缓存保持最新。从 PostgreSQL 9.0 开始,NOTIFY 还支持指定有效负载。我们用 C++ 和 ODBC 实现了它,但 JPA/JDBC 也提供了这样的特性。

该过程更复杂,但比刷新完整缓存或根本不使用缓存提供更好的性能,尤其是在某些关系相对很少更新的情况下。

程序的本质是:

    在特定事件上缓存实现LISTENs(例如"MYTABLE"MYTABLE 上的后插入/更新/删除触发器将更改(例如事件时间戳、操作码和主键)记录到表中 MYTABLE_NY 并发送通知:NOTIFY MYTABLE 缓存实现接收通知并检查MYTABLE_NY 中的最新更改(例如EVENT_TIMESTAMP > last_cache_refresh)。 对于每个事件,它都会从缓存中删除给定的实例。如果是休眠,则使用 session.evict()cache.evictEntity()

结果是一个缓存实现,其中包含在数据库服务器上关闭任何事务的一秒内的最新数据。我们主要将它用于 AutoComplete 没有问题,即它甚至对于缓存数据的高度交互使用也是可行的。

如果有兴趣,我可以提供一些代码示例。

【讨论】:

以上是关于JPA 缓存是最新的,具有对数据库的并发访问的主要内容,如果未能解决你的问题,请参考以下文章

使用缓存需要考虑的问题

Memcache 缓存系统

Spring boot , Spring data JPA 并发访问

云计算openstack共享组件——Memcache 缓存系统

jpa锁

jpa缓存导致无法查询到更新后的数据&android出现ANR的一个解决办法