【问题标题】:Best way to synchronize cache data between two servers [closed]在两台服务器之间同步缓存数据的最佳方法[关闭]
【发布时间】:2013-05-11 05:59:38
【问题描述】:

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

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

【问题讨论】:

  • 另一个很好的问题,我被谷歌发现并被堆栈关闭。谢谢stackholes。

标签: java caching synchronize


【解决方案1】:

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

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

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

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

编辑

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

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

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

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

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

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

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

【讨论】:

  • 感谢您的回复。你能解释一下集中缓存的优点吗,因为它可能会增加我服务器的开销。目前它有大约 5000 个同时用户。注意:根据目前的统计数据,我现在也在某个特定时间超出了内存范围。
  • 通过响应更新以包含一些优点...
  • Thanx Cmbaxter...这真的很有帮助...
  • @cmbaxter 很好的解释,您对两级缓存有何看法,即本地缓存并将所有本地缓存​​与 Redis 等集中式缓存同步。
【解决方案2】:

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

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

【讨论】:

  • 感谢您的回复。我有大约 5000 个同时用户,因此我想我无法删除缓存。将搜索ehCache...
  • "99% 你不需要它。"严重地?我认为恰恰相反。许多开发人员不使用它。因此,继续用不必要的负载冲击他们的后端服务器
  • 我尝试在 spring-boot 应用程序中实现缓存我的问题是,无论我添加的任何新记录都没有在缓存中更新。如何将数据库与缓存同步。如果我写一个函数来比较数据,那就是额外的工作。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-30
    • 1970-01-01
    • 2010-12-17
    相关资源
    最近更新 更多