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-08-09

[Graphics] Sprite는 무엇인가

 Sprite는 렌더링 파이프라인을 타지 않고 target(screen이든 FBO든)에 직접 그림을 그릴 수 있게 해주는 2D bitmap을 의미한다. Sprite에 그린 그림은 rendering pipeline을 타지 않기 때문에 transform 이나 다른 효과들과 독립적으로 화면에 보이게 된다.
 이러한 특성 때문에 3D게임에서 UI를 그릴 때 이용된다.

2014-08-08

Service Provider Interface란?

 Service Provider Interface(a.k.a. SPI)는 extensible한 코드를 작성하기 위해서 Java 진영에서 주로 쓰이는 방법이다.

 보통의 API들은 구현체의 Interface를 외부로 공개하여 구현체를 사용하는 주체가 자신의 환경에 맞게 사용한다.
 반면에 SPI는 사용자가 구현해야 할 Interface를 정의한다.
 SPI 사용자(보통은 driver vendor)가 자신의 환경에 맞는 구현체를 직접 정의하여 제공하면 SPI를 제공해준 service에서는 제공 받은 구현체를 불러다 사용하는 형태로 동작한다.

 대표적인 예로 Java Cryptography Extension가 있다.

2014-08-07

[MongoDB] Sharding (3) - shard key

 MongoDB는 auto sharding을 해주기 때문에 사용자가 어떤 shard에 저장할지 신경 쓰지 않아도 된다.
 그렇다면 어떤 document를 어떤 shard에 저장할지 어떻게 결정할까?

Shard Key

 MongoDB는 shard key를 이용하여 구분한다.
 별도로 지정하지 않았다면 shard key는 object ID(_id)이다. 하지만 해당 collection에 모든 document에 존재하는 field index 혹은 compound field index라면 shard key로 지정할 수 있다.
 하지만 compound index는 shard key로 지정할 수 없다.

Shard key의 제약 조건

 shard key에는 몇 가지 제약이 있다. 우선 shard key는 512 byte를 넘을 수 없다.
 하지만 이는 시스템적 제약조건이지 실제로 512 byte를 넘는 field를 shard key로 만들 일은 거의 생기지 않는다. (사실 512 byte가 넘는 index를 지정하는 일도 거의 생기지 않는다.)

 또한 한번 sharding한 collection에 shard key는 변경할 수 없다.
 만약 변경하고 싶다면 새 collection을 만들어 shard key를 설정하고 collection 전체를 복사해서 새로운 collection을 만들어야 한다.

 그다음 제약은 꽤 까다로운데 shard key로 지정된 field의 value는 변경할 수 없다. Update 때 document를 다른 shard로 옮겨야 할 일이 없도록 하기 위해서다. 변경할 일 없는 field들만을 shard key로 지정해야 한다.

 특별히 튜닝해야 할 일이 없다면 기본값인 object id를 shard key로 사용하는 것을 추천한다.

MongoDB Sharding

2014-08-06

[MongoDB] Sharding (2) - Primary shard

 MongoDB는 collection 별로 sharding을 할지 안 할지를 결정할 수 있다.
 이때 sharding되지 않은 collection들이 저장되는 shard를 "Primary Shard"라고 부른다.

 sharding되지 않은 data들이 들어 있기 때문에 이는 Single point of failure이다.

 혹시 primary shard인 머신을 down시켜야 한다면 movePrimary command로 다른 shard를 primary로 만들고 down시켜야 한다. movePrimary는 sharding되지 않은 collection들을 모두 copy해가기 때문에 무거운 작업이다. 될 수 있으면 movePrimary를 호출할 상황이 오지 않도록 노력해야 한다.

 별도로 primary shard를 정하지 않았다면, 가장 먼저 cluster에 붙은 shard가 primary shard가 된다.


 p.s. 솔직히 말하면 난 아직 primary shard를 사용해야 하는 경우를 보지 못했다.
 아마 내 MongoDB 튜닝 경험이 적어서 그럴 것이다.
 혹시 primary shard를 이용해야 했던 경험이 있다면 공유해주기 바란다.

MongoDB Sharding

2014-08-05

[MongoDB] Sharding (1) - Sharded cluster의 구성

Scale up과 Scale out

 한 머신이 처리하지 못할 정도로 부하가 들어왔을 때의 해결책을 크게 scale up과 scale out 두가지로 분류한다.
 Scale up은 머신 자체의 성능을 올리는 것으로 vertical scaling이라고 불린다.
 효과는 확실하지만, scale out보다 비용이 많이 든다.
 Scale out은 기존의 머신을 그대로 두고 새로운 머신을 추가하는 방식이다. 다른 말로는 horizontal scaling이라고 부른다.

 Sharding은 scale out의 일종으로 data를 여러 서버에 나눠서 저장하는 방식을 말한다.
 이때 data가 저장된 서버들을 shard라고 부르고 shard들을 포함한 몽고디비 환경을 sharded cluster라고 부른다.

Sharded cluster

 MongoDB의 sharded cluster는 크게 3가지 군으로 나뉜다.
  1. Shards
  2. Config Servers
  3. Query Routers

Shard

 Shard는 실제 data가 저장되는 곳이다. MongoDB는 보통 하나의 data를 세 군데의 shard에 저장하여 특정 shard가 Single point of failure(a.k.a. SPOF)가 되는 것을 막는다. Scaling을 위해 수를 줄이고 늘리고 하는 것이 이 shard이다.

Config Server

 Config server에는 shard된 data들의 metadata. 즉, 어떤 data가 어떤 shard들에 저장되어 있는지에 관한 정보가 저장되어 있다.
 하나의 Config server만을 이용할 수도 있지만 보통 3개의 Config server를 사용하여 특정 Config server가 SPOF가 되는 것을 막는다.

 Config server에 저장되는 정보는 two-phase commit으로 저장하여 consistency를 보장해준다.

 Config server는 shard와 달리 scaling의 대상이 아니다. 보통 3개의 Config Server를 실행하는 것을 기본으로 하고, 만약 하나의 config server라도 name 혹은 address가 변하면 모든 mongod(shard + config server)와 mongos(query router)를 재 시작하여야 한다. 혹시 address가 변경될 것을 대비하여 CNAME을 사용하는 것을 권장한다.

Query Router

 Query router는 Query router를 실행시키는 binary의 이름을 따서 mongos라고 부르기도 한다.
 Query router는 일종의 client interface이다. client는 data가 들어 있는 shard에게 직접 command를 날릴 수 없고, router를 통해서만 요청할 수 있다. Router는 client가 요청한 command를 어떤 shard에게 명령해야 하는지를 보고 필요한 shard에게 명령을 날리고 수행된 결과를 취합한다.
 Router가 어떤 shard에 어떤 data가 들어 있는지 알기 위해 항상 Config server에 물어보는 것은 아니다. Router는 Config server에 저장된 metadata를 cache 해둔다.

MongoDB Sharding