레이블이 zookeeper인 게시물을 표시합니다. 모든 게시물 표시
레이블이 zookeeper인 게시물을 표시합니다. 모든 게시물 표시

2014-08-11

[ZooKeeper] (2) zookeeper server는 어떠게 구성되는가?

ensemble

 테스트 환경이나 개발 환경에서는 stand-alone mode를 이용하여 한 대의 ZooKeeper 서버만을 실행하여 사용할 수 있지만, 이렇게 되면 ZooKeeper의 큰 장점인 availability를 크게 해치게 된다.
 그래서 실제 배포 환경에서는 보통 최소 3대의 ZooKeeper 서버를 cluster로 묶어서 배포하는 것이 일반적이다. 이때 ZooKeeper cluster를 ensemble이라고 부른다.

 같은 ZooKeeper ensemble에 포함된 서버는 모두 같은 data를 저장함으로써 특정 서버가 SPOF(Single Point Of Failure)가 되는 일을 막는다.
 그렇다면 분산 된 환경에서 모든 서버에 같은 data가 저장되는 것을 어떻게 보장해줄 수 있을까?

Leader

 ZooKeeper ensemble에는 외부에는 공개되지 않지만, 내부적으로 사용되는 leader가 있다.
 client는 ensemble에 포함된 어떤 서버에게도 query를 날릴 수 있다.
 서버는 query를 받으면 이 query를 ensemble의 leader에게 전달해 주고, leader가 모든 서버에 같은 data가 저장되는 것을 보장해 준다.

Two phase commit

 ZooKeeper는 모든 follower가 leader와 같은 data를 가지고 있는 것을 보장하기 위하여 간략화된 two phase commit을 사용한다.
 leader는 request에 대해서 follower에 해당하는 server들에게 propose message를 보낸다.

 propose message를 받은 follower는 해당 proposal에 대해서 local disk에 commit log를 저장하고 ack message를 보낸다.

 leader는 Follower로부터 받은 ack이 quorum(보통은 n/2 + 1이다.)을 넘으면 모든 Follower들에게 Commit을 날린다. Commit을 받으면 zookeeper는 commit log에 저장되어 있던 커밋을 실행하여 znode를 갱신한다.
 Follower들은 이후 자신에게 들어오는 read 요청에 대하여 request가 반영된 값을 보여준다. 이 순간 ZooKeeper 서버들은 각각 다른 값을 가지고 있을 수 있고, 이 때문에 ZooKeeper는 eventual consistency만을 보장한다고 한다.
http://zookeeper.apache.org/doc/r3.4.6/zookeeperInternals.html#sc_activeMessaging를 수정.
지금 document에 올라가 있는 그림은 틀렸다. 왼쪽 아래에 있는 commit의 방향이 반대로 되어 있다.

 일반적인 two phase coommit과는 다르게 propose에 대해서 agree/abort 하거나 commit/rollback을 하고 그 결과에 대해서 받는 과정이 없이 언제나 성공할 것으로 생각하고 ack을 기다린다.

 이때 leader는 보내는 모든 proposal에 대해 자신이 받은 순서대로 transaction id를 매겨서 처리하기 때문에 sequential consistency를 보장할 수 있다.

Leader election

 이렇게 leader를 통해서 consistency와 동기화가 보장된다면 leader가 또 다른 SPOF가 되는 것은 아닐까 하는 의문이 든다.
 ZooKeeper는 leader가 또 다른 SPOF가 되는 것을 막기 위하여, leader에 문제가 생겼을 때, 내부적으로 leader를 선출하는 mechanism을 가지고 있다.
 ZooKeeper의 leader election mechanism에 대해서는 다음에 설명하도록 하겠다.

2014-05-23

[ZooKeeper] (1) ZNode - ZooKeeper가 data를 저장하는 방법.

 지난번 글에서 ZooKeeper는 일종의 파일시스템을 제공해주어 이를 이용하여 semaphore나 mutex를 만들어 사용할 수 있다고 말했다.
 이때 ZooKeeper가 제공해주는 파일시스템에 저장되는 파일 하나하나를 znode라고 부른다.
 이번에는 znode에 대해서 자세히 설명해보도록 하겠다.

ZNode의 특징

hierarchy

 znode는 unix-like 시스템에서 쓰이는 file system처럼 node 간에 hierarchy namespace를 가지고, 이를 /(slash)를 이용하여 구분한다.
http://zookeeper.apache.org/doc/r3.3.2/zookeeperOver.html

 일반적인 file system과 다른 부분이 있다. ZooKeeper는 file과 directory의 구분이 없이 znode라는 것 하나만을 제공한다. 즉, directory에도 내용을 적을 수 있는, directory와 file 간의 구분이 없는 file system이라는 것이다.
 이는 znode의 큰 특징 중 하나이다. namespace hierarchy를 가지기 때문에 관련 있는 일들을 눈에 보이는 하나의 묶음으로 관리할 수 있으면서, directory가 내용을 가질 수 있게 함으로써(혹은 file 간에 hierarchy를 가진다고 하기도 한다. 원하는 표현으로 말하면 된다.) redundunt한 file을 생성해야 하는 것을 막을 수 있다.

size 제한

 ZooKeeper는 모든 data를 메모리에 저장한다.
 data를 메모리에 저장하기 때문에 jvm의 heap memory를 모든 znode를 올릴 수 있는 충분한 크기로 만들어야 한다.

 심지어 The disk is death to ZooKeeper.라고 말하면서, JVM이 heap memory를 swap 하여 하드에 저장하는 것을 피하도록 설정하는 것을 강요(?)하고 있다.

 data를 저장하는 보통의 파일 시스템이나 DBMS같은 경우 모든 data가 메모리에 올라갈 수 있는 크기로 제한된다는 제약조건은 말도 안 되는 조건이라고 할 것이다.
 하지만 znode의 목적은 data를 저장하는 것이 아니라, distributed 된 시스템 간의 조정을 하기 위함이다. 따라서 znode에는 조정에 필요한 meta data만을 저장하는 것이 기본적은 사용법이고, znode 자체도 크기가 작은 data를 저장할 것이라고 가정하고 구현되어 있기 때문에 각 znode의 크기는 1MB로 제한된다.


Recovery

 ZooKeeper설정파일을 봤으면 모든 data를 메모리에 올린다는 설명이 이상하게 느껴질 것이다. ZooKeeper의 설정파일에는 dataDir을 설정할 수 있게 되어 있다.
 그렇다면 dataDir은 무엇을 위한 것일까?

 dataDir은 zookeeper의 recovery를 위해 사용된다.
 ZooKeeper는 모든 data를 메모리에 들고 있기 때문에 서버가 종료되었다가 재 시작했을 때 자료를 보존할 수 없다. 이때 원래의 자료를 복구할 수 있는 것을 보장하기 위하여 ZooKeeper는 모든 transaction log를 dataDir에 저장한다.
 zookeeper를 재 시작하면 dataDir에서 transaction log를 읽어와서 모든 트랜잭션을 다시 실행하여 data를 복구한다.

 하지만 언제나 transaction log만을 이용하여 자료를 복구한다면, 자료를 복구하는데 시간이 걸리기도 하고, 무엇보다도 로그가 쌓일수록 복구할 자료의 양에 비해서 로그의 크기가 커지는 문제가 생긴다.
 이를 해결하기 위하여 ZooKeeper는 transaction log가 일정 이상이 되면, 지금까지 쌓인 transaction log로 만들 수 있는 data를 하드에 저장하고 transaction log를 지운다. 이 data를 snapshot이라고 하는데, 다음에 복구할 일이 생기면 이 snapshot에서부터 자료를 읽어온 뒤, 추가로 쌓인 transaction log만을 실행시켜 자료를 복구한다.

ZNode의 종류

 znode를 생성할 때 2종류의 옵션을 줄 수 있다.
 하나는 life cycle에 관한 option으로 persistent인지 ephemeral인지를 설정하는 것이고, 다른 하나는 znode의 uniqueness에 관한 option으로 sequential node인지 아닌지를 설정하는 것이다.

Persistent mode와 Ephemeral mode

 Persistent mode와 Ephemeral mode는 znode의 life cycle에 관한 설정으로, 모든 znode는 persistent 하거나 ephemeral 하지만 동시에 둘 다일 수는 없다.

 Persistent mode로 생성된 znode는 명시적으로 삭제될 때까지 지워지지 않는, 우리가 일반적으로 생각하는 file과 같다.
 그렇다면 Ephemeral mode는 어떻게 동작할까?
 Ephemeral mode로 생성된 znode는 ZooKeeper서버와 znode를 생성하도록 요청한 클라이언트 사이의 connection이 종료되면 자동으로 지워진다. ephemeral node의 이런 특성을 이용하여 lock이나 leader election을 구현하기도 한다.

Sequence mode

 Sequence mode는 znode의 uniqueness를 보장하기 위한 것이다.
 sequence mode로 만들어진 znode는 주어진 이름 뒤에 int 범위의 10개의 숫자가 postfix로 붙는다.
 이 숫자는 atomic 하게 증가하여 같은 이름으로 만든 node라고 해도 서로 다른 이름의 znode로 만들어준다.1)

 ephemeral mode와 persistent mode 둘 다 sequence node로 만들 수 있다.
 하지만 ephemeral mode와 sequence mode를 동시에 사용하여 node를 생성하는 것은 문제가 생길 수 있다. ZooKeeper서버와 ZooKeeper클라이언트는 비동기적으로 동작할 뿐 아니라 둘 사이의 connection은 빈번하게 끊길 수 있다.
 따라서 ephemeral + sequence node를 생성하라고 요청하였을 때 성공인지 실패인지 응답이 와야 하지만 실제로는 응답이 오지 않고 timeout이 발생할 수 있다.
 이때 성공인지 실패인지 알기 위해서는 node가 생성되었는지 확인해야 하는데 생성된 znode의 이름을 서버에서 결정하기 때문에 클라이언트는 znode의 생성 여부를 알 방법이 없다.
 ZooKeeper를 사용하기 쉽게 해주는 curator라는 라이브러리에서는 이를 위해 protect mode라는 것을 도입하였다. 이에 대해서는 다음 기회에 curator를 설명할 기회가 있으면 더 자세히 다루도록 하겠다.

ACL (Access Control List)

 znode는 ACL(Access control list)을 이용하여 각각의 znode에 접근권한을 설정할 수 있다.

 하지만 unix-like 파일시스템과 다르게 znode에는 user/group/others라는 개념이 존재하지 않는다. 대신
 하지만 차이가 있는
 ACL은 permission과 scheme
 이때 조심해야 하는 것이 있다. 각 znode의 ACL은 자기 자신의 ACL이고, 자식들에게 recursive 하게 적용되지 않는다는 것이다.
 즉, /some-node에 권한을 설정하였다고 해도 /some-node/child에는 권한이 설정되지 않는다는 것이다.

ACL Permissions

 ZooKeeper에서의 권한은 unix-like 파일시스템의 권한과 크게 다를 것은 없다.
 특정 권한들에 대해 allow flag가 있어서 이것이 어떻게 설정되는가에 따라서 해당 권한을 실행시킬 수 있는지가 결정된다.

 ZooKeeper에서 설정할 수 있는 ACL의 종류는 아래의 5가지이다.
  1. CREATE : 해당 znode의 자식 node를 만들 수 있는 권한.
  2. READ : 해당 znode에서 data를 읽고 와 그 자식들의 목록을 읽을 수 있는 권한.
  3. WRITE : 해당 znode에 값을 쓸 수 있는 권한.
  4. DELETE : 해당 znode의 자식들을 지울 수 있는 권한.
  5. ADMIN : 해당 znode에 권한을 설정할 수 있는 권한.
 unix-like file system과 다른 부분이 2가지 있다.
 첫 번째는 보통의 file system에는 없는 CREATE와 DELETE라는 권한이 존재하여 자식 node를 생성하고 삭제할 수 있는 권한이 있다는 것이다.
 unix-like file system에서 directory는 실제로는 자기 자식의 list를 가지고 있는 file이다.
 그래서 자식을 만들고 지우는 것은 부모 directory에 내용을 변경하는 것이고, 부모 directory에 쓰기 권한이 있는지가 자식을 만들고 지우는 권한이 된다.
 하지만 ZooKeeper에서는 모든 znode가 directory이기도 하고, file이기도 해서 자기 자신에 대한 쓰기 권한과 자식 node에 대한 생성/삭제 권한을 같이 쓸 수 없다.

Schemes

 ZooKeeper는 unix-like 시스템과 다르게 각 znode에 user/group/others라는 개념이 존재하지 않는다.
 대신 scheme이라는 것을 이용하여 권한을 구분하게 되어 있다.
 built in으로 제공되는 설정할 수 있는 scheme은 아래와 같이 4가지가 있다.

  1. WORLD
  2. AUTH
  3. DIGEST
  4. IP
 WORLD는 모든 요청에 대해 허락하는 것이고, AUTH는 authenticated된 session에서 들어오는 요청에 대해서만 허락하는 것이다.
 DIGEST는 username과 password를 보내서 이를 이용하여 만든 MD5 hash값이 같은 요청에 대해서만 처리하는 것이고, IP는 해당 IP에서의 요청만을 처리하도록 하는 것이다.

Stat

 ZNode는 node와 node의 data에 관한 여러 정보를 들고 있고, 이것을 stat이라고 부른다. stat이 가지는 정보는 다음과 같다.
  • czxid : znode를 생성한 트랜잭션의 id
  • mzxid : znode를 마지막으로 수정 트랜잭션의 id
  • ctime : znode가 생성됐을 때의 시스템 시간
  • mtime : znode가 마지막으로 변경되었을 때의 시스템 시간
  • version : znode가 변경된 횟수
  • cversion : znode의 자식 node를 수정한 횟수
  • aversion : ACL 정책을 수정한 횟수
  • ephemeralOwner : 임시 노드인지에 대한 flag
  • dataLength : data의 길이
  • numChildren : 자식 node의 수

1) 이 숫자의 범위는 int 범위로 최대 2147483647까지 올라가고 그보다 커지면 overflow가 발생한다. 문서에는 overflow가 발생했을 때 -2147483647가 된다고 적혀 있지만, 실제로는 -2147483648이다. 이는 단순한 실수로 보인다.

2014-05-13

[ZooKeeper] (0) zookeepr는 무엇인가?

 보통 분산 시스템을 구현할 때, 모든 시스템이 완전히 독립적으로 돌아가는 시스템이 아니라면, 시스템 간의 락, 설정 공유, 리더 선출, atomic 한 연산 등을 구현하는 것이 필요하지만, 분산환경에서 이를 구현하는 것은 매우 어려운 일이다.
 위의 기능들을 구현하기 어렵기 때문에 보통은 apache에서 제작한 zookeeper라는 시스템을 이용하여 분산 시스템 간의 동기화된 작업을 구현한다.
 zookeeper는 위의 기능들을 직접적으로 제공하지는 않지만 이런 일들을 하기 쉽게 해주는 환경을 제공한다.

 zookeepr가 제공해주는 환경이라는 것은 일종의 공유 가능한 file system을 제공해준다. 그러면 사용자가 file을 이용해서 semaphoremutex를 구현하듯이 zookeeper를 이용해서 semaphore나 mutex등을 구현하여 사용하면 된다.

 zookeeper는 분산환경에서의 다음과 같은 특징을 보장해준다.

ZooKeeper의 특징

Atomicity

 zookeeper에서 data의 저장은 원자성을 가진다.
 즉, node를 만들건 node에 data를 update하든 해당 request는 완벽하게 처리되거나 처리되지 않거나 하지 그 중간의 어중간한 상태는 존재하지 않는다.

Consistency

 분산환경에서, 특히나 data를 copy하여 여러 서버에 저장하면서 strong consistency를 보장하는 것은 매우 어려운 일다. 그래서 zookeeper에서는 아래의 2가지 consistency를 보장한다.


 첫 번째는 sequential consistency다.
 즉, 모든 요청은 들어온 순서대로 처리되고, 모든 서버가 요청을 같은 순서로 처리하는 것을 보장하는 것이다.


 두 번째는 eventual consistency다.
 strong consistency와 달리, 모든 요청에 대해 모든 서버가 완벽히 같은 순간에 같은 값을 갖지는 않지만 결국에는 같은 값을 가질 것을 보장하는 것이다.
 즉, 어떤 서버에서는 특정 request가 실행됐지만 다른 서버에서는 실행되지 않는 일은 없다는 것이다.

Durability

 zookeeper는 강한 durability를 보장한다.
 zookeeper에서 data 그 자체는 언제나 메모리에만 존재한다. 하지만 서버의 로컬디스크에 트랜잭션 로그와 스냅 샷을 저장하기 때문에 메모리가 날아가도 트랜잭션 로그와 스냅 샷을 이용하여 data를 복구할 수 있다.


 zookeeper가 어떻게 구현되어서 위의 특징들을 만족시키는지는 다음 기회에 설명하도록 하겠다