Apache 负载均衡器数据在多个应用程序之间同步

Apache load balancer data syncing across multiple applications

我有一个设置,其中同一应用程序的两个实例部署在负载平衡器后面,并且这两个应用程序都与同一个数据库通信。

我遇到的问题是,当通过其中一个应用程序将数据插入数据库时​​,完全相同的数据不会 accessible/visible 到另一个应用程序。

这两个应用程序在数据库抽象框架、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"/>

导致此问题的可能性有多种。

1) 检查数据库访问权限。还要检查您的应用程序是否能够将数据提交到数据库中。 您需要调试不同的场景

  1. 从 cluster_1 插入数据并尝试从 cluster_2
  2. 读取相同的数据
  3. 以不同的顺序重复步骤 1
  4. 检查 SQL 数据库在插入数据(所有者信息、对象版本)时是否有任何差异。

2) 您可以在 (Clustering/Session Replication How-To)

中创建 tomcat 个服务器的集群

您的应用程序中是否有与数据库通信的 ORM? 我想是的,所以这是我的答案: 每个应用程序都通过 ORM(如 Hibernate)拥有自己的缓存机制。如果其中一个更改数据,更改将反映在其缓存中,但另一个对数据库中的更改一无所知。您可以执行以下选项之一:

  1. 在应用程序中禁用 ORM 缓存(最快的解决方案)
  2. 用另一个充当模型层+缓存服务器的应用程序包装数据库
  3. 创建消息系统以在实例之间广播更改事件并在触发时更新缓存。 (虽然不是个好主意)

您很可能遇到缓存复制问题,可能是由于 missing/incorrect 缓存协调配置。

假设

您在 Hibernate 中同时启用了二级缓存和查询缓存,这当然很好,并且您获得了性能提升。问题是您使用了 2 个节点,每个节点都有自己的缓存,或者它们没有正确地使缓存无效。

例如,节点A对所有实体Z执行查询(即产品类别列表:Z1、Z2、...)并缓存结果。随后,节点 B 添加了一个新的产品类别实体 Zn。节点 A 在其自己的缓存失效之前不会使用该新实体;到那时它将使用不包括 Zn 的缓存结果集。

如果禁用查询缓存(即设置 <property name="hibernate.cache.use_query_cache">false</property>)后问题消失,您可以验证此假设。

解决方案

选项A

优化缓存失效。这在很大程度上取决于您的业务需求,但一些建议是:

  • 减少某些查询的缓存 TTL,直到找到最佳点(您可以容忍 missing/extra 值的时间跨度)。您可以为此使用 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

这是真正的解决方案。您可以为所有节点提供 shared 缓存。虽然设置和配置肯定更难,但它可以为您提供最佳性能。例如,缓存查询将 运行 每个集群一次,而不是现在每个节点一次。

看看Terracotta