Spring boot integrated hazelcast implements distributed cache

HBLOG
3 min readMar 13, 2024

--

1.Hazelcast introduction

Hazelcast is an open source in-memory database product from Hazelcast Company that provides elastic, scalable, high-performance iterative in-memory computing. And by providing many developer-friendly hybrid implementations for Java such as Map, Queue, ExecutorService, Lock and JCache.

Hazelcast Advantages

  • Hazelcast provides an open source version.
  • Hazelcast does not need to be installed, it is just a very small jar package.
  • Hazelcast provides out-of-the-box distributed data structures such as Map, Queue, MultiMap, Topic, Lock and Executor.
  • The non-traditional master-slave relationship in the Hazelcast cluster avoids single points of failure; all members in the cluster share cluster functions.
  • Hazelcast clusters provide elastic expansion, and new members can dynamically join the cluster when there is insufficient memory or the load is too high.
  • Members in the Hazelcast cluster share data caching and redundantly back up the data of other members to prevent data loss when a member goes offline.
  • Hazelcast provides an SPI interface to support user-defined distributed data structures.

Hazelcast applicable scenarios

  • Read and write data frequently
  • Highly available distributed cache is required
  • In-memory row NoSql storage
  • Elastic expansion in distributed environments

2.Code Project

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springboot-demo</artifactId>
<groupId>com.et</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>hazelcast</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-all</artifactId>
<version>4.0.2</version>
</dependency>
</dependencies>

</project>

hazelcast.xml

<hazelcast
xsi:schemaLocation="http://www.hazelcast.com/schema/config
http://www.hazelcast.com/schema/config/hazelcast-config-3.12.12.xsd"
xmlns="http://www.hazelcast.com/schema/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<instance-name>XML_Hazelcast_Instance</instance-name>
<network>
<join>
<multicast enabled="false">
</multicast>
<tcp-ip enabled="true">
<member>10.11.68.77</member>
</tcp-ip>
</join>
</network>
</hazelcast>

application.yaml

server:
port: 8090

entity

package com.et.hazelcast.entity;
import java.io.Serializable;
public class Employee implements Serializable{
private static final long serialVersionUID = 1L;
private int empId;
private String name;
private String department;
public Employee(Integer id, String name, String department) {
super();
this.empId = id;
this.name = name;
this.department = department;
}
public int getEmpId() {
return empId;
}
public void setEmpId(int empId) {
this.empId = empId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
@Override
public String toString() {
return "Employee [empId=" + empId + ", name=" + name + ", department=" + department + "]";
}
}

controller

package com.et.hazelcast.controller;
import com.et.hazelcast.entity.Employee;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
@Controller
public class HelloWorldController {
@RequestMapping("/hello")
@ResponseBody
public Map<String, Object> showHelloWorld(){
Map<String, Object> map = new HashMap<>();
map.put("msg", "HelloWorld");
return map;
}
@Cacheable(value = "employee")
@GetMapping("employee/{id}")
@ResponseBody
public Employee getSubscriber(@PathVariable("id") int id) throws
InterruptedException {
System.out.println("Finding employee information with id " + id + " ...");
return new Employee(id, "John Smith", "CS");
}
}

prepare three main class ,such as:

package com.et.hazelcast;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@EnableCaching
@SpringBootApplication
public class HazelcastNode1Starter {
public static void main(String[] args) {
SpringApplication.run(HazelcastNode1Starter.class, args);
}
}
package com.et.hazelcast;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@EnableCaching
@SpringBootApplication
public class HazelcastNode2Starter {
public static void main(String[] args) {
SpringApplication.run(HazelcastNode2Starter.class, args);
}
}
package com.et.hazelcast;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@EnableCaching
@SpringBootApplication
public class HazelcastNode3Starter {
public static void main(String[] args) {
SpringApplication.run(HazelcastNode3Starter.class, args);
}
}

java client

The most critical parameter in this code is to set the previously defined cluster-name “hazelcast-cluster”. This implements the call to map in the hazelcast cluster. During the above process, if any hazelcast node is closed, the data in the above cache will be available. Distribution is well implemented.

package com.et.hazelcast;
import com.hazelcast.client.HazelcastClient;
import com.hazelcast.client.config.ClientConfig;
import com.hazelcast.core.HazelcastInstance;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
@Slf4j
public class HazelcastGetStartClient {
public static void main(String[] args) {
ClientConfig clientConfig = new ClientConfig();
clientConfig.setClusterName("hazelcast-cluster");
HazelcastInstance instance = HazelcastClient.newHazelcastClient(clientConfig);
Map<Integer, String> clusterMap = instance.getMap("map");
}
}

Code repository

3.Test

  • modify port 8088,start HazelcastNode1Starter
  • modify port 8089,start HazelcastNode2Starter
  • modify port 8090,start HazelcastNode3Starter
Members {size:3, ver:5} [
Member [10.11.68.77]:5701 - 2faf3b2d-76f3-493c-be48-d19d25aeb581 this
Member [10.11.68.77]:5702 - 63caca7f-f8ba-4b0a-989a-6e86a199fb72
Member [10.11.68.77]:5703 - 3e9fa03c-72f4-4866-8904-73b908c4005d
]

Enter http://localhost:8088/employee/6 in the browser, store the data into hazelcast, and output the console

Finding employee information with id 6 ...

4.reference

--

--