Hazelcast

- Hazelcast는 인메모리 데이터 그리드(In-Memory Data Grid, IMDG) 로, 분산 환경에서 데이터를 빠르게 공유하고 처리할 수 있게 도와주는 오픈소스 프레임워크다.
- 클러스터 기반으로 동작 (여러 JVM 인스턴스가 하나의 논리적 시스템처럼 동작)
- 분산 캐시, 세션 스토리지, Pub/Sub, 분산 Lock 등 다양한 기능 제공
- Java 애플리케이션에 쉽게 임베딩 가능
- 장점
- k8s 환경에서 배포하기 편리
- 병렬 처리로 redis 보다 성능적으로 우수한 측면이 있다.
- 피어 투 피어 구성으로 SPoF 가 없도록 설계되어있다.
- 단점
- 레퍼런스가 비교적 적은 편이다.
- 메모리를 많이 사용한다.
IMDG 관련 자료 : https://d2.naver.com/helloworld/106824
Hazelcast VS Redis

분산 시스템 환경에서 Hazelcast와 Redis 는 IMDG 라는 공통점이 있지만, 장단점은 다르다.
Hazelcast는 IMDG를 제공하기 위해 생겨났다면, Redis는 IMDB 기반이며 분산 환경을 위해 클러스터 기능으로 IMDG를 제공해준다. Hazelcast 는 JVM 멀티스레드 방식을 사용하여 CPU 코어를 병렬 활용하기 때문에 부하 환경에서 네트워크 처리에 효율적으로 활용할 수 있다는 장점이 있지만, 그만큼 힙 메모리를 많이 사용하므로 Full GC 로 인한 전체 애플리케이션 부하가 발생할수 있다.
| 구분 | Hazelcast | Redis |
| 기본 모델 | P2P 클러스터 (모든 노드 대등, 분산 파티션 관리) | Master-Replica 구조 |
| 확장 방식 | 노드 추가 시 자동 파티션 리밸런싱 | Cluster 모드에서만 샤딩 |
| 일관성 | AP (IMap 등) + CP Subsystem (Raft 합의) | 기본 AP, 일부 기능에서 강한 일관성 옵션 |
| 내구성 | 엔터프라이즈 Persistence로 로그/스냅샷 디스크 저장 가능 | RDB(AOF) 옵션으로 스냅샷/로그 기반 디스크 내구성 |
| 스레드 모델 | JVM 멀티스레드, 네트워크·분산연산 멀티스레드 처리 | 싱글스레드 이벤트 루프 (단, I/O 멀티스레드 옵션 있음) |
| 장애조치 | 멤버 장애 시 백업 파티션 승격 및 리밸런싱 | 슬레이브 노드 마스터로 승격 |
| 장점 | Java 기반, 분산락/시퀀스 강력 | 다양한 자료구조, 언어 지원 폭 넓음 |
| 단점 | JVM 오버헤드 발생, 운영 복잡, 레퍼런스 부족 | 일관성 한계, 클러스터 제약, 락 보장 어려움 |
분산 데이터 관리 방법
Hazelcast는 분산 데이터를 파티션 단위로 관리한다.
만약 A,B 각 서버에서 2대의 인스턴스를 띄운다면? 서버 단위로 메모리를 공유하는 것이 아니라 인스턴스 단위로 메모리를 공유한다. 각 인스턴스는 클러스터의 멤버로 참여해서 파티션을 배정받는다
결론적으로 공통 메모리 영역이 아닌 실제로는 네트워크 위에 있는 분산 메모리 맵으로, 물리적으로는 각 인스턴스 내 분산 저장되어있고, 논리적으로 hz.getMap("key") 실행 시 하나로 접근
파티션 생성
- 기본적으로 클러스터는 271개 파티션을 만들고 노드 단위로 분배된다.
- 4개의 인스턴스(A1, A2, B1, B2)가 파티션을 나눠 맡는다.
- 예시 ( A1 : 0 ~ 50 파티션, A2 : 51 ~ 100 , B1 : 101 ~ 180, B2 : 181 ~ 270)
Primary / Backup 파티션

- 파티션은 순서로 분포되지않고, 무작위로 분포된다. (검은색 주파티션, 파란색 백업 파티션)
- 각 파티션에는 Primary Owner와 Backup Owner가 있습니다.
- 예: key
"user:123"이 hash값에 따라 파티션 57에 들어가면 → Primary는 A1, Backup은 B2로 지정될 수 있어요. - 그러면 클러스터 전체에서
"user:123"을 조회할 때, Hazelcast는 자동으로 파티션 57의 Primary Owner(A1)로 라우팅한다.
Hazelcast 권장 아키텍처
- 운영 환경
- 서버 1대 = Hazelcast 인스턴스 1개 (자원 충돌 최소화로 안정적 성능 확보, 모니터링 단순화 )
- 클러스터 크기: 최소 3노드 이상 (쿼럼 확보용)
- 파티션 자동 분산 + 백업 1~2개 설정
- CPU/RAM 스펙에 맞춰 JVM Heap 크기 튜닝
- 개발 환경
- 서버 한 대에서 여러 인스턴스 띄워 멀티노드 시뮬레이션
CP subsystem
CPSubsystem은 CAP 이론에서 CP를 뜻한다. Hazelcast의 MAP, 캐시 등 대부분의 기능은 네트워크 분할이나 장애 상황에서 높은 가용성을 보장하기 위해 AP를 지향한다.
하지만 분산 락 / 원자 단위의 카운터 / 세마포어 등과 같이 동기화 문제에는 강한 일관성이 필요하므로, CPSubsystem을 별도로 두어 Raft 합의 알고리즘 기반의 강한 일관성을 제공한다.
강한 일관성을 보장하는 방법 ? 아래 IAtomicLong 으로 보자면, 하나의 CP 그룹에 영구 배치된다. 이 그룹은 Raft 합의를 수행하며 (리더1 + 팔로워 N) 으로 구성되어있다.
private long next(String key) {
// CP 그룹 영구 배치
IAtomicLong c = hz.getCPSubsystem().getAtomicLong(key);
// 해당 그룹의 리더 노드로 라우팅 (여러 노드에서 동시 요청해도 단일 순서로 처리)
return c.alterAndGet(x -> x + 1);
}
- FencedLock, ISemaphore, ICountDownLatch, IAtomicLong 등이 강한 일관성을 제공한다.
CAP 정리: 분산 시스템은 일관성(Consistency), 가용성(Availability), 파티션 내성(Partition tolerance) 중 동시에 셋을 모두 만족할 수 없고, 현실적으로 P는 반드시 필요하니 C 또는 A 중 하나를 더 우선해야한다.
Raft 합의 알고리즘: 일부 노드에 결함이 생기더라도 전체 시스템이 문제 없이 동작하도록 만들기 위해 고안된 합의 알고리즘으로, CP 그룹 내 내부 멤버에서 리더 1 + 팔로워 N 구조로 이루어져 있다. 쓰기 : 리더가 로그에 기록 후 과반수 (N +1 ) / 2 이상이 복제한 경우 커밋, 읽기 : 리더 기준으로 최신 커밋 상태를 선형화하여 보장 (일부 노드가 문제 생기더라도, 그 노드 전체 수가 과반수 (Quorum) 이하라면 전체가 다운될 위험은 없어진다.)
Pub /Sub
@Component
@Slf4j
public class LogTopicEvent<S> {
private final ITopic<String> logTopic;
public LogTopicEvent(HazelcastInstance hazelcastInstance) {
this.logTopic = hazelcastInstance.getTopic("log");
}
@PostConstruct
public void init() {
logTopic.addMessageListener(new MessageListener<String>() {
@Override
public void onMessage(Message<String> message) {
log.info("LOG RECEIVE : {}", message.getMessageObject());
}
});
}
}
private final HazelcastInstance hz;
private ITopic<String> logTopic;
private static final long MAX_VALUE = 9_999_999_999L;
@PostConstruct
void init() {
this.logTopic = hz.getTopic("log");
}
public CreateSeqResponse createSeq() {
String key = DateUtil.generateYyyyMmDd();
long seq = nextSeqByKeyV2(key);
logTopic.publish(new String("SEQ : " + seq));
return CreateSeqResponse.builder().seq(seq).build();
}
Multicast VS TCP-IP
Hazelcast는 여러 JVM 인스턴스가 네트워크 상에서 서로를 찾아야 클러스터를 형성한다.
노드 간의 서로 찾는 방법을 Discovery 라고하며, 이 과정에 멀티캐스트와 TCP-IP 방식이 있다.
Multicast 방식
- 같은 네트워크 서브넷 안에 있는 노드들이 멀티캐스트 주소(IP 범위) 로 "브로드캐스트" 메시지를 보냄.
- 노드 IP를 몰라도 자동으로 클러스터가 구성된다.
- 네트워크 환경에 따라 멀티캐스트가 차단될 수있다. (라우터, 방화벽, 클라우드 환경 등)
멀티캐스트는 네트워크 상에 특정 그룹에 속한 모든 호스트에게 동시에 패킷을 전달하는 방식으로,
클라우드 환경 (AWS, GCP, Azure), 라우터, 스위치, 방화벽 장비들은 기본적으로 멀티캐스트 트래픽을 제한하거나 차단하는 경우가 있을 수 있다. (불필요한 트래픽)
TCP-IP 방식
- 클러스터에 참여할 노드들의 IP 주소나 호스트명을 설정 파일에 미리 적어둔다.
- 새로운 노드가 실행되면, IP 리스트에 차례대로 연결을 시도한다.
- 멀티캐스트가 안 되는 환경(클라우드, 데이터센터, 방화벽 등)에서도 확실히 동작
int basePort = 5701;
List<String> members = IntStream.range(0, cpCount)
.mapToObj(i -> "127.0.0.1:" + (basePort + i))
.toList();
JoinConfig join = networkConfig.getJoin();
join.getAutoDetectionConfig().setEnabled(false);
join.getMulticastConfig().setEnabled(false);
join.getTcpIpConfig()
.setEnabled(true)
.setMembers(members);