我有一个设置,其中同一应用程序的两个实例部署在负载均衡器后面,并且这两个应用程序都与同一个数据库通信。
我遇到的问题是,当数据通过其中一个应用程序插入数据库时,其他应用程序无法访问/不可见相同的数据。
这两个应用在数据库抽象框架、spring框架等方面的配置完全相同,而且这两个应用运行在不同物理服务器上的不同tomcat服务器上。
问题的原因可能是什么?
编辑
Hibernate 配置如下:
编辑2
这是ehcache.xml
<cache name="org.hibernate.cache.internal.StandardQueryCache"
maxElementsInMemory="10000"
eternal="false"
timeToLiveSeconds="86400"
overflowToDisk="false"
memoryStoreEvictionPolicy="LRU"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToLiveSeconds="86400"
overflowToDisk="false"
memoryStoreEvictionPolicy="LRU"/>
最佳答案
您很可能遇到缓存复制问题,这可能是由于缺少/不正确的缓存协调配置所致。
假设
您在 Hibernate 中同时启用了二级缓存和查询缓存,这当然很好,并且您获得了性能提升。问题是您使用了 2 个节点,每个节点都有自己的缓存,或者它们没有正确地使缓存无效。
例如,节点 A 对所有实体 Z(即产品类别列表:Z1、Z2、...)执行查询并缓存结果。随后,节点 B 添加了一个新的产品类别实体 Zn。节点 A 在其自己的缓存失效之前不会使用该新实体;在此之前它将使用不包含 Zn 的缓存结果集。
如果禁用查询缓存(即设置 <property name="hibernate.cache.use_query_cache">false</property>
)后问题消失,您可以验证此假设。
解决方案
选项A优化缓存失效。这在很大程度上取决于您的业务需求,但一些建议是:
- 减少某些查询的缓存 TTL,直到找到最佳点(您可以容忍缺失/额外值的时间跨度)。您可以为此使用 EhCache 区域。
- 完全禁用某些实体的缓存
例子:
为 ehcache.xml
中的短期(即 5 分钟)查询结果创建一个区域:
<cache name = "short-lived"
maxElementsInMemory = "500"
eternal = "false"
timeToIdleSeconds = "600"
timeToLiveSeconds = "600"
overflowToDisk = "false"
/>
对于需要经常刷新的特定查询:
Query query = session.createQuery("FROM Z");
query.setCacheable(true);
query.setCacheRegion("short-lived");
有关该主题的更多信息 here .
选项B这是真正的解决方案。您可以为所有节点提供一个共享 缓存。虽然设置和配置肯定更难,但它可以为您提供最佳性能。例如,缓存查询将在每个集群中运行一次,而不是像现在这样在每个节点上运行一次。
看看Terracotta .
关于java - Apache 负载均衡器数据在多个应用程序之间同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60877034/