在两台服务器之间同步缓存数据的最佳方法

想要在两个服务器之间同步缓存数据。 两个数据库共享同一个数据库,但为了更好的执行数据,我在启动时将数据缓存到Hash Map中。 因此,希望在不重新启动服务器的情况下同步缓存的数据。 (两台服务器同时启动)。

请建议我最好和最有效的方法。

而不是尝试在两个服务器实例之间同步缓存数据,为什么不使用memcached / couchbase或redis之类的内容来集中缓存? 使用像ehcache这样的分布式缓存要复杂得多,容易出错IMO使用像上面提到的缓存服务器集中缓存数据。

作为我原来答案的补充,在决定使用哪种缓存方法时(在内存中,集中),要考虑的一件事是缓存的数据的波动性。

如果数据存储在数据库中,但在服务器加载后没有更改,那么您甚至不需要在服务器之间进行同步。 让他们每个人从源头将这些静态数据加载到内存中,然后以他们喜欢的方式进行他们的快乐方式。 数据不会改变,因此无需引入复杂的模式来保持服务器之间的数据同步。

如果数据中存在确实存在一定程度的波动(比如说你是缓存从数据库中查找实体数据以便保存对数据库的命中),那么我仍然认为集中式缓存是一种比内存分布更好的方法。同步缓存。 您只需要确保在缓存数据上使用适当的过期时间,以便不时地自然刷新数据。 此外,您可能只想在特定实体的更新路径中从集中式存储中删除缓存数据,然后在下次请求该数据时从缓存中重新加载缓存数据。 这是IMO比尝试执行真正的直写缓存更好,您可以在其中写入底层存储以及缓存。 数据库本身可能会对数据进行调整(例如,通过默认的不匹配值),在这种情况下,您的缓存数据可能与数据库中的数据不匹配。

编辑

在评论中提出了一个关于集中式缓存优势的问题(我猜测的是内存分布式缓存)。 我会就此提出我的意见,但首先是标准的免责声明。 集中式缓存并不是万灵药。 它旨在解决与in-jvm-memory缓存相关的特定问题。 在评估是否切换到它之前,您应该首先了解您的问题,看看它们是否符合集中式缓存的好处。 集中式缓存是一种架构变化,它可能带有问题/警告。 不要简单地转向它,因为有人说它比你正在做的更好。 确保原因符合问题。

好的,现在我认为集中式缓存可以解决哪些问题与内部jvm内存(以及可能是分布式)缓存有关。 我要列出两件事,虽然我相信还有更多。 我的两个主要问题是: 整体内存占用数据同步问题

让我们从整体记忆足迹开始。 假设您正在进行标准实体缓存,以保护您的关系数据库免受过度压力。 我们还要说,为了真正保护您的数据库,您需要缓存大量数据; 说在许多GB的范围内。 如果你正在使用in-jvm-memory缓存,并且你说有10个应用服务器盒,你需要为每个需要在jvm中进行缓存的每个盒子获得10倍的额外内存($$$)记忆。 此外,您必须为JVM分配更大的堆以容纳缓存的数据。 我认为JVM堆应该小而精简,以减轻垃圾收集负担。 如果你有一大堆无法收集的Old Gen,那么当它进入一个完整的GC并且试图从那个臃肿的Old Gen空间中收回一些东西时,你会给你的垃圾收集器施加压力。 你想避免长时间的GC2暂停时间和膨胀你的Old Gen对此没有帮助。 另外,如果您的内存要求高于某个阈值,并且您恰好为您的应用层运行32位计算机,则必须升级到64位计算机,这可能是另一个令人望而却步的成本。

现在,如果您决定集中缓存数据(使用Redis或Memcached之类的东西),您可以显着减少缓存数据的总内存占用量,因为您可以将它放在几个盒子而不是所有应用程序服务器盒中。应用层。 您可能希望使用集群方法(两种技术都支持它)和至少两台服务器为您提供高可用性并避免缓存层中的单点故障(更多内容在一秒内)。 有一台机器可以支持缓存所需的内存需求,你可以节省一些可观的内存。 此外,您可以不同地调整应用程序框和缓存框,因为它们用于不同的目的。 可以针对高吞吐量和低堆调整应用程序框,并且可以针对大内存调整缓存框。 拥有较小的堆肯定有助于提高应用层框的整体吞吐量。

现在是集中缓存的一个快速点。 您应该以这样的方式设置应用程序,使其在没有缓存的情况下能够存活,以防它完全停机一段时间。 在传统的实体缓存中,这意味着当缓存完全不可用时,您只需针对每个请求直接访问您的数据库。 不是很棒,但也不是世界末日。

好的,现在是数据同步问题 。 使用分布式in-jvm-memory缓存,您需要保持缓存同步。 对一个节点中缓存数据的更改需要复制到其他节点并同步到其缓存数据中。 这种方法有点可怕,因为如果由于某种原因(例如网络故障)其中一个节点失去同步,那么当请求进入该节点时,用户看到的数据将不会准确反对当前的节点。 D B。 更糟糕的是,如果他们发出另一个请求并且遇到不同的节点,他们将看到不同的数据,这将使用户感到困惑。 通过集中数据,您可以消除此问题。 现在,人们可以争辩说,集中式缓存需要对同一缓存数据密钥的更新进行并发控制。 如果同一个密钥有两个并发更新,那么如何确保这两个更新不会相互踩踏? 我的想法是不要担心这个; 当更新发生时,从缓存中删除项目(并直接写入数据库)并在下次读取时重新加载。 这种方式更安全,更容易。 如果您不想这样做,那么如果您真的想在更新时更新缓存和数据库,则可以使用CAS(检查和设置)function代替乐观并发控制。

总而言之,如果集中缓存的数据,您可以节省资金并更好地调整应用层机器。 您还可以获得更好的数据准确性,因为您需要处理的数据同步问题较少。 我希望这有帮助。

首先,尽量忘记过早优化。 你真的需要缓存吗? 99%你不需要它。 在这种情况下,您的解决方案是删除冗余代码。

如果你需要它,试着停止重新发明轮子。 有完美的即用型库。 例如,具有分布式模式的ehCache 。

使用HazelCast 。 它允许使用多播协议的服务器之间的数据同步 它易于使用。 它支持锁定和其他function。