Hazelcast分布式内存网格(IMDG)基本使用,使用Hazelcast做分布式内存缓存

2023-12-07 08:28

本文主要是介绍Hazelcast分布式内存网格(IMDG)基本使用,使用Hazelcast做分布式内存缓存,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 一、Hazelcast简介
    • 1、Hazelcast概述
    • 2、Hazelcast之IMDG
    • 3、数据分区
  • 二、Hazelcast配置
    • 1、maven坐标
    • 2、集群搭建
      • (1)组播自动搭建
    • 3、客户端
    • 4、集群分组
    • 5、其他配置
  • 三、Hazelcast分布式数据结构
    • 1、IMap
    • 2、IQueue:队列
    • 3、MultiMap
    • 4、ISet
    • 5、IList
    • 6、其它
  • 参考资料

一、Hazelcast简介

1、Hazelcast概述

官方文档:https://docs.hazelcast.com/hazelcast/5.3/

Hazelcast是驻内存数据网格(In-Memory Data Grid,IMDG)的数据网格开源项目,同时也是该公司的名称。Hazelcast提供弹性可扩展的分布式内存计算,Hazelcast被公认是提高应用程序性能和扩展性最好的方案。Hazelcast通过开放源码的方式提供以上服务。更重要的是,Hazelcast通过提供对开发者友好的Map、Queue、ExecutorService、Lock和JCache接口使分布式计算变得更加简单。例如,Map接口提供了内存中的键值存储,这在开发人员友好性和开发人员生产力方面提供了NoSQL的许多优点。

除了在内存中存储数据外,Hazelcast还提供了一组方便的api来访问集群中的cpu,以获得最大的处理速度。轻量化和简单易用是Hazelcast的设计目标。Hazelcast以Jar包的方式发布,因此除Java语言外Hazelcast没有任何依赖。Hazelcast可以轻松地内嵌已有的项目或应用中,并提供分布式数据结构和分布式计算工具。

Hazelcast 具有高可扩展性和高可用性(100%可用,从不失败)。分布式应用程序可以使用Hazelcast进行分布式缓存、同步、集群、处理、发布/订阅消息等。Hazelcast基于Java实现,并提供C/C++,.NET,REST,Python、Go和Node.js客户端。Hazelcast遵守内存缓存协议,可以内嵌到Hibernate框架,并且可以和任何现有的数据库系统一起使用.

如果你正在寻找基于内存的、高速的、可弹性扩展的、对开发者友好的NoSQL,Hazelcast是一个很棒的选择。

2、Hazelcast之IMDG

Hazelcast功能非常强大,本文主要讨论Hazelcast用于做分布式缓存。

Hazelcast做IMDG的官方文档如下:https://docs.hazelcast.com/imdg/4.2/

在这里插入图片描述
Hazelcast支持如下语言的API:Java、.NET、C++、Node.js、Python、Go。在此我们主要讨论JavaAPI。

下面的架构图中包含所有Hazelcast IMDG版本的功能:
在这里插入图片描述

3、数据分区

默认情况下,Hazelcast提供271个分区。当您启动只有一个成员的集群时,它拥有全部271个分区(即,它保留271个分区的主副本)。下图显示了具有单个成员的Hazelcast群集中的分区。
在这里插入图片描述
在这里插入图片描述

当添加更多成员时,Hazelcast会将一些主分区副本和备份分区副本逐个移动到新成员,从而使所有成员都是平等的和冗余的。得益于一致的哈希算法,只有最少量的分区被移动以横向扩展Hazelcast。下面是一个有四个成员的Hazelcast集群中的分区副本分布图:
在这里插入图片描述
也就是说,Hazelcast会对数据进行冗余,以实现它的高可用。一个节点挂掉之后,其分区中的数据一定会在集群中其它服务中找到。

Hazelcast通过分区表存储分区id和它们所属的集群成员的地址。这个表的目的是让集群中的所有成员(包括lite成员)都知道这个信息,确保每个成员都知道数据在哪里。

二、Hazelcast配置

1、maven坐标

直接引入jar包即可使用,非常方便。

<!-- https://mvnrepository.com/artifact/com.hazelcast/hazelcast -->
<dependency><groupId>com.hazelcast</groupId><artifactId>hazelcast</artifactId><version>5.3.6</version>
</dependency>

Gradle等其他坐标请移步:
https://mvnrepository.com/artifact/com.hazelcast/hazelcast/5.3.6

2、集群搭建

(1)组播自动搭建

Config cfg = new Config();
HazelcastInstance instance = Hazelcast.newHazelcastInstance(cfg);
Map<Integer, String> mapCustomers = instance.getMap("customers");
mapCustomers.put(1, "Joe");
mapCustomers.put(2, "Ali");
mapCustomers.put(3, "Avi");System.out.println("Customer with key 1: "+ mapCustomers.get(1));
System.out.println("Map Size:" + mapCustomers.size());Queue<String> queueCustomers = instance.getQueue("customers");
queueCustomers.offer("Tom");
queueCustomers.offer("Mary");
queueCustomers.offer("Jane");
System.out.println("First customer: " + queueCustomers.poll());
System.out.println("Second customer: "+ queueCustomers.peek());
System.out.println("Queue size: " + queueCustomers.size());

以上代码运行两次,就会形成一个集群:

Members {size:2, ver:2} [Member [127.0.0.1]:5701 - e40081de-056a-4ae5-8ffe-632caf8a6cf1 thisMember [127.0.0.1]:5702 - 93e82109-16bf-4b16-9c87-f4a6d0873080
]

在这里,您可以看到集群的大小(size)和成员列表版本(ver).当集群发生变化时,成员列表版本递增,例如,成员离开或加入集群。

默认情况下,Hazelcast通过组播的形式,在同一个网络中,自动发现其它成员。

3、客户端

下面的代码启动一个Hazelcast客户机,连接到我们的集群,并打印customers Map:

public class GettingStartedClient {public static void main( String[] args ) {ClientConfig clientConfig = new ClientConfig();HazelcastInstance client = HazelcastClient.newHazelcastClient( clientConfig );IMap map = client.getMap( "customers" );System.out.println( "Map Size:" + map.size() );}
}

Hazelcast其实有两种用法,一种是搭建一个独立的服务器集群,然后客户端连接上进行使用,就像redis那样。还有一种是,随着项目的启动而启动,此时就不需要客户端了,每一个java应用都作为Hazelcast集群服务的一员。

4、集群分组

通过指定集群名称,可以简单地对集群进行分离和分组。

可以通过编程方式定义集群配置(也可以使用xml和yaml进行配置https://docs.hazelcast.com/imdg/4.2/clusters/creating-clusters)。一个JVM可以托管多个Hazelcast实例。每个Hazelcast实例只能参与一个组。每个Hazelcast实例只加入自己的组,不与其他组交互:下面的代码示例创建三个单独的Hazelcast实例-h1属于production群集,而h2和h3属于development集群:

Config configProd = new Config();
configProd.setClusterName( "production" );Config configDev = new Config();
configDev.setClusterName( "development" );HazelcastInstance h1 = Hazelcast.newHazelcastInstance( configProd );
HazelcastInstance h2 = Hazelcast.newHazelcastInstance( configDev );
HazelcastInstance h3 = Hazelcast.newHazelcastInstance( configDev );

5、其他配置

Hazelcast用于在集群成员之间通信的端口。其默认值为5701,如果端口被占用会递增,可以进行配置:

Config config = new Config();
config.getNetworkConfig().setPort( 5701 ).setPortAutoIncrement( true ).setPortCount( 20 );

其他网络配置:Hazelcast提供自动检测、多播、TCP/IP、AWS、Kubernetes、Azure、GCP、Eureka等等。
https://docs.hazelcast.com/imdg/4.2/clusters/network-configuration

Hazelcast可以使用xml或者yaml进行特殊的额外配置,在项目中,新建一个hazelcast.yml或者hazelcast.xml,在里面进行配置,更多配置请移步官方文档!

三、Hazelcast分布式数据结构

1、IMap

IMap继承了ConcurrentMap,所以我们可以使用其put和get方法对数据进行写入和读取。其所有的操作都是线程安全的。

Hazelcast对IMap数据进行分区(上面讨论过)存储,并进行备份。

Config config = new Config();
config.setClusterName("CLUSTER_NAME");MapConfig mapConfig = new MapConfig();
mapConfig.setName("MY_MAP");
mapConfig.setBackupCount(1); // 同步备份,默认就是1
mapConfig.setAsyncBackupCount(1); // 异步备份,默认是0
mapConfig.setTimeToLiveSeconds(100); // 100秒过期时间
mapConfig.setMaxIdleSeconds(100); // 100秒活跃时间,最后一次对其进行读写时间 过期
mapConfig.setInMemoryFormat(InMemoryFormat.NATIVE); // 设置内存格式,二进制、反序列化、堆外内存。默认是二进制方式存储EvictionConfig evictionConfig = new EvictionConfig();
evictionConfig.setEvictionPolicy(EvictionPolicy.LRU); // LRU形式驱逐key
evictionConfig.setSize(1000); // 1000最大key
mapConfig.setEvictionConfig(evictionConfig);config.addMapConfig(mapConfig);
HazelcastInstance hazelcastInstance = Hazelcast.newHazelcastInstance(config);
IMap<String, String> map = hazelcastInstance.getMap("map");map.put( "key", "value", 50, TimeUnit.SECONDS); // 可以为单个key设置过期时间
map.setTtl("key", 50, TimeUnit.SECONDS ); // 单独设置过期时间
map.put( "key", "value", 50, TimeUnit.SECONDS, 40, TimeUnit.SECONDS );// 过期时间、活跃时间
map.put("key", "value");
map.get("key"); // 获取的是一个克隆,并不是原对象!
map.putIfAbsent("key", "value");
map.lock("key"); // 锁定键
map.evictAll(); // 清除锁定键之外的所有的键
map.clear(); // 清除// 可以实现分布式锁
map.lock("key");
map.unlock("key");// 乐观锁
map.replace("key", "old", "new");// 还可以为map添加拦截器,详见官方文档

2、IQueue:队列

IQueue继承了BlockingQueue,是分布式队列,Hazelcast分布式队列允许所有集群成员与之交互。使用Hazelcast分布式队列,您可以在一个集群成员中添加一个项目,并从另一个集群成员中删除它。

Config config = new Config();
config.setClusterName("CLUSTER_NAME");QueueConfig queueConfig = new QueueConfig();
queueConfig.setName("task"); // 设置队列名
queueConfig.setMaxSize(10); // 设置队列最大数量,超过最大数量,再添加将阻塞
queueConfig.setBackupCount(1); // 备份数量config.addQueueConfig(queueConfig);HazelcastInstance hazelcastInstance = Hazelcast.newHazelcastInstance(config);
IQueue<String> queue = hazelcastInstance.getQueue( "task" );
queue.put("MyTask"); // 放值
String task = queue.take(); // 取值boolean offered = queue.offer( "task", 10, TimeUnit.SECONDS );
task = queue.poll( 5, TimeUnit.SECONDS );
if ( task != null ) {//process task
}

3、MultiMap

HazelcastInstance hazelcastInstance = Hazelcast.newHazelcastInstance();
MultiMap<String, String> map = hazelcastInstance.getMultiMap("map");map.put("a", "1");
map.put("a", "2");
map.put("b", "3");
System.out.printf("PutMember:Done");for (String key: map.keySet()){Collection<String> values = map.get(key);System.out.printf("%s -> %s\n", key, values);
}

b → [3]
a → [2, 1]

4、ISet

ISet是的分布式并发实现java.util.Set。它具有以下特点:

  • ISet不允许重复元素。
  • ISet不保留元素的顺序。
  • ISet是一种非分区的数据结构:属于一个集合的所有数据都存在于该成员的一个分区中。
  • ISet的规模不能超过单台机器的容量。由于整个集合位于单个分区上,因此在单个集合上存储大量数据可能会造成内存压力。因此,您应该使用多个集合来存储大量数据。这样,所有的集分布在集群中,分担负载。
  • ISet的备份存储在集群中另一个成员的分区上,以便在主成员出现故障时数据不会丢失。
  • 所有项都被复制到本地成员,迭代在本地发生。
  • 在ISet中实现的equals方法使用对象的序列化字节版本,而不是java.util.HashSet.
HazelcastInstance hz = Hazelcast.newHazelcastInstance();
ISet<String> set = hz.getSet("set");
set.add("Tokyo");
set.add("Paris");
set.add("London");
set.add("New York");
System.out.println("Putting finished!");

5、IList

Hazelcast列表(IList)类似于Hazelcast的ISet,但它也允许重复元素。
除了允许重复元素之外,Hazelcast列表(IList)还保留了元素的顺序。
Hazelcast列表(IList)是一种非分区的数据结构,其中值和每个备份由它们自己的单个分区表示。
Hazelcast列表(IList)不能超出单台机器的容量。
所有项目都被复制到本地,迭代在本地进行。

HazelcastInstance hz = Hazelcast.newHazelcastInstance();
IList<String> list = hz.getList("list");
list.add("Tokyo");
list.add("Paris");
list.add("London");
list.add("New York");
System.out.println("Putting finished!");

6、其它

Haselcast还实现了Ringbuffer(环型缓冲器)、Topic(发布订阅)、FencedLock(分布式锁)、IAtomicLong(原子Long类型)、ISemaphore(分布式信号量)、IAtomicReference(分布式原子引用)、ICountDownLatch(分布式闭锁)、PNCounter(PN计数器)、FlakeIdGenerator (ID生成器)等等数据结构,但是由于Haselcast基于内存使用,可靠性并没有Redis高,所以还是得分场景进行使用。

参考资料

https://www.lidihuo.com/hazelcast/hazelcast-index.html
https://www.cnblogs.com/jdw5/p/12017044.html
https://xie.infoq.cn/article/9c7e32628b5839f8490b1f782

官方文档:https://docs.hazelcast.com/imdg/4.2/

这篇关于Hazelcast分布式内存网格(IMDG)基本使用,使用Hazelcast做分布式内存缓存的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/465174

相关文章

Java使用ANTLR4对Lua脚本语法校验详解

《Java使用ANTLR4对Lua脚本语法校验详解》ANTLR是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件,下面就跟随小编一起看看Java如何使用ANTLR4对Lua脚本... 目录什么是ANTLR?第一个例子ANTLR4 的工作流程Lua脚本语法校验准备一个Lua Gramm

Java Optional的使用技巧与最佳实践

《JavaOptional的使用技巧与最佳实践》在Java中,Optional是用于优雅处理null的容器类,其核心目标是显式提醒开发者处理空值场景,避免NullPointerExce... 目录一、Optional 的核心用途二、使用技巧与最佳实践三、常见误区与反模式四、替代方案与扩展五、总结在 Java

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析

Qt中QUndoView控件的具体使用

《Qt中QUndoView控件的具体使用》QUndoView是Qt框架中用于可视化显示QUndoStack内容的控件,本文主要介绍了Qt中QUndoView控件的具体使用,具有一定的参考价值,感兴趣的... 目录引言一、QUndoView 的用途二、工作原理三、 如何与 QUnDOStack 配合使用四、自

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指

使用Python构建一个Hexo博客发布工具

《使用Python构建一个Hexo博客发布工具》虽然Hexo的命令行工具非常强大,但对于日常的博客撰写和发布过程,我总觉得缺少一个直观的图形界面来简化操作,下面我们就来看看如何使用Python构建一个... 目录引言Hexo博客系统简介设计需求技术选择代码实现主框架界面设计核心功能实现1. 发布文章2. 加

在Spring Boot中浅尝内存泄漏的实战记录

《在SpringBoot中浅尝内存泄漏的实战记录》本文给大家分享在SpringBoot中浅尝内存泄漏的实战记录,结合实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录使用静态集合持有对象引用,阻止GC回收关键点:可执行代码:验证:1,运行程序(启动时添加JVM参数限制堆大小):2,访问 htt

MySQL 中的 LIMIT 语句及基本用法

《MySQL中的LIMIT语句及基本用法》LIMIT语句用于限制查询返回的行数,常用于分页查询或取部分数据,提高查询效率,:本文主要介绍MySQL中的LIMIT语句,需要的朋友可以参考下... 目录mysql 中的 LIMIT 语句1. LIMIT 语法2. LIMIT 基本用法(1) 获取前 N 行数据(

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

使用Python开发一个带EPUB转换功能的Markdown编辑器

《使用Python开发一个带EPUB转换功能的Markdown编辑器》Markdown因其简单易用和强大的格式支持,成为了写作者、开发者及内容创作者的首选格式,本文将通过Python开发一个Markd... 目录应用概览代码结构与核心组件1. 初始化与布局 (__init__)2. 工具栏 (setup_t