Zookeeper 기반 리더 선출 알고리즘 구현
이번 글에서는 Zookeeper를 활용한 리더 선출 알고리즘 구현, Jar 패키징 후 실행 할 예정이고,
다음 실습에서 장애 감지 및 군집 효과(Herd Effect) 대응 전략과 재선출 알고리즘을 설명하겠습니다.
리더 선출 알고리즘 구현
Zookeeper는 분산 시스템의 코디네이터 역할을 수행할 수 있도록 강력한 API를 제공합니다. 그 중 하나가 리더 선출 메커니즘입니다. 핵심은 다음과 같습니다:
- 각 클러스터 노드는 Zookeeper에 /election이라는 부모 노드 아래에 EPHEMERAL_SEQUENTIAL 모드의 자식 노드를 등록합니다.
- Zookeeper는 이 자식 노드들에 대해 고유한 순번을 부여합니다.
- 노드 중 가장 작은 번호를 가진 노드가 리더가 됩니다.
Java 구현 예시 (LeaderElection.java)
String znodePrefix = "/election/c_";
String fullPath = zooKeeper.create(znodePrefix, new byte[]{}, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
this.currentZnodeName = fullPath.replace("/election/", "");
리더 여부 확인은 다음과 같이 진행됩니다:
List<String> children = zooKeeper.getChildren("/election", false);
Collections.sort(children);
if (children.get(0).equals(currentZnodeName)) {
System.out.println("I am the leader");
} else {
System.out.println("I am not the leader, " + children.get(0) + " is the leader");
}
전체코드
import org.apache.zookeeper.*;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
public class LeaderElection implements Watcher {
private static final String ZOOKEEPER_ADDRESS = "localhost:2181";
private static final int SESSION_TIMEOUT = 3000;
private static final String ELECTION_NAMESPACE = "/election";
private ZooKeeper zooKeeper;
private String currentZnodeName;
// NOTE - Don't forget to create the /election ZNode
public static void main(String[] arg) throws IOException, InterruptedException, KeeperException {
LeaderElection leaderElection = new LeaderElection();
leaderElection.connectToZookeeper();
leaderElection.volunteerForLeadership();
leaderElection.electLeader();
leaderElection.run();
leaderElection.close();
System.out.println("Disconnected from Zookeeper, exiting application");
}
public void volunteerForLeadership() throws KeeperException, InterruptedException {
String znodePrefix = ELECTION_NAMESPACE + "/c_";
String znodeFullPath = zooKeeper.create(znodePrefix, new byte[]{}, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println("znode name " + znodeFullPath);
this.currentZnodeName = znodeFullPath.replace("/election/", "");
}
public void electLeader() throws KeeperException, InterruptedException {
List<String> children = zooKeeper.getChildren(ELECTION_NAMESPACE, false);
Collections.sort(children);
String smallestChild = children.get(0);
if (smallestChild.equals(currentZnodeName)) {
System.out.println("I am the leader");
return;
}
System.out.println("I am not the leader, " + smallestChild + " is the leader");
}
public void connectToZookeeper() throws IOException {
this.zooKeeper = new ZooKeeper(ZOOKEEPER_ADDRESS, SESSION_TIMEOUT, this);
}
private void run() throws InterruptedException {
synchronized (zooKeeper) {
zooKeeper.wait();
}
}
private void close() throws InterruptedException {
this.zooKeeper.close();
}
@Override
public void process(WatchedEvent event) {
switch (event.getType()) {
case None:
if (event.getState() == Event.KeeperState.SyncConnected) {
System.out.println("Successfully connected to Zookeeper");
} else {
synchronized (zooKeeper) {
System.out.println("Disconnected from Zookeeper event");
zooKeeper.notifyAll();
}
}
}
}
}
2. 배포 가능한 Jar 패키징
리더 선출 프로그램은 다양한 서버에 배포될 수 있어야 하므로, 종속성을 모두 포함한 단일 .jar 파일로 패키징해야 합니다.
Maven을 사용하는 경우
pom.xml에 maven-assembly-plugin 추가:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
...
<configuration>
<archive>
<manifest>
<mainClass>LeaderElection</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
Gradle을 사용하는 경우
jar {
manifest {
attributes(
'Main-Class': application.mainClass
)
}
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
archiveClassifier.set('jar-with-dependencies')
}
빌드 명령:
- Maven: mvn clean package
- Gradle: ./gradlew jar
리더 선출 실행
주키퍼 서버 실행
# mac
zkServer start
# windows, linux
zkServer.sh start
터미널에서 주키퍼 CLI 실행:
# mac
zkCli
# windows, linux
zkCli.sh
/election Z노드 생성
create /election ""
각자 다른 터미널/노드에서 jar 파일 실행
java -jar leader-election-jar-with-dependencies.jar
실행 및 리더 선정 결과

반응형
'Server-side 개발 & 트러블 슈팅 > 🦍 ZooKeeper (주키퍼)' 카테고리의 다른 글
[ZooKeeper] 주키퍼 클라이언트 스레딩 모델과 Java API 연결하기 (0) | 2025.04.12 |
---|---|
[ZooKeeper] 주키퍼 설치 및 설정 가이드 (Mac OS, Windows, Linux) (0) | 2025.04.12 |
[ZooKeeper] 코디네이터(Coordinator)개념과 주키퍼 소개 (0) | 2025.04.12 |
댓글