hazelcast java_Hazelcast 介绍与使用(整理)

要用到 Hazelcast 这个东西用作分布式缓存, 网上搜索了下发现这篇文章对我理解 Hazelcast 那种无主从之分, 避免了单点故障很有帮助, Hazelcast 的数据分布方式很有点像磁盘阵列 RAID 1, RAID0+1 的影子. 基本上在一个节点出现故障的情况下是不会影响数据访问的.

下面这个系列讲的很详细:

Hazelcast 是一个开源的可嵌入式数据网格(社区版免费,企业版收费)。你可以把它看做是内存数据库,不过它与 Redis 等内存数据库又有些不同。项目地址:http://hazelcast.org/

Hazelcast 使得 Java 程序员更容易开发分布式计算系统,提供了很多 Java 接口的分布式实现,如:Map, Queue, Topic, ExecutorService, Lock, 以及 JCache 等。它以一个 JAR 包的形式提供服务,只依赖于 Java,并且提供 Java, C/C++, .NET 以及 REST 客户端,因此十分容易使用。

如何存储数据

Hazelcast 服务之间是端对端的,没有主从之分,因此也不存在单点故障。集群中所有的节点都存储等量的数据以及进行等量的计算。

Hazelcast 缺省情况下把数据分为 271 个区。这个值可配置于系统属性hazelcast.partition.count。 对于一个给定的键,在经过序列号、哈希并对分区总数取模之后能得到此键对应的分区号。所有的分区等量的分布与集群中所有的节点中,每个分区对应的备份也同样分布在集群中。

下例是拥有2个节点的 Hazelcast 集群:

8242816ff1e3b28f1d0a9b812a9ad850.png

黑色字体表示分区,蓝色字体表示备份。节点1存储了1到135分区,这些分区同时备份在节点2中。节点2存储了136到271分区,并备份在节点1中。

此时如果添加2个节点到集群中,Hazelcast 一个一个的移动分区和备份到新的节点,使得集群数据分布平衡。

9a5d408f2709fc6ae8548d723712a81d.png

注意实际中分区并不是有顺序的分布,而是随机分布,上面的示例只是为了方便理解。重要的是理解 Hazelcast 平均分布分区以及备份。

Hazelcast 使用哈希算法进行数据分区。对于一个给定的键(如Map)或者对象名称(如topic和list):

序列化此键或对象名称,得到一个byte数组。

对byte数组进行哈希。

取模后的值即为分区号。

每个节点维护一个分区表,存储着分区号与节点之间的对应关系。这样每个节点都知道如何获取数据。

重分区

集群中最老的节点(或者说最先启动)负责定时发送分区表到其他节点。这样如果有节点加入或者离开集群,所有的节点也能更新分区表。

注意: 如果最老的节点挂了,次老节点会接手这个任务。

这个定时任务时间间隔可配置系统属性 hazelcast.partition.table.send.interval。 缺省值为15秒。

重分区发生在:

节点加入集群。

节点离开集群。

此时最老节点会更新分区表,分发,接着集群开始移动分区,或者从备份恢复分区。

使用方式

有两种方式:嵌入式和客户端服务器。

嵌入式,Hazelcast 服务器的 jar 包被导入宿主应用程序,服务器启动并存在于各个宿主应用中。优点是可以更低延迟的数据访问。

ff07f8e528a2b8e9829d346048659b5a.png

客户端服务器,Hazelcast 客户端的 jar 包被导入宿主应用程序,服务器 jar 包独立运行于 JVM 中。优点是更容易调试以及更可靠的性能,最重要的是更好的扩展性。

d776ada1a64915fe906192625bfd0512.png

以下是两段使用 Hazelcast 作为分布式 Map 和 Topic 的例子

import com.hazelcast.config.Config;

import com.hazelcast.core.Hazelcast;

import com.hazelcast.core.HazelcastInstance;

import java.util.concurrent.ConcurrentMap;

public class DistributedMap {

public static void main(String[] args) {

Config config = new Config();

HazelcastInstance h = Hazelcast.newHazelcastInstance(config);

ConcurrentMap<String, String> map = h.getMap("my-distributed-map");

map.put("key", "value");

//Concurrent Map methods

map.putIfAbsent("somekey", "somevalue");

map.replace("key", "value", "newvalue");

map.forEach((k, v) -> System.out.println(k + " => " + v));

h.shutdown();

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

importcom.hazelcast.config.Config;

importcom.hazelcast.core.Hazelcast;

importcom.hazelcast.core.HazelcastInstance;

importjava.util.concurrent.ConcurrentMap;

publicclassDistributedMap{

publicstaticvoidmain(String[]args){

Configconfig=newConfig();

HazelcastInstanceh=Hazelcast.newHazelcastInstance(config);

ConcurrentMap<String,String>map=h.getMap("my-distributed-map");

map.put("key","value");

//Concurrent Map methods

map.putIfAbsent("somekey","somevalue");

map.replace("key","value","newvalue");

map.forEach((k,v)->System.out.println(k+" => "+v));

h.shutdown();

}

}

import com.hazelcast.config.Config;

import com.hazelcast.core.*;

public class DistributedTopic implements MessageListener<String> {

static HazelcastInstance h;

public static void main(String[] args) {

Config config = new Config();

h = Hazelcast.newHazelcastInstance(config);

ITopic<String> topic = h.getTopic("my-distributed-topic");

topic.addMessageListener(new DistributedTopic());

topic.publish("Hello to distributed world");

}

@Override

public void onMessage(Message<String> message) {

System.out.println("Got message " + message.getMessageObject());

h.shutdown();

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

importcom.hazelcast.config.Config;

importcom.hazelcast.core.*;

publicclassDistributedTopicimplementsMessageListener<String>{

staticHazelcastInstanceh;

publicstaticvoidmain(String[]args){

Configconfig=newConfig();

h=Hazelcast.newHazelcastInstance(config);

ITopic<String>topic=h.getTopic("my-distributed-topic");

topic.addMessageListener(newDistributedTopic());

topic.publish("Hello to distributed world");

}

@Override

publicvoidonMessage(Message<String>message){

System.out.println("Got message "+message.getMessageObject());

h.shutdown();

}

}

启动后会看到输出

Members [2] {

Member [192.168.2.106]:5702 - 274180a0-f05e-467d-bd84-13249f9db491

Member [192.168.2.106]:5703 - 16de21f2-3c5c-477f-aec6-0a33d6d02aba this

}

即使是本地的启动方式也会打开 Socket 端口, 默认在本机启动两个不同的端口号. 其他 Hazelcast 的应用例子可参考 https://hazelcast.org/.

其他相关链接:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值