【Hazelcast学习】入门篇,以及和Spring Boot集成

本文是关于Hazelcast的入门,Hazelcast是分布式数据存储中间件(当然不仅仅是数据存储功能)。

关于Hazelcast的介绍,简书上其它小伙伴写的文章讲解的非常好:【Hazelcast系列一】Hazelcast 概览

1. 简单介绍

1.1 Hazelcast公司提供了两个版本的产品

关于两个版本的对比,戳:https://hazelcast.com/pricing/

  • Hazelcast open source edition(开源版本)
  • Hazelcast enterprise edition(收费版本,提供了更高级的功能)
1.2 Hazelcast最些年也更新了很多版本:

值得注意的是,3.x版本到5.x版本,包名也有改动。比如IMap在3.x里从属于包com.hazelcast.core.IMap下,而5.x在com.hazelcast.map.IMap下,关于如何升级,官网也有详细说明:5.1: Upgrading from IMDG 3.12.x

1.3 Hazelcast的拓扑结构

Hazelcast集群有两种部署模式:内嵌模式,客户端/服务器模式。

1.4 附上网站:

2. Hello World示例

  • 基于Java8
  • Hazelcast v5.1.1,使用的是内嵌模式
  • Spring Boot v2.5.7
2.1 依赖

Spring Boot及test的依赖:略
Hazelcast的主要依赖只有一个,即hazelcast-5.1.1.jar,引入这一个jar理论上就能使用Hazelcast了,而加入hazelcast-spring.jar主要是为了结合Spring使用,例如在xml配置中使用<hz:hazelcast id="instance">这样的命名空间。

        <dependency>
            <groupId>com.hazelcast</groupId>
            <artifactId>hazelcast</artifactId>
            <version>5.1.1</version>
        </dependency>

        <dependency>
            <groupId>com.hazelcast</groupId>
            <artifactId>hazelcast-spring</artifactId>
            <version>5.1.1</version>
            <exclusions>
                <exclusion>
                    <groupId>com.hazelcast</groupId>
                    <artifactId>hazelcast</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
2.2 配置

首先是application.yaml文件,主要是为了启动多个instance,而将server.port动态化。

server:
  port: ${PORT:5010}

其次是hazelcast.xml,我选择使用<hz:hazelcast id="instance">这样的配置,主要是从3.x升级过来的时候,对我来说使用起来更加方便。
关于配置的sample,在上述#1.4中有附上网站。

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:hz="http://www.hazelcast.com/schema/spring"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
                http://www.hazelcast.com/schema/spring
                http://www.hazelcast.com/schema/spring/hazelcast-spring.xsd">

    <hz:hazelcast id="instance">
        <hz:config>
            <hz:cluster-name>dev</hz:cluster-name>
            <hz:network port="5701" port-auto-increment="true">
                <hz:join>
                    <hz:multicast enabled="false" multicast-group="224.2.2.3" multicast-port="54327"/>
                    <hz:tcp-ip enabled="true">
                        <hz:members>localhost</hz:members>
                    </hz:tcp-ip>
                </hz:join>
            </hz:network>
        </hz:config>
    </hz:hazelcast>
</beans>

使用@ImportResource导入hazelcast.xml

@Configuration
@ImportResource(locations = "classpath:hazelcast.xml")
public class HazelcastConfig {
}
2.3 开始使用HazelcastInstance

在#2.2的配置后,就可以使用@Autowired来注入HazelcastInstance了,这个类是Hazelcast的核心类,通过它可以获得IMap, Iset, ITopic, IQueue等分布式结构的data,关于这块戳:https://docs.hazelcast.com/hazelcast/5.1/data-structures/distributed-data-structures

以下例子暴露了两个API:

  • /test/put?key={String}&value={String},往IMap中put数据。
  • /test/get?key={String},从IMap中get数据。
@RestController
public class TestController {
    @Autowired
    private HazelcastInstance hazelcastInstance;

    @GetMapping("test/put")
    public boolean put(String key, String value) {
        IMap iMap = hazelcastInstance.getMap("testMap");
        iMap.put(key, value);
        return true;
    }

    @GetMapping("test/get")
    public String get(String key) {
        IMap iMap = hazelcastInstance.getMap("testMap");
        return iMap.containsKey(key) ? iMap.get(key).toString() : null;
    }
}
2.4 测试

为了测试分布式,开启了两个服务,一个是5010端口,一个是5011端口,通过VM options动态传入端口号。

以下是5010的配置截图(5011略,基本差不多)。
配置5010端口

先启动端口为5010的程序,日志如下:

2022-05-14 22:52:41.369 INFO 95845 --- [ main] c.h.internal.cluster.ClusterService : [localhost]:5701 [dev] [5.1.1]
Members {size:1, ver:1} [
Member [localhost]:5701 - 699774f5-1982-400a-9033-6625d46e9d06 this
]
2022-05-14 22:52:41.386 INFO 95845 --- [ main] com.hazelcast.core.LifecycleService : [localhost]:5701 [dev] [5.1.1] [localhost]:5701 is STARTED

再启动端口为5011的程序,日志如下:
可以看到在5011启动之后Members变为2台:

2022-05-14 22:54:43.094 INFO 95894 --- [ration.thread-0] c.h.internal.cluster.ClusterService : [localhost]:5702 [dev] [5.1.1]
Members {size:2, ver:2} [
Member [localhost]:5701 - 699774f5-1982-400a-9033-6625d46e9d06
Member [localhost]:5702 - 7c902d8c-adbd-4b5e-8012-7c46ead9de36 this

]
2022-05-14 22:54:43.103 INFO 95894 --- [ main] com.hazelcast.core.LifecycleService : [localhost]:5702 [dev] [5.1.1] [localhost]:5702 is STARTED

开始测试:

3. 配置解释

3.1 cluster-name

关于#2.2配置里的一些参数说明。
5.1版本里的cluster-name,在3.x里就是group的配置,就是组成集成的名字,如果cluster-name不一样,就不能组成一个集群,比如:

instance-01配置:<hz:cluster-name>dev</hz:cluster-name>
日志:

Members {size:1, ver:1} [
Member [localhost]:5701 - 12d30f00-0fde-4416-8606-4b695a1fcc91 this
]
2022-05-14 23:03:51.941 INFO 96095 --- [ main] com.hazelcast.core.LifecycleService : [localhost]:5701 [dev] [5.1.1] [localhost]:5701 is STARTED

instance-02配置:<hz:cluster-name>dev-02</hz:cluster-name>
日志如下:可以看到dev-02和dev并不会组成同一个cluster集群,在日志中也会打印warn级别的日志,提示5701端口已经被占用了,从而使用5702节点。

Members {size:1, ver:1} [
Member [localhost]:5702 - 9d343cea-a482-4e21-b26f-695e54dcb164 this
]
2022-05-14 23:04:03.917 WARN 96101 --- [ main] com.hazelcast.instance.impl.Node : [localhost]:5702 [dev-02] [5.1.1] Config seed port is 5701 and cluster size is 1. Some of the ports seem occupied!
2022-05-14 23:04:03.926 INFO 96101 --- [ main] com.hazelcast.core.LifecycleService : [localhost]:5702 [dev-02] [5.1.1] [localhost]:5702 is STARTED

3.2 集群中节点发现机制

官网:https://docs.hazelcast.com/hazelcast/5.1/clusters/discovery-mechanisms
Hazelcast提供了很多种节点发现的方式:

  • Multicast(默认为true,<xs:complexType name="multicast"><xs:attribute name="enabled" type="xs:string" default="true"/></xs:complexType>
  • TCP
  • 其它:Eureka Cloud Discovery \ Zookeeper Cloud Discovery \ Hazelcast for Kubernetes \ Hazelcast for Tanzu VMware

用的比较多的应该是前两种,即Multicast多播和TCP(Unicast,即单播),关于这两者最大的区别应该是:TCP是单播的,因为它是面向链接的可靠传输协议,因为它总是需要确认报文。而Multicast多播是基于UDP的,它可以实现一对多。

关于Multicast和TCP/IP,可以参考以下文章:
~ Is multicast possible in tcp?
~ Multicast
~ 什么是 Multicast|组播

如果使用TCP作为发现机制,可以定义members,可以按ip区段定义,也可以逗号隔开等等,参考:https://docs.hazelcast.com/hazelcast/5.1/clusters/discovering-by-tcp

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容