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 也提供了这样的特性。
该过程更复杂,但比刷新完整缓存或根本不使用缓存提供更好的性能,尤其是在某些关系相对很少更新的情况下。
程序的本质是:
-
在特定事件上缓存实现
LISTEN
s(例如"MYTABLE"
)
MYTABLE
上的后插入/更新/删除触发器将更改(例如事件时间戳、操作码和主键)记录到表中 MYTABLE_NY
并发送通知:NOTIFY MYTABLE
缓存实现接收通知并检查MYTABLE_NY
中的最新更改(例如EVENT_TIMESTAMP > last_cache_refresh
)。
对于每个事件,它都会从缓存中删除给定的实例。如果是休眠,则使用 session.evict()
或 cache.evictEntity()
结果是一个缓存实现,其中包含在数据库服务器上关闭任何事务的一秒内的最新数据。我们主要将它用于 AutoComplete 没有问题,即它甚至对于缓存数据的高度交互使用也是可行的。
如果有兴趣,我可以提供一些代码示例。
【讨论】:
以上是关于JPA 缓存是最新的,具有对数据库的并发访问的主要内容,如果未能解决你的问题,请参考以下文章
Spring boot , Spring data JPA 并发访问