분산 시스템을 구축하면서 다양한 고민거리가 생겨났다.
분산된 시스템 간의 정보를 어떻게 공유할 것인가?
클러스터에 있는 서버들의 상태를 어떻게 체크할 것인가?
분산된 서버들 간에 동기화를 위해 잠금(Lock)을 어떻게 처리할 것인가?
이러한 점들을 해결하기 위해 Coodination Service인 Zookeeper가 탄생하였다.
Coodination Service 시스템
분산 환경에서 노드 간 정보공유, 잠금, 이벤트 등의 기능을 수행하며 노드간에 조정자 역할을 수행하는 서비스이다.
Coordination Service 시스템은 다음과 같은 기능을 제공한다.
Load-Balancing을 통해 여러개의 노드에 작업을 분산시켜주는 부하 분산 기능 제공
서버에서 처리된 결과를 다른 서버에 동기화 할 때 잠금(Lock)처리 수행
서버 장애 시 대기 서버가 기존 서버를 대신 처리할 수 있도록 장애 상황 판단 및 복구 기능 제공
이러한 기능을 제공하기 위해 몇가지 조건이 필요하다.
빠른 데이터 액세스 속도 → Zookeeper는 관리 데이터를 메모리상에 유지한다.
자체적인 장애에 대한 대응성 → Zookeeper는 자체적으로 클러스터링을 제공하여 장애에도 데이터 유실 없이 Fail Over/Fail Back이 가능하다.
Zookeeper 아키텍쳐
Zookeeper는 디렉토리 구조 기반의 tree 구조 데이터 저장소를 가진다.
znode라는 key-value 방식의 데이터 저장 객체를 제공한다. 이 객체에 데이터(상태 정보, 구성 정보, 위치 정보)를 넣고 빼는 기능을 제공한다.
Zookeeper Architecture
Zookeeper Node의 종류
Persistent Node
노드에 데이터를 저장하면 삭제하지 않는 이상 영구히 저장되는 노드이다.
트랜잭션 로그, 스냅샷, 상태 이미지 등을 유지한다.
Ephimeral Node
노드를 생성한 클라이언트의 세션이 연결되어 있을 경우만 유효하며, 연결이 끊어지는 순간 삭제된다.
이를 통해 클라이언트의 연결 상태를 파악할 수 있다.
Sequence Node
노드를 생성할 때 자동으로 일련 번호가 붙는 노드이다.
주로 분산 Lock을 구현하는데 사용된다.
Watcher
주키퍼 클라이언트가 특정 znode(모든 노드를 권장한다)에 watcher를 등록하면, 해당 znode가 변경되거나 실패했을 시, 클라이언트로 callback을 호출하게 된다. 이는 클라이언트에게 해당 znode가 변경되었음을 알려준다.
Replication
분산되어 구동되는 Zookeeper 서버들에게 모든 데이터가 복제되어 저장된다. 이를 통해 높은 일관성과 가용성(CAP 이론 중 CA)을 보장받는다.
서버들은 TCP를 통해 연결되어있으며 요청, 응답, watcher 이벤트, heart beat 등을 주고받는다. 기존 서버와의 연결이 끊어지면 곧바로 다른 서버에 연결된다.
Zookeeper 서버에 연결된 Client로부터 znode 수정이 일어나면, 해당 서버는 Zookeeper 서버들 사이에서 선출된 Leader 서버에게 수정된 정보를 보낸다. 그 후, Leader는 다른 모든 서버들에게 정보를 수정할것을 broadcast 하며, 과반수 이상의 서버가 정보를 복제하여 저장했을 시, 이를 commit하여 클라이언트에게 업데이터가 성공했다는 알림을 보낸다.
이 업데이트 행위는 성공 혹은 실패의 Atomicity(원자성)을 띄며 전체를 갱신하거나 전체를 받아 읽어들인다. 즉, append는 불가하다.
과반수 서버의 갯수(5개의 서버로 앙상블을 이루는 Zookeeper 시스템이라면, 3개)를 쿼럼(Quorum)이라 하며, 이러한 이유로 앙상블에선 보통 홀수개의 노드를 둔다.
Election
/election과 같은 임의의 path 하위에 가용하는 Zookeeper의 서버 목록을 Ephimerical-Sequential Node로 생성한다. Sequential한 특성을 가진 노드를 이용하여 낮은 번호의 노드를 Leader로 선출한다. 만약 Leader 서버에 장애가 발생하였다면, Leader 노드에 등록한 watcher가 바로 다음으로 낮은 번호를 가진 노드가 감지한다. 이 노드는 Backup node라 불리며, Leader에게 장애가 발생했을 시 Leader를 위임받는다. watcher를 등록하는 로직은 path 하위에 노드를 생성할 때 같이 진행하면 된다.
Zookeeper 활용 분야
클러스터 정보를 저장할 때 사용한다. Ephemeral Node는 Zookeeper 클라이언트와의 연결이 가능할 때만 유효한 특성을 지녀, 클러스터 에 연결되어 실행되고있는 노드 리스트만 유지할 수 있다.
클러스터 내의 각 서버정보를 저장할 때 사용한다. watcher을 이용해 설정 정보가 저장 또는 변경될 경우, 각 서버에서 바로 반영할 수 있게 한다.
Global Lock을 구현할 때 사용한다. 여러 개의 서버로 이루어진 분산 환경에서 특정 데이터 저장소나 공유 자원에 먼저 접근해있는 서버를 알릴 수 있다.