负载平衡应用程序中的缓存失效

Cache invalidation in load balanced application

我正在开发的应用程序使用简单的 HashMap 作为来自数据库的某些对象的缓存。这远非理想,但这些缓存列表的数据量确实很小(少于 100 个)并且不会经常更改。此解决方案提供最小的开销。当其中一个缓存列表中的项目发生更改时,其值将在 HashMap 中被替换。

我们即将发布此应用程序的生产日期。为了提供一个可合理扩展的解决方案,我们提供了一个负载平衡解决方案。平衡器在几个 Wildfly 节点之间切换,每个节点都包含整个应用程序,数据库除外。

现在的问题是,当缓存项发生更改时,它只会在其中一个节点中更新。更改不会应用于其他节点中的缓存。可能的解决方案是:

我的问题是:是否有提供最后解决方案的产品(免费且具有开放许可证,可商用)?如果没有,我会实施第三种解决方案。有什么 risks/mistakes 我需要注意的吗?

Risks/mistakes:当然重要的一点是数据的一致性。从数据库缓存数据时,我通常会确保在更新时使用事务。通常我使用这样的模式:

begin transaction
invalidate cache entries in the transaction
update database
commit transaction

如果在更新期间发生缓存未命中,读取需要等到事务提交。

对于您的用例,典型的选择是集群或分布式缓存,例如:HazelCast、Infinispan、Apache Ignite。但是,不知何故,这在您的用例中确实很重。

另一种方法是实施自己的机制来向所有节点发布失效事件。这仍然不是一件容易的事,因为您可能希望确保每个节点都收到消息,但如果一个节点同时出现故障,也需要容错。所以你可能想为此使用一个合适的库,例如JGroups 或各种 MQ 产品。

我在没有使用 JGroups 或其他信号库的情况下实现了它。每个节点都有一个 REST 端点来清除缓存。当一个节点启动时,它会使用它的 IP、域和令牌在 DB table 中注册自己。当它关闭时,它会删除它的记录。

当一个对象在一个节点中更新时,该节点会清除其缓存并启动多个线程,这些线程使用 Unirest 向所有其他节点发送 REST 调用(带有其令牌和对象类型),这些节点依次检查令牌并驱逐他们的缓存。抛出错误时,调用的节点从列表中删除。

在安全性和容错性方面应该有所改进。节点的移除现在真的很悲观。只有在多次尝试失败后,才应删除该节点。现在,这个简单的解决方案就可以了!