
분산된 서버들끼리 통신할 때 리소스를 공유하려다 보면 자원 점유 문제가 발생하는데, 이를 처리하기 위한 대표적인 해결책으로 리소스 락을 볼 수 있다. 이 리소스는 Lock,Unlock하는데도 관리해주는 시스템이 필요하다.
코디네이션 서비스는 분산 시스템 내에서 중요한 상태 정보나 설정 정보 등을 유지하기 때문에 코디네이션 시스템의 장애는 전체 시스템 장애로 이어지는 장애 전파 특성이 있다.
따라서 고가용성을 제공하는 것이 필수이다.

ZooKeeper는 분산 시스템을 위한 중앙화된 설정, 네이밍, 동기화, 상태 관리를 지원하는 오픈소스 코디네이션 서비스
- 즉, 여러 서버들이 “누가 리더인지?”, “누가 살아있는지”, “설정을 공유할지?”를 조율해주는 분산 시스템 관리자 역할을 한다.
- 어플리케이션의 정보를 중앙 집중화하고 구성관리, 그룹 관리 네이밍, 동기화 등의 서비스를 제공한다. 주키퍼의 데이터는 메모리에 저장되고, 영구 저장소에 스냅샷을 저장한다.
분산 시스템에서 시스템 간의 정보 공유, 상태 체크, 서버들 간의 동기화를 위한 락 등을 처리해주는 서비스

⇒ 그림에서 Server는 주키퍼, Client는 카프카
구성
Request Processor : Write 요청 처리
Zab (Zookeeper Atomic Broadcast Protocol) : Request Processor에서 처리한 요청을 트랜잭션을 생성하여 모든 서버에게 전파한다. [Leader-Propose] -> [Follower-Accept] -> [Leader-Commit] 단계로 구성
In-memory DB: Znode 정보 저장, 로컬 fs에 Replication을 구성
주키퍼 역시 분산 시스템의 일부분이기 때문에 동작을 멈춘다면 분산 시스템이 멈출수도 있다. 그래서 안정성을 확보하기 위해 클러스터(Cluster)로 구축한다.
상태 정보들은 주키퍼에 Znode 라고 불리는 곳에 Key - Value 형태로 저장
저장된 형태로 분산 어플리케이션들은 서로 데이터를 주고받음
주키퍼의 인터페이스

주키퍼가 상태 정보를 저장하는곳

→ 파일 시스템과 유사하게 노드간 계층구조(트리구조)를 가지며 각 노드를 ‘/’로 구분하나 file과 directory 구분이 없음
Leader가 새로운 트랜잭션을 수행하기 위해서는 자신을 포함하여 과반수 이상의 서버의 합의를 얻어야하는데, 과반수 합의를 위해 필요한 서버들
Ensemble을 구성하는 서버의 수가 5개라면, Quorum은 3개의 서버로 구성이 된다.
왜 쿼럼은 과반수로 이루어져야 하느냐?
첫번째, 리더 선출
두번째, 데이터의 일관성
과반수 이상의 데이터가 죽어버리면, 주키퍼는 동작을 멈춘다! 더이상 데이터를 쓸수가 없다.

Watcher
ZooKeeper는 znode에 변화를 감지할 수 있는 Watcher를 클라이언트가 설정할 수 있도록 한다. Watcher는 자신이 감시하고 있는 znode에 수정이 발생하였을 때, 클라이언트로 callback 호출을 전송하는 알림 기능을 제공한다.
주키퍼를 사용하는 클라이언트 A가 ZooKeeper에게 Watcher 등록을 요청한다.
주키퍼를 사용하는 클라이언트 B가 ZooKeeper에게 Znode를 수정한다고 말한다.
클라이언트 A에게 변경 이벤트를 전달한다.
Zookeeper는 DB처럼 데이터 저장하려는 목적이 아니다.
진짜 목적은 분산 시스템끼리 서로 "상태를 동기화"하고 "조정"하는 것.
- 누가 리더(Leader)가 될지 선출하기 (Leader Election)
- 분산 락(Distributed Lock) 걸기
- 설정 파일(Configuration)을 중앙 집중화해서 관리
- 서버들이 클러스터에 살아 있는지 확인(Heartbeat)
즉, Zookeeper는 다음 같은 걸 해주는 조정자(Coordinator) 역할.
주키퍼는 "중앙 심판" 역할. 카프카는 "선수들". 평소에는 선수들끼리 알아서 경기함. 심판이 없어도 당장은 진행됨. 근데 문제가 생기거나 판정이 필요한 순간 → 심판 없으면 경기 진행 불가.
- 이때 주키퍼가 죽어있으면 카프카가 요청을 처리 못 함
→ 결국 카프카 클러스터 장애로 연결될 수 있음