Shared java 集群环境下的HashMap

Shared java HashMap in a clustered environment

我有一个客户端应用程序每 1 秒从 url 请求一些信息。

在服务器端(一个servlet & JSP应用程序),为了避免在不需要的时候访问数据库,已经实现了下一个解决方案。这是一个片段:

//a static HashMap where we save the last record inserted in db
public static Map<Long, Long> VALUES = new HashMap<Long, Long>(); 

// A lastRecordRead sent by the client 
if (VALUES.get(id) != lastRecordRead) {     
    //Access the database to get some information 
    //cause the last value read is different from the last record inserted
    ...
}else{
    //Do nothing
    //It's not necessary access DB cause the parameters match
}

这在开发环境中按预期工作。

当我们有一个集群环境时,问题就来了。我们将服务器部署在两个节点中(使用 jboss),每个节点都有自己的 HashMap 和自己的值。所以根据我们攻击的节点,我们可以 获取不同的值...

¿有没有办法在两个节点之间共享这个HashMap?我正在寻找一些不需要更新 2 个地图的答案,这意味着节点之间不需要调用...

如有任何帮助,我们将不胜感激。

编辑:我现在正在玩 HazelCast,它看起来很简单,我担心我做错了什么......

在我的服务器中,我现在使用 HazelCast 而不是 HasMap:

public static Map<Long, Long> VALUES = (Hazelcast.newHazelcastInstance(new Config())).getMap("VALUES"); 

插入记录时:

        if (((VALUES.get(id) == null)||(VALUES.get(id) < lastIdInserted))) {
            VALUES.put(id, lastIdInserted);     
        }

当客户端应用程序调用服务器时:

// A lastRecordRead sent by the client 
if (VALUES.get(id) != lastRecordRead) {     
    //Access the database to get some information 
    //cause the last value read is different from the last record inserted
    ...
}else{
    //Do nothing
    //It's not necessary access DB cause the parameters match
}

我想,仅此而已。谁能确认这是否可以,或者我是否遗漏了什么……?这个解决方案真的遍布所有节点吗?我一直在用 2 个 tomcat 进行测试,它确实有效,但它能与不同的 ips 一起使用吗?

您需要使用分布式HashMap。那里有一些框架。 hazelcast 就是一个例子。您可以使用 Hazelcast 社区版(免费)。

你也可以使用Redisson(分布式计算):https://github.com/mrniko/redisson

您确定访问数据库是您负担不起的开销吗?如果您使用数据库,那么您可以确保正确处理锁定和并发访问。使用 HashMap 意味着您必须自己处理并发读写访问,这可能会显着增加您的设计、构建和测试工作量。

您确定这不是过早的优化吗?

您有两个选择:

  1. 使用一些分布式键值,例如: http://memcached.org/

http://infinispan.org/about/

http://basho.com/riak/

http://hazelcast.org/

...还有很多其他的。

  1. 使用'publisher-subscriber'概念,通过事件更新每个HashMap实例。这通常是通过一些 JMS 代理实现的:

    http://docs.oracle.com/cd/E19717-01/819-7759/aerbk/index.html https://www.rabbitmq.com/tutorials/tutorial-three-java.html

选择取决于您的需要:要获得最快的读取和查找速度,没有网络延迟但更新速度较慢 - 使用第二个选项。对于不经常更改的数据来说,这是一个很好的解决方案:地理名称、地址等。

一般情况下 - 使用第一个。