与其尝试在两个服务器实例之间同步缓存数据,为什么不使用 memcached/couchbase 或 redis 之类的工具来集中缓存呢?在我看来,与使用上述提到的缓存服务器集中缓存数据相比,使用像 ehcache 这样的分布式缓存要复杂得多,而且更容易出错。
作为我原来答案的附录,在决定使用哪种缓存方法(在内存中,集中式)时,需要考虑的一件事是正在缓存的数据的波动性。
如果数据存储在数据库中,但在服务器加载后没有更改,那么您甚至不需要服务器之间的同步。只需让他们每个人将这些静态数据从源加载到内存中,然后继续他们快乐的方式做他们所做的事情。数据不会改变,因此无需引入复杂的模式来保持服务器之间的数据同步。
如果数据确实存在一定程度的波动性(比如您正在缓存从数据库中查找的实体数据以保存对数据库的命中),那么我仍然认为集中式缓存是比内存中分布式缓存更好的方法同步缓存。您只需要确保对缓存数据使用适当的过期时间,以允许数据不时自然刷新。此外,您可能希望在特定实体的更新路径中时从集中式存储中删除缓存的数据,然后在下次请求该数据时从缓存中重新加载它。在我看来,这比尝试执行真正的直写式缓存(在其中写入底层存储以及缓存)要好。数据库本身可能会对数据进行调整(例如通过默认未提供的值),并且在这种情况下您的缓存数据可能与数据库中的数据不匹配。
EDIT:
评论中提出了一个关于集中式缓存优点的问题(我猜测是针对内存中分布式缓存之类的东西)。我将对此发表我的意见,但首先是标准免责声明。集中式缓存并不是包治百病的灵丹妙药。它旨在解决与 jvm 内存缓存相关的特定问题。在评估是否切换到它之前,您应该首先了解您的问题是什么,并看看它们是否符合集中式缓存的好处。集中式缓存是一种架构变化,它可能会带来自己的问题/警告。不要因为有人说它比你正在做的更好而转向简单的做法。确保原因符合问题。
好的,现在谈谈我对集中式缓存与 jvm 内存(可能还有分布式)缓存相比可以解决哪些问题的看法。我将列出两件事,尽管我确信还有更多。我的两个大的是:总体内存占用 and 数据同步问题.
让我们从总体内存占用。假设您正在执行标准实体缓存,以保护您的关系数据库免受过度压力。假设您有大量数据需要缓存,以便真正保护您的数据库;比如说在许多GB的范围内。如果您正在进行 jvm 内存中的缓存,并且您说有 10 个应用程序服务器框,那么您需要为每个需要在 jvm 中进行缓存的框获得额外的内存 ($$$) 乘以 10记忆。此外,您还必须为 JVM 分配更大的堆以容纳缓存的数据。我认为 JVM 堆应该小而精简,以减轻垃圾收集负担。如果您有大量无法收集的 Old Gen,那么当垃圾收集器进入完整的 GC 并尝试从臃肿的 Old Gen 空间中回收一些东西时,您会给垃圾收集器带来压力。您希望避免长时间的 GC2 暂停时间,而让您的 Old Gen 膨胀对此无济于事。另外,如果您的内存要求高于某个阈值,并且您的应用程序层恰好运行 32 位计算机,则您必须升级到 64 位计算机,这可能是另一个令人望而却步的成本。
现在,如果您决定集中缓存数据(使用 Redis 或 Memcached 等),则可以显着减少缓存数据的总体内存占用量,因为您可以将其放在几个盒子上,而不是放在所有应用程序服务器盒子上。应用程序层。您可能希望使用集群方法(两种技术都支持它)和至少两台服务器来为您提供高可用性并避免缓存层中的单点故障(稍后将详细介绍)。通过拥有几台机器来支持缓存所需的内存要求,您可以节省大量资金。此外,您现在可以以不同的方式调整应用程序框和缓存框,因为它们具有不同的用途。应用程序框可以调整为高吞吐量和低堆,缓存框可以调整为大内存。拥有更小的堆肯定有助于提高应用程序层框的整体吞吐量。
现在简要介绍一下一般的集中式缓存。您应该以这样的方式设置您的应用程序,即使它在一段时间内完全崩溃,它也可以在没有缓存的情况下生存。在传统的实体缓存中,这意味着当缓存完全不可用时,您只需为每个请求直接访问数据库。不算太棒,但也不是世界末日。
好的,现在为数据同步问题。对于分布式 jvm 内存缓存,您需要保持缓存同步。对一个节点中缓存数据的更改需要复制到其他节点并同步到其缓存数据中。这种方法有点可怕,因为如果由于某种原因(例如网络故障)其中一个节点不同步,那么当请求发送到该节点时,用户看到的数据将与当前节点中的数据不准确。 D B。更糟糕的是,如果他们发出另一个请求并到达不同的节点,他们将看到不同的数据,这会让用户感到困惑。通过集中数据,您可以消除这个问题。现在,人们可能会争辩说,集中式缓存需要围绕同一缓存数据密钥的更新进行并发控制。如果同一个密钥有两个并发更新,如何确保这两个更新不会互相干扰?我的想法是根本不用担心这个问题;当发生更新时,从缓存中删除该项目(并直接写入数据库)并让它在下次读取时重新加载。这样更安全、更容易。如果您不想这样做,那么如果您确实想在更新时更新缓存和数据库,则可以使用 CAS(检查并设置)功能来代替乐观并发控制。
总而言之,如果您集中缓存的数据,您可以节省资金并更好地调整应用程序层计算机。由于需要处理的数据同步问题较少,您还可以获得更高的数据准确性。我希望这有帮助。