dist. system

Zookeeper 구조와 일관성에 대해

식피두 2020. 10. 26. 16:46

주키퍼 서버 구조

http://zookeeper.apache.org/doc/current/zookeeperOver.html

 

주키퍼 서비스를 구성하는 각 서버는 Request Processor를 제외한 각 컴포넌트의 복사본을 복제한다.

 

그림의 Replicated Database는 in-memory DB이며, 전체 데이터 트리를 가지고 있다.

- Update의 경우엔 복구를 위해 로깅 되며,

- Write의 경우엔 디스크에 serialized 되어 저장된다.

 

각 주키퍼 서버는 클라이언트에게 서비스를 할 수 있다.

- 클라이언트는 정확히 한 대의 서버로만 요청을 보내고,

- 요청 받은 서버는 로컬 레플리카 데이터베이스로 부터 요청을 서비스한다.

 

서비스의 상태를 변경하는 요청이 발생하는 경우 Agreement Protocol에 의해 처리 된다.

* Agreement Protocol ; 모든 쓰기 요청을 '리더'를 거친다. 리더를 제외한 나머지는 팔로워.
팔로워는 리더로 부터 message proposal을 받은 뒤 해당 메시지에 동의를 한다.

 

Messaging Layer에서는 리더가 죽는 경우, 리더를 대체하고, 팔로워가 리더와 싱크를 맞출 수 있게 해준다.

(그림에는 어디 위치해 있는지 나오지 않음)

 

주키퍼는 Atomic Messaging Protocol을 쓰는데,

이 레이어는 atomic해서 주키퍼는 로컬 레플리카들이 절대 서로 다르지 않다는 것을 보장할 수 있다.

리더가 쓰기 요청을 받았을 때, 쓰기 요청이 적용 됐을 때의 시스템 상태를 먼저 계산하고,

이러한 정보를 트랜잭션(새로운 상태를 캡쳐)으로 바꾼다.

 

주키퍼 구현

(한 대로 구성된 독립 모드는 생략)

앙상블 모드(클러스터 모드)는 replicated mode로 실행된다.

이 때 서버 개수는 반드시 홀수여야 한다.

 

주키퍼는 '복제'를 통해서 고가용성을 구현한다.

 

앙상블 내의 '과반수'의 컴퓨터가 살아 있을 때만 서비스 제공이 가능하다.

znode 트리에 대한 모든 업데이트가 '앙상블의 과반수 노드에 복제'되도록 보장한다는 것이 기본 원칙이다.

 

이 원칙을 구현하기 위해 'Zab Protocol'을 사용함.

1. 리더 선출 ; 앙상블 내의 서버들 끼리 리더를 선출하는 과정을 거치고, 나머지는 팔로워가 된다. 과반수 팔로워의 상태가 리더와 동기화가 되면 끝.

2. Atomic Broadcast ; 모든 쓰기 요청은 리더에게 전달되고, 리더는 팔로워에게 업데이트를 브로드캐스트한다. 과반수 노드에서 변경을 저장하면, 리더는 업데이트 연산을 커밋, 클라이언트는 성공 응답을 받는다. 변경 결과는 실패 혹은 성공 둘 중 하나.

 

만약 리더에 문제가 있는 경우, 남은 서버 중에서 새로운 리더를 선출(200마이크로 초)하여 다시 동작한다.

 

앙상블 내의 모든 서버는 업데이트 사항을 자신의 znode 트리의 메모리 복사본에 기록하기 전에 디스크에 저장한다.

반면, 읽기의 경우 메모리에서 검색하기 때문에 매우 빠르다.

 

일관성

리더와 팔로워가 있기 때문에, 팔로워는 자연스레 리더보다 갱신 작업이 느릴 수 밖에 없다.

 

znode 트리에 수행된 모든 업데이트 연산Zookeeper Transaction ID (zxid)가 부여된다.

- zxid z1이 z2 보다 작다면, z1 업데이트가 z2 이전에 발생한 것이다.

 

순차적 일관성 ; 클라이언트의 업데이트는 보낸 순서대로 적용된다. 어떤 클라이언트가 znode z의 값을 a로 업데이트 하고, 그 보다 늦게 z를 b로 업데이트한다면, b로 변경된 이후엔 클라이언트가 a 값을 절대 볼 수 없다.

 

원자성 ; 업데이트는 성공 혹은 실패 중 하나

 

단일 시스템 이미지 ; 클라이언트는 연결된 서버가 어딘가에 관계 없이, 같은 시스템을 바라본다. 서버에 문제가 발생해서 클라이언트가 다른 서버로 연결할 때, 실패한 서버를 이어받는 서버는 자신이 그 서버와 동일한 상태가 될 때 까지 클라이언트의 요청을 받지 않는다. 따라서 이전 서버보다 더 오래된 상태를 볼 수 없다.

 

지속성 ; 업데이트 연산이 성공하면 업데이트 내역은 저장되고 취소되지 않는다.

 

적시성 ; 클라이언트가 시스템을 볼 때, 지연이 발생하더라도 오래된 정보를 보여주진 않는다.

 

*성능상의 이유로 읽기는 주키퍼 서버의 메모리에서 이루어지고, 쓰기 순서를 전체 정렬하지 않기 때문에,

예를 들어, 클라이언트가 znode z의 값을 a에서 b로 업데이트 하고, 또 다른 클라이언트가 z를 읽을 때, z의 값이 b가 아닌 a일 수가 있다.

이런 상황을 막기위해 z에 대해 sync를 호출하면, 두 번째 클라이언트가 연결된 주키퍼서버에게 리더와 싱크를 맞추라고 명령할 수 있다.

'dist. system' 카테고리의 다른 글

Zookeeper를 이용한 분산 시스템 공용 데이터 관리  (1) 2020.11.03
Zookeeper 컨셉 정리  (0) 2020.10.26
Zookeeper 설치법 정리  (0) 2020.10.26
NATS streaming client example  (0) 2020.09.25
nats streaming server (NATS.io)  (2) 2020.09.02