14

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

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

4

3 回答 3

41

与其尝试在两个服务器实例之间同步缓存数据,不如使用 memcached/couchbase 或 redis 之类的东西来集中缓存?与使用像提到的那些缓存服务器集中缓存数据相比,将分布式缓存与 ehcache 之类的东西一起使用要复杂得多且容易出错 IMO。

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

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

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

编辑

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

好的,现在谈谈我对集中式缓存与 jvm-memory(可能是分布式)缓存可以解决哪些问题的看法。我将列出两件事,尽管我确信还有更多。我的两个大问题是:整体内存占用数据同步问题

让我们从整体内存占用开始. 假设您正在执行标准实体缓存以保护您的关系数据库免受过度压力。假设您有很多数据要缓存以真正保护您的数据库;说在许多 GB 的范围内。如果您正在执行 jvm 内存缓存,并且您说有 10 个应用程序服务器框,那么您需要为每个需要在 jvm 中进行缓存的框获取额外的内存 ($$$) 乘以 10记忆。此外,您必须为 JVM 分配更大的堆以容纳缓存的数据。我认为 JVM 堆应该小而精简,以减轻垃圾收集的负担。如果你有一大块老一代可以' 如果没有被收集,那么当垃圾收集器进入完整的 GC 并试图从那个臃肿的旧代空间中回收一些东西时,你就会给它施加压力。你想避免长时间的 GC2 暂停时间,而让你的老一代臃肿无济于事。另外,如果您的内存要求高于某个阈值,并且您的应用层恰好运行 32 位机器,则您必须升级到 64 位机器,这可能是另一个令人望而却步的成本。

现在,如果您决定集中缓存数据(使用 Redis 或 Memcached 之类的东西),您可以显着减少缓存数据的总体内存占用,因为您可以将它放在几个盒子上,而不是所有应用服务器盒子上应用层。您可能希望使用集群方法(两种技术都支持)和至少两台服务器来为您提供高可用性并避免缓存层中的单点故障(稍后会详细介绍)。通过拥有几台机器来支持缓存所需的内存需求,您可以节省一些可观的美元。此外,您现在可以对应用程序框和缓存框进行不同的调整,因为它们有不同的用途。应用程序盒可以针对高吞吐量和低堆进行调整,缓存盒可以针对大内存进行调整。

现在,一般来说集中缓存的一个要点。您应该以这样一种方式设置您的应用程序,以便它可以在没有缓存的情况下生存,以防它在一段时间内完全关闭。在传统的实体缓存中,这意味着当缓存完全不可用时,您只需为每个请求直接访问您的数据库。不可怕,但也不是世界末日。

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

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

于 2013-05-16T11:13:18.957 回答
8

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

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

于 2013-05-16T11:14:54.513 回答
3

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

于 2013-08-23T11:24:01.553 回答