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 意味着您必须自己处理并发读写访问,这可能会显着增加您的设计、构建和测试工作量。
您确定这不是过早的优化吗?
您有两个选择:
- 使用一些分布式键值,例如:
http://memcached.org/
...还有很多其他的。
使用'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
选择取决于您的需要:要获得最快的读取和查找速度,没有网络延迟但更新速度较慢 - 使用第二个选项。对于不经常更改的数据来说,这是一个很好的解决方案:地理名称、地址等。
一般情况下 - 使用第一个。
我有一个客户端应用程序每 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 意味着您必须自己处理并发读写访问,这可能会显着增加您的设计、构建和测试工作量。
您确定这不是过早的优化吗?
您有两个选择:
- 使用一些分布式键值,例如: http://memcached.org/
...还有很多其他的。
使用'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
选择取决于您的需要:要获得最快的读取和查找速度,没有网络延迟但更新速度较慢 - 使用第二个选项。对于不经常更改的数据来说,这是一个很好的解决方案:地理名称、地址等。
一般情况下 - 使用第一个。