Java 集群环境中的单例
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1194129/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Singleton in Cluster environment
提问by lud0h
What is the best strategy to refactor a Singleton object to a cluster environment?
将 Singleton 对象重构为集群环境的最佳策略是什么?
We use Singleton to cache some custom information from Database. Its mostlyread-only but gets refreshed when some particular event occurs.
我们使用 Singleton 从数据库中缓存一些自定义信息。它主要是只读的,但在发生某些特定事件时会刷新。
Now our application needs to be deployed in a Clustered environment. By definition, each JVM will have its own Singleton instance. So the cache may be out-of-sync between the JVM's when a refresh event occurs on a single node and its cache is refreshed.
现在我们的应用程序需要部署在集群环境中。根据定义,每个 JVM 都有自己的 Singleton 实例。因此,当单个节点上发生刷新事件并刷新其缓存时,JVM 之间的缓存可能不同步。
What is the best way to keep the cache's in sync?
保持缓存同步的最佳方法是什么?
Thanks.
谢谢。
Edit: The cache is mainly used to provide an autocomplete list (performance reasons) to UI and we use Websphere. So any Websphere related tips welcome.
编辑:缓存主要用于向 UI 提供自动完成列表(性能原因),我们使用 Websphere。所以欢迎任何与 Websphere 相关的提示。
采纳答案by pjp
The simplest approaches are:
最简单的方法是:
Add an expiry timer to your singleton cache so that every so often the cache gets purged and subsquent calls fetch the updated data from source (e.g. a database)
Implement a notification mechanism for the cache using something like a JMS topic/tibRV. Get each cache instance to subscribe and react to any change messages broadcast on this topic.
将到期计时器添加到您的单例缓存中,以便缓存经常被清除,并且后续调用从源(例如数据库)获取更新的数据
使用 JMS 主题/tibRV 之类的东西为缓存实现通知机制。获取每个缓存实例以订阅并对此主题广播的任何更改消息做出反应。
回答by Chris Vest
Replace your singleton cache with a distributed cache.
用分布式缓存替换你的单例缓存。
One such cache could be JBoss Infinispanbut I'm sure that other distributed cache and grid technologies exist, including commercial ones which are probably more mature at this point.
JBoss Infinispan就是一个这样的缓存,但我确信存在其他分布式缓存和网格技术,包括在这一点上可能更成熟的商业技术。
For singleton objects in general, I'm not sure. I think I'd try to not have singletons in the first place.
对于一般的单例对象,我不确定。我想我首先会尽量不要单身。
回答by skaffman
If possible, use your app server's support for this, if possible (some have it, some don't). For example, we use JBoss's support for an "HA Singleton" which is a service that only runs on the cluster master node. It's not perfect (you have to handle the case where occasionally it brain farts), but it's good enough.
如果可能,请尽可能使用您的应用服务器对此的支持(有些有,有些没有)。例如,我们使用 JBoss 对“HA Singleton”的支持,它是一种仅在集群主节点上运行的服务。它并不完美(你必须处理它偶尔会放屁的情况),但它已经足够好了。
Failing that, you may be able to engineer something using JGroups, which provides with cluster node auto-discovery and negotiation, but it's non-trivial.
如果做不到这一点,您也许可以使用 JGroups 来设计一些东西,它提供集群节点自动发现和协商,但这并不重要。
As a last resort, you can use database locking to manage cluster singletons, but that's seriouslyfragile. Not recommended.
作为最后的手段,您可以使用数据库锁定来管理集群单例,但这非常脆弱。不建议。
As an alternative to a cluster singleton, you could use a distributed cache instead. I recommend JBossCache(which doesn't need JBoss app server to run) or EhCache (which now provides a distribution mechanism). You'll have to reengineer your cache to work in a distributed way (it won't magically just work), but it's probably going to be a better solution than a cluster singleton.
作为集群单例的替代方案,您可以使用分布式缓存。我推荐JBossCache(它不需要运行 JBoss 应用服务器)或 EhCache(它现在提供了一个分发机制)。你必须重新设计你的缓存以分布式方式工作(它不会神奇地工作),但它可能是比集群单例更好的解决方案。
回答by Chris K
I'm with Mr. Vest Hansen on this one, move as far away from singletons as you possibly can. After being plaguged with the nightmare that is SAAJ and JAXP and getting compatible versions working on JBoss, I'm done with singletons and factories. A SOAP message shouldn't need a factory to instantiate it.
我和 Vest Hansen 先生在一起,尽可能远离单身人士。在被 SAAJ 和 JAXP 的噩梦困扰并在 JBoss 上获得兼容版本之后,我已经完成了单例和工厂的工作。SOAP 消息不应该需要工厂来实例化它。
Okay, rant over, what about memcache or something similar? What sort of affinity do you need for your cache? Is it bad if it's EVER out of date, or is there some flexibility in how out of date the data can get?
好吧,吐槽一下,memcache 或类似的东西呢?您的缓存需要什么样的亲和力?如果它已经过时了是不是很糟糕,或者数据过时的程度是否有一些灵活性?
回答by monkey_p
Or something like memcached
或者像memcached这样的东西
http://www.danga.com/memcached/
http://www.danga.com/memcached/
What is memcached? memcached is a high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load.
Danga Interactive developed memcached to enhance the speed of LiveJournal.com, a site which was already doing 20 million+ dynamic page views per day for 1 million users with a bunch of webservers and a bunch of database servers. memcached dropped the database load to almost nothing, yielding faster page load times for users, better resource utilization, and faster access to the databases on a memcache miss.
什么是内存缓存?memcached 是一种高性能、分布式内存对象缓存系统,本质上是通用的,但旨在通过减轻数据库负载来加速动态 Web 应用程序。
Danga Interactive 开发了 memcached 来提高 LiveJournal.com 的速度,该网站每天已经为 100 万用户处理了 2000 万次以上的动态页面浏览量,拥有大量网络服务器和大量数据库服务器。memcached 将数据库负载降至几乎为零,从而为用户提供更快的页面加载时间、更好的资源利用率以及在 memcache 未命中时更快地访问数据库。
回答by KeithB
There are several ways to handle this, depending on 1) how out of data the data is, and 2) does every instance need to have the same values all of the time.
有几种方法可以解决这个问题,这取决于 1) 数据的数据不足程度,以及 2) 是否每个实例都需要始终具有相同的值。
If you just need data that is reasonably up to data, but every JVM doesn't need to have matching data, you can just have every jvm refresh its data on the same schedule (e.g., every 30 seconds).
如果您只需要与数据相当的数据,但每个 JVM 不需要具有匹配数据,您可以让每个 jvm 以相同的时间表(例如,每 30 秒)刷新其数据。
If the refresh needs to happen at about the same time, you can have one jvm send out a message to the rest of them saying "its time to refresh now"
如果刷新需要大约在同一时间发生,您可以让一个 jvm 向其余的人发送一条消息,说“现在该刷新了”
If every jvm always needs the same information, you need to do a sync, where the master says "refresh now", all of the caches block any new queries, refresh, and tell the master that they are done. When the master gets an answer back from every member of the cluster, it sends another message that says to proceed.
如果每个 jvm 总是需要相同的信息,你需要做一个同步,在那里 master 说“现在刷新”,所有的缓存都会阻止任何新的查询,刷新,并告诉 master 他们已经完成。当 master 从集群的每个成员那里得到答复时,它会发送另一条消息,说要继续。
回答by Yishai
There are products for having a distributed in memory cache (such as memcache) that can help in this situation.
有些产品具有分布式内存缓存(例如 memcache)可以帮助解决这种情况。
A better solution, if possible, may be to have the singletons not really be single, but have the application tolerate having separate instances (say that all recognize when they need to be refreshed) but not that they have to be in sync across JVMs, that can turn your cache into a bottleneck.
如果可能的话,更好的解决方案可能是让单例不是真正的单例,而是让应用程序容忍具有单独的实例(假设所有实例都知道何时需要刷新),而不是它们必须跨 JVM 同步,这可能会将您的缓存变成瓶颈。
回答by Rick
回答by XpiritO
I'm facing a similar situation, but I'm using Oracle's WebLogicand Coherence.
我面临类似的情况,但我使用的是 Oracle 的WebLogic和Coherence。
I'm working over a web application that uses an hashmapwith cached data read from the database (text to show on webform's labels). To accomplish this, the developers used a singleton instance where they stored all this information. This worked well on a single server environment, but now we want to go into cluster solution and I'm facing this issue with this singleton instance.
我正在处理一个 Web 应用程序,该应用程序使用带有从数据库读取的缓存数据的哈希图(显示在webform标签上的文本)。为了实现这一点,开发人员使用了一个单例实例来存储所有这些信息。这在单服务器环境中运行良好,但现在我们想进入集群解决方案,我正面临这个单例实例的问题。
From what I've read by now, this is the best solution to accomplish what I want. I hope this helps you with your problem, too.
从我现在读到的内容来看,这是完成我想要的最佳解决方案。我希望这也能帮助你解决你的问题。