1.Hazelcast概述

1.1 Hazelcast简介

​ Hazelcast 是由Hazelcast公司开发的一款开源的分布式内存级别的缓存数据库,可以为基于JVM环境运行的各种应用提供分布式集群和分布式缓存服务。利用Hazelcast可以满足**“分布式”、“集群服务”、“网格式内存数据”、“分布式缓存“、“弹性可伸缩服务”等的要求。Hazelcast IMDG(In-Memory Data Grid 内存数据网格)具有高度可扩展性可用性**。分布式应用程序可以将其用于分布式缓存、同步、集群、处理、发布/订阅消息传递等。

​ Hazelcast 目前已经更新到 3.X 版本,Java 中绝大部分数据结构都被其以为分布式的方式实现。比如 Javaer 熟悉的 Map 接口,当通过 Hazelcast 创建一个 Map 实例后,在节点 A 调用 Map::put(“A”,“A_DATA”) 方法添加数据,节点 B 使用 Map::get(“A”) 可以获到值为 “A_DATA” 的数据*。Hazelcast* 提供了 Map、Queue、MultiMap、Set、List、Semaphore、Atomic 等接口的分布式实现;提供了基于 Topic 实现的消息队列或订阅 \ 发布模式;提供了分布式 id 生成器(IdGenerator);提供了分布式事件驱动(Distributed Events);提供了分布式计算(Distributed Computing);提供了分布式查询(Distributed Query)。总的来说在独立 jvm 经常使用数据结果或模型 Hazelcast 都提供了分布式集群的实现。

Hazelcast 有开源版本和商用版本。开源版本遵循 Apache License 2.0 开源协议免费使用。商用版本需要获取特定的 License,两者之间最大的区别在于:商用版本提供了数据高密度存储。我们都知道 jvm 有自己特定的 GC 机制,无论数据是在堆还是栈中,只要发现无效引用的数据块,就有可能被回收。而 Hazelcast 的分布式数据都存放在 jvm 的内存中,频繁的读写数据会导致大量的 GC 开销。使用商业版的 Hazelcast 会拥有高密度存储的特性,大大降低 Jvm 的内存开销,从而降低 GC 开销。

​ 附:

​ Hazelcast架构:

在这里插入图片描述

1.2 Hazelcast的特性

  • 自治集群(无中心化)
  • 数据按应用分布式存储
  • 抗单点故障
  • 简易性

​优势:

  • 开源。
  • 基于Jar发布,无需安装软件。
  • 数据保存在内存(RAM)中,便于快速读取和更新。
  • 不对用户暴露Hazelcast的架构。
  • 提供开箱即用的分布式数据结构。
  • 无单点故障。Hazelcast IMDG是点对点的;在Hazelcast IMDG集群中没有单点故障;集群中的每个成员都配置为功能相同。它们都存储等量的数据并进行等量的处理。可以在现有的应用程序中嵌入Hazelcast IMDG,或者在客户机和服务器模式下使用它,其中应用程序是Hazelcast成员的客户机。
  • 当内存大小和计算需求增加时,可以动态地将新成员加入到Hazelcast IMDG集群中,以实现弹性扩展。
  • 数据备份,节点故障数据无丢失。数据对成员故障具有弹性。数据备份分布在整个集群中。当集群中的成员崩溃时,这是一个很大的好处,因为数据没有丢失。Hazelcast在多个成员上保留每个数据条目的备份。当成员发生故障时,数据从备份中恢复,集群继续运行而不会停机。
  • 集群内节点彼此感知。
  • 使用SPI可以构建自己的分布式数据结构。
  • 拥有一个活跃的开源社区。

1.3 使用场景

  • 共享服务器配置和服务器信息,
  • 集群数据变更通知,
  • 作为简单的内存缓存,
  • 作为一个在特定节点执行特定任务的调度器,
  • OSGI框架下不同节点共享信息.
  • 集群内共享数千个key,
  • 作为Cassadra的前端.
  • 集群内分发用户状态,不同对象间传递信息,共享系统数据结构,
  • 多租户缓存,每个租户都有自己独立的缓存,
  • 共享数据集合,
  • 从亚马逊EC2分发和收集服务负载信息,
  • 作为性能检测的实时流,
  • Session存储器
  • 需要通过数据分区进行大数据处理的分析应用
  • 在网格中保留频繁访问的数据
  • 缓存,特别是具有弹性分布式可伸缩性的开源JCache提供程序
  • 为具有最高性能、可伸缩性和低延迟要求的应用程序提供主数据存储
  • 一个内存中的NoSQL键值存储
  • 在应用程序之间以最高速度和可伸缩性进行发布/订阅通信
  • 需要在分布式和云环境中弹性伸缩的应用程序
  • 用于应用程序的高可用分布式缓存
  • 是Coherence和Terracotta的替代品。

使用案例

  • 将高度变化的数据与事件通知聚类,例如,基于用户的事件,以及排队和分发后台任务
  • 作为一个简单的Memcache与近缓存
  • 作为需要在某些成员上执行的某些进程的云范围调度器
  • 与OSGI环境下不同安装中的多个成员动态共享信息(用户信息、queue、map等)
  • 在集群中共享密钥,其中在应用程序服务器上有web服务接口和一些验证
  • 作为分布式主题(发布/订阅服务器),为智能手机构建可扩展的聊天服务器
  • 作为它的并发API的强烈一致的层Hazelcast的CP (CP对上限原理)子系统之上筏共识的算法
  • 作为Cassandra后端的前端层
  • 在集群中分布用户对象状态,在对象之间传递消息并共享系统数据结构(静态初始化状态、镜像对象、对象标识生成器)
  • 作为多租户缓存,其中每个租户都有自己的映射
  • 共享数据集,如表状数据结构,供应用程序使用
  • 分发负载并收集来自Amazon EC2服务器的状态,其中前端是使用Spring框架开发的
  • 作为实时流的性能检测
  • 作为web应用程序中会话数据的存储(支持web应用程序的水平可伸缩性)。

1.4 Hazelcast的入门案例

  1. 引入坐标
<!--hazelcast服务端依赖-->
<dependency>
    <groupId>com.hazelcast</groupId>
    <artifactId>hazelcast</artifactId>
    <version>${hazelcast.version}</version>
</dependency>
<!--hazelcast客户端依赖-->
<dependency>
    <groupId>com.hazelcast</groupId>
    <artifactId>hazelcast-client</artifactId>
    <version>${hazelcast.version}</version>
</dependency>
  1. 搭建hazelcast服务端集群,一个主节点 一个从节点

​ 主节点:创建一个hazelcast实例,即开放计算机的5701端口,在内存中开辟空间建立内存数据库。

package com.joiwsev.hazelcast.quick;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import java.util.Map;
import java.util.Queue;
/**
 * Hazelcast入门案例
 */
public class HazelcastGetStartServerMaster {
	/**
	 hazelcast创建一个内存数据库节点,实际上就是在计算机某个端口(默认5071)创建一个主内存数据库,并对外一直开放。
	 然后通过实例创建一个分布式的map和queue,并添加数据
	 */
	public static void main(String[] args) {
		// 创建一个 hazelcastInstance实例
		HazelcastInstance instance = Hazelcast.newHazelcastInstance();
		// 创建集群Map
		Map<Integer, String> clusterMap = instance.getMap("MyMap");
		clusterMap.put(1, "Hello hazelcast map!");

		// 创建集群Queue
		Queue<String> clusterQueue = instance.getQueue("MyQueue");
		clusterQueue.offer("Hello hazelcast!");
		clusterQueue.offer("Hello hazelcast queue!");
	}
}

​ 从节点:操作已创建的内存数据库,实现主从共同管理。

package com.joiwsev.hazelcast.quick;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import java.util.Map;
import java.util.Queue;
/**
 * hazelcast从节点
 */
public class HazelcastGetStartServerSlave {
	public static void main(String[] args) {
		//创建一个 hazelcastInstance实例
		HazelcastInstance instance = Hazelcast.newHazelcastInstance();
		Map<Integer, String> clusterMap = instance.getMap("MyMap");
		Queue<String> clusterQueue = instance.getQueue("MyQueue");
		System.out.println("Map Value:" + clusterMap.get(1));
		System.out.println("Queue Size :" + clusterQueue.size());
		System.out.println("Queue Value 1:" + clusterQueue.poll());
		System.out.println("Queue Value 2:" + clusterQueue.poll());
		System.out.println("Queue Size :" + clusterQueue.size());
	}
}

​ 3.搭建hazelcast客户端

​ 客户端与服务端的差异为:客户端不会存储数据也不会修改服务集群中的数据。

package com.joiwsev.hazelcast.quick;
import com.hazelcast.client.HazelcastClient;
import com.hazelcast.client.config.ClientConfig;
import com.hazelcast.core.HazelcastInstance;
import java.util.Map;
import java.util.Queue;

/**
 * hazelcast客户端
 */
public class HazelcastGetStartClient {
	public static void main(String[] args) {
		ClientConfig clientConfig = new ClientConfig();
		HazelcastInstance instance = HazelcastClient.newHazelcastClient(clientConfig);
		Map<Integer, String> clusterMap = instance.getMap("MyMap");
		Queue<String> clusterQueue = instance.getQueue("MyQueue");
		System.out.println("Map Value:" + clusterMap.get(1));
		System.out.println("Queue Size :" + clusterQueue.size());
		System.out.println("Queue Value 1:" + clusterQueue.poll());
		System.out.println("Queue Value 2:" + clusterQueue.poll());
		System.out.println("Queue Size :" + clusterQueue.size());
	}
}

客户端的console输出比服务端少很多,因为客户端不需要承载服务端的数据处理功能,也不需要维护各种节点信息。

1.5 入门案例解析

八月 30, 2023 1:14:31 下午 com.hazelcast.config.XmlConfigLocator
信息: Loading 'hazelcast-default.xml' from classpath.
# 这里输出的内容表示 Hazelcast 启动时加载的配置文件。如果用户没有提供有效的配置文件,Hazelcast 会使用默认配置文件
八月 30, 2023 1:14:32 下午 com.hazelcast.instance.DefaultAddressPicker
信息: [LOCAL] [dev] [3.4.6] Prefer IPv4 stack is true.
八月 30, 2023 1:14:32 下午 com.hazelcast.instance.DefaultAddressPicker
信息: [LOCAL] [dev] [3.4.6] Picked Address[192.168.2.47]:5701, using socket ServerSocket[addr=/0:0:0:0:0:0:0:0,localport=5701], bind any local is true
# 这一段输出说明了当前 Hazelcast 的网络环境。首先是检测 IPv4 可用且检查到当前的 IPv4 地址是 192.168.2.47(本机ip地址)。然后使用 IPv6 启用 socket。在某些无法使用 IPv6 的环境上,需要强制指定使用 IPv4,增加 jvm 启动参数:-Djava.net.preferIPv4Stack=true 即可
八月 30, 2023 1:14:32 下午 com.hazelcast.spi.OperationService
信息: [192.168.2.47]:5701 [dev] [3.4.6] Backpressure is disabled
八月 30, 2023 1:14:32 下午 com.hazelcast.spi.impl.BasicOperationScheduler
信息: [192.168.2.47]:5701 [dev] [3.4.6] Starting with 10 generic operation threads and 20 partition operation threads.
八月 30, 2023 1:14:32 下午 com.hazelcast.system
#  这一段说明了数据的序列化方式和启用的线程。Hazelcast 在节点间传递数据有 2 种序列化方式,在后续的文章中国会详细介绍。Hazelcast 会控制多个线程执行不同的工作,有负责维持节点连接的、有负责数据分区管理的。
信息: [192.168.2.47]:5701 [dev] [3.4.6] Hazelcast 3.4.6 (20150914 - 74c48e6) starting at Address[192.168.2.47]:5701
八月 30, 2023 1:14:32 下午 com.hazelcast.system
信息: [192.168.2.47]:5701 [dev] [3.4.6] Copyright (C) 2008-2014 Hazelcast.com
八月 30, 2023 1:14:32 下午 com.hazelcast.instance.Node
信息: [192.168.2.47]:5701 [dev] [3.4.6] Creating MulticastJoiner
八月 30, 2023 1:14:32 下午 com.hazelcast.core.LifecycleService
# 上面这一段输出中,Creating MulticastJoiner 表示使用组播协议来组建集群。还创建了 6 个用于维护非拥塞信息输出 \ 输出。
信息: [192.168.2.47]:5701 [dev] [3.4.6] Address[192.168.2.47]:5701 is STARTING
#  这一段输出说明了当前实例的初始化端口号是 5701。Hazelcast 默认使用 5701 端口。如果发现该端口被占用,会 + 1 查看 5702 是否可用,如果还是不能用会继续向后探查直到 5800。Hazelcast 默认使用 5700 到 5800 的端口,如果都无法使用会抛出启动异常。
八月 30, 2023 1:14:39 下午 com.hazelcast.cluster.impl.MulticastJoiner
信息: [192.168.2.47]:5701 [dev] [3.4.6] 

Members [1] {
	Member [192.168.2.47]:5701 this
}
Members [2] {
	Member [192.168.2.47]:5701
	Member [192.168.2.47]:5702 this
}
# Members [2] 表示当前集群只有 2 个节点。2 个节点都在 ip 为 192.168.2.47 的这台设备上,2 个节点分别占据了 5701 端口和 5702 端口。端口后面的 this 说明这是当前节点,而未标记 this 的是其他接入集群的节点。最后 InternalPartitionService 输出的信息表示集群初始化了 “数据分片”,后面会介绍 “数据分片” 的概念和原理。

八月 30, 2023 1:14:39 下午 com.hazelcast.core.LifecycleService
信息: [192.168.2.47]:5701 [dev] [3.4.6] Address[192.168.2.47]:5701 is STARTED
八月 30, 2023 1:14:39 下午 com.hazelcast.partition.InternalPartitionService
信息: [192.168.2.47]:5701 [dev] [3.4.6] Initializing cluster partition table first arrangement...

参考:
hazelcast官方文档:https://docs.hazelcast.com/imdg/4.2/data-structures/queue

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐