43

将 Singleton 对象重构为集群环境的最佳策略是什么?

我们使用 Singleton 来缓存数据库中的一些自定义信息。它主要是只读的,但在某些特定事件发生时会刷新。

现在我们的应用程序需要部署在集群环境中。根据定义,每个 JVM 都会有自己的 Singleton 实例。因此,当单个节点上发生刷新事件并且其缓存被刷新时,JVM 之间的缓存可能不同步。

保持缓存同步的最佳方法是什么?

谢谢。

编辑:缓存主要用于向 UI 提供自动完成列表(性能原因),我们使用 Websphere。因此,欢迎任何与 Websphere 相关的提示。

4

9 回答 9

16

用分布式缓存替换您的单例缓存。

JBoss Infinispan就是一个这样的缓存,但我确信存在其他分布式缓存和网格技术,包括目前可能更成熟的商业技术。

对于一般的单例对象,我不确定。我想我会尽量不要有单身人士。

于 2009-07-28T13:35:51.673 回答
10

最简单的方法是:

  1. 将过期计时器添加到您的单例缓存中,以便每隔一段时间清除缓存并且后续调用从源(例如数据库)获取更新的数据

  2. 使用 JMS 主题/tibRV 之类的东西为缓存实现通知机制。让每个缓存实例订阅并响应关于此主题广播的任何更改消息。

于 2009-07-28T13:54:30.183 回答
8

您可以使用WAS 中内置的DistributedMap 。

-瑞克

于 2009-08-04T21:57:38.927 回答
4

或者类似 memcached 的东西

http://www.danga.com/memcached/

什么是内存缓存?memcached 是一个高性能的分布式内存对象缓存系统,本质上是通用的,但旨在通过减轻数据库负载来加速动态 Web 应用程序。

Danga Interactive 开发了 memcached 来提高 LiveJournal.com 的速度,该网站已经为 100 万用户提供了每天超过 2000 万次动态页面浏览量,拥有一堆网络服务器和一堆数据库服务器。memcached 将数据库负载降低到几乎为零,从而为用户提供更快的页面加载时间、更好的资源利用率以及在 memcache 未命中时更快地访问数据库。

于 2009-07-28T13:55:42.630 回答
1

如果可能,请尽可能使用您的应用服务器对此的支持(有些有,有些没有)。例如,我们使用 JBoss 对“HA Singleton”的支持,这是一项仅在集群主节点上运行的服务。它并不完美(你必须处理偶尔会放屁的情况),但它已经足够好了。

如果做不到这一点,您也许可以使用 JGroups 来设计一些东西,它提供集群节点自动发现和协商,但这并不简单。

作为最后的手段,您可以使用数据库锁定来管理集群单例,但这非常脆弱。不建议。

作为集群单例的替代方案,您可以使用分布式缓存。我推荐JBossCache(它不需要运行 JBoss 应用服务器)或 EhCache(它现在提供了一种分发机制)。你必须重新设计你的缓存以分布式方式工作(它不会神奇地工作),但它可能会是一个比集群单例更好的解决方案。

于 2009-07-28T13:38:00.827 回答
1

我和 Vest Hansen 先生在这个问题上,尽可能远离单身人士。在被 SAAJ 和 JAXP 的噩梦所困扰并在 JBoss 上获得兼容版本之后,我已经完成了单例和工厂。SOAP 消息不需要工厂来实例化它。

好吧,吐槽一下,memcache 或类似的东西呢?您的缓存需要什么样的亲和力?如果它已经过时了是不是很糟糕,或者在数据过时的程度方面是否有一些灵活性?

于 2009-07-28T13:41:43.413 回答
1

有几种方法可以处理这个问题,取决于 1) 数据的数据量,以及 2) 每个实例是否需要始终具有相同的值。

如果您只需要合理的数据,但每个 JVM 都不需要匹配数据,您可以让每个 jvm 以相同的时间表(例如,每 30 秒)刷新其数据。

如果刷新需要大约在同一时间发生,您可以让一个 jvm 向其余的 jvm 发送一条消息,说“现在该刷新了”

如果每个 jvm 总是需要相同的信息,你需要做一个同步,master 说“refresh now”,所有的缓存都会阻塞任何新的查询,刷新,然后告诉 master 已经完成了。当主节点从集群的每个成员那里得到答复时,它会发送另一条消息,表示继续。

于 2009-07-28T13:59:16.650 回答
1

我面临着类似的情况,但我正在使用 Oracle 的WebLogicCoherence

我正在处理一个 Web 应用程序,该应用程序使用带有从数据库读取的缓存数据的哈希图(显示在webform标签上的文本)。为此,开发人员使用了一个存储所有这些信息的单例实例。这在单个服务器环境中运行良好,但现在我们想要进入集群解决方案,我正面临这个单例实例的问题。

从我现在阅读的内容来看,这是完成我想要的最佳解决方案。我希望这也可以帮助您解决问题。

于 2010-02-25T11:16:00.993 回答
0

在这种情况下,有一些产品可以提供分布式内存缓存(例如 memcache)。

如果可能的话,一个更好的解决方案可能是让单例不是真正的单例,而是让应用程序容忍有单独的实例(比如所有实例都可以识别它们何时需要刷新),而不是它们必须在 JVM 之间同步,这可能会将您的缓存变成瓶颈。

于 2009-07-28T13:59:43.763 回答