본문 바로가기

분석/데이터베이스

[MongoDB] Sharding에 대해 알아보자

아키텍처

1. Config Server

shard cluster의 metadata를 저장하는 component이다.

metadata로 아래와 같은 collection을 저장하고 있다.

 

collections은 sharding이 적용되어있는 collection 목록을 관리한다.

_id database 이름과 collection 이름으로 구성된 namespace
lastmod collection이 마지막으로 변경된 시점
dropped collection의 삭제 유무
key collection의 sharding key
unique sharding key의 unique 유무

 

chunks는 sharding이 적용되어있는 collection의 chunk 정보를 관리한다.

chunk는 collection을 여러 조각으로 파티션하고 여러 shard 서버로 분산 저장하는데 데이터 조각을 chunk라고 한다.

_id chunk의 식별값
lastmod chunk가 마지막으로 변경된 시점
ns chunk가 포함된 collection의 namespace
min chunk가 가지는 값의 범위에서 시작값
max chunk가 가지는 값의 범위에서 종료값
shard chunk를 가지고 있는 shard의 이름

 

settings는 chunk balancing과 관련된 작업 설정을 관리한다.

 

changelog는 metadata의 변경을 유발한 event 이력을 관리한다.

chunk의 변화를 시간대별로 확인할 수 있다.

_id <hostname>-<timestamp>-<increment> 형식으로 이벤트를 식별
server event 대상 데이터를 가지고 있는 멤버의 hostname
time event가 발생한 시각
what 발생한 event의 종류
details event의 상세 내용을 document 형태로 저장

 

2. Router

client와 shard cluster 간 proxy 역할을 하는 component로

사용자의 쿼리 요청을 어떤 shard로 전달할지 정하고 각 shard로부터 받은 쿼리 결과를 병합해서 반환한다.

 

사용자가 router로 query 요청을 하면 다음과 같은 과정을 거친다.

1. query가 참조하는 collection의 chunk 정보를 config server로부터 가져와서 캐싱한다.

2. query 조건에 sharding key가 있으면 chunk 정보를 검색해서 해당 shard server로만 요청을 보낸다.

    sharding key가 없으면 모든 shard server로 요청을 보낸다.

3. query 결과를 shard server로부터 받아서 병합 후 사용자에게 반환한다.

 

Sharding

1. Chunk

샤딩 클러스터에서 데이터를 분산 저장하기 위한 논리적인 데이터 단위로

샤드키의 범위를 기준으로 묶인 document 묶음이다.

 

chunk의 기본 크기는 64MB로 데이터가 많아져서 64MB를 넘을 경우

chunk split을 통해 2개의 chunk로 나뉜다. 

 

2. Range Sharding

shard key 값을 기준으로 범위를 나누고 데이터가 어느 chunk에 포함될지 정하는 알고리즘이다.

 

범위 기반의 query에 효율적이지만 shard key가 순차적으로 증가하거나

특정 범위의 데이터가 많아질 경우 부하가 몰리는 문제가 발생할 수 있다. 

 

3. Hash Sharding

shard key 값의 hash 값을 계산하고 앞의 64bit만 잘라서 정수형으로 사용한다.

이 값을 기준으로 범위로 나누고 데이터가 어느 chunk에 포함될지 정하므로

일종의 range sharding이라고 볼 수도 있다.

 

hash 값은 균등하게 분포된 값을 가지므로 데이터를 골고루 분산시킬 수 있다.

하지만 shard key의 원본 값이 같으면 결과값도 같으므로 cardinality가 떨어지면 부하가 몰리는 문제를 피할 수 없다.

 

원본 값의 범위 검색을 할 때 특정 chunk를 한정시킬 수 없으므로

모든 shard server로 요청을 보내는 broadcast query가 실행된다.

 

4. Zone Sharding

zone sharding은 range sharding이나 hash sharding 처럼 독립적으로 사용할 수 없다.

shard key의 범위로만 chunk를 정하지 않고

shard key가 어느 지역에 속할지 결정하는 zone range도 같이 사용한다. 

 

zone sharding을 사용하려면 shard 별로 tag를 할당하고 shard key 범위별로 tag를 할당해야한다.

tag는 지역을 구분하는 용도 말고도 다른 용도로 사용될 수 있다. 

 

Chunk Balancing

1. Balancer

balancer는 cluster의 각 shard 간 chunk 갯수를 모니터링하다가 일정 수치 이상 차이가 생겨 불균형해지면

chunk를 옮겨서 부하의 균형을 맞춰주는 background process이다.

 

mongodb 3.2 버전까지는 balancer가 router에서 실행되었고 한 시점에 하나의 chunk만 이동이 가능했다.

mongodb 3.4 버전부터는 balancer가 config server에서 수행되도록 변경되고

한 시점에 여러개의 chunk의 이동이 가능해졌다.

 

2. Chunk Split

chunk에 document가 insert되거나 update될 때 해당 chunk split을 수행할지 결정하게 된다.

config server의 settings collection의 balancer에 chunk size가 설정되어있으며 기본값은 64MB이다.

64MB를 넘을 경우 chunk split이 수행된다.

 

chunk split은 다음과 같은 과정을 거친다.

split vector 단계에서는 해당 chunk가 split이 필요한지 확인하고 split을 수행할 위치를 반환한다.

split chunk 단계에서는 전 단계에서 반환된 위치를 기준으로 chunk를 split한다.

config server의 metadata에 대한 잠금을 획득하고 metadata를 변경한다.

변경이 완료되면 변경이력을 config server의 changelog collection에 저장한다.

 

3. Chunk Merge

chunk가 비어있는 경우 주위의 chunk와 병합된다.

병합이 수행되려면 병합하려는 chunk는 같은 shard에 존재해야하고 연속된 shard key 범위여야한다.

 

4. Chunk Migration

chunk가 이동되는 과정에서 다음과 같은 상태를 가진다.

CLONE from-shard의 chunk를 to-shard로 복사
CATCHUP CLONE 단계에서 from-shard로 유입되는 데이터를 to-shard로 복사
COMMIT 변경된 shard와 chunk 정보를 config server에 반영
DONE chunk 이동이 완료된 상태로 from-shard에서 이동된 chunk 데이터를 삭제
FAIL chunk 이동 실패