MongoDB in Action을 바탕으로 정리한 내용입니다.
샤딩의 배경
최신 애플리케이션의 규모가 커짐에 따라 많은 데이터와 부하를 처리할 만큼 강력한 단일 시스템을 얻는 것이 점점 더 비용이 많이 들고, 일부의 경우 불가능해지고 있다. (컴퓨팅 성능에는 한계가 존재하기 때문)
문제에 대한 한 가지 해결책은 많은 컴퓨팅의 용량을 모으는 것이다.
샤딩이란?
샤딩(Sharding)은 데이터베이스를 작은 조각으로 분할하여 단일 머신이 모든 데이터를 저장하거나 전체 부하를 처리하지 않도록 하기 위해 고안된 것.
- 데이터의 크기가 커지고 애플리케이션이 더 많은 읽기 쓰기 처리량을 필요로 할 때 단일 서버로는 충분하지 않을 수 있다.
- 이러한 문제를 해결하기 위해 데이터베이스를 둘 이상의 서버에 분산시켜야 한다. MongoDB에서는 이를 수행하는 방법을 샤딩이라고 한다. (참고로 샤딩은 관리 및 성능 오버헤드가 존재하므로 샤딩을 하)
샤딩을 언제 하는 것이 좋을까?
일반적으로 샤딩은 저장소 분산과 부하 분산이라는 두 가지 주요한 목적을 가지고 있다.
(다만 샤딩이 모든 성능 문제를 해결하는 것은 아니며, 추가적인 관리 복잡성과 성능 오버 헤드를 발생시키므로, 애플리케이션에 필요할 경우인지 확인하는 절차가 필요하다.)
부하 분산
- 샤딩을 하는 가장 큰 이유 중 하나로 인덱스와 작업 데이터 세트를 RAM에 유지하는 것이 성능상 중요하다.
- 애플리케이션의 데이터 세트가 무한대로 계속 증가하면 해당 데이터가 더 이상 램에 들어가지 않게 된다.
샤드 클러스터 구성 요소
샤딩이 가능하도록 하기 위해서는 여러 구성 요소가 함께 작동해야 한다.
- 모든 것이 함께 기능적으로 작동할 때 샤드 클러스터라고 한다.
샤드 (애플리케이션 데이터의 저장소)
- 애플리케이션 데이터를 저장한다.
- 샤드 클러스터에서는 오직 mongos 라우터 또는 시스템 관리자만 샤드에 직접 연결해야 한다.
mongos (연산 라우터)
- 각 샤드에는 클러스터 데이터의 일부만 들어 있으므로 연산을 적절한 샤드로 라우팅해야 한다
- mongos 프로세스는 모든 읽기, 쓰기 및 명령을 해당 샤드에 보내는 라우터다.
- 이러한 방식으로 mongos는 클라이언트에게 클러스터와의 단일 접촉 지점을 제공하며, 이는 샤드 클러스터가 비 샤드 클러스터와 동일한 인터페이스를 제공할 수 있게 한다.
설정 서버
- mongos 프로세스는 지속성이 없으며 이는 클러스터를 적절하게 관리하는 데 필요한 메타 데이터를 영구적으로 저장해야 함을 뜻한다. (이것이 설정 서버의 역할)
- 메타 데이터에는 글로벌 클러스터의 설정사항과 각 데이터베이스 컬렉션, 각 범위의 데이터의 위치, 샤드 간 데이터 전송 내역을 가지고 있는 변동사항 로그이다.
- 설정 서버가 가지고 있는 메타 데이터는 클러스터가 제대로 동작하고 유지되기 위해 반드시 필요하다. 예를 들어 mongos 프로세스는 시작할 때마다 설정 서버로부터 메타데이터 복사본을 가지고 온다.
- mongos 프로세스가 쓰기를 할 때 2단계 커밋을 사용하는데, 이것을 통해 설정 서버들 사이의 일관성이 보장된다.
샤드 된 클러스터에서의 데이터 분산
도큐먼트
- MongoDB에서 가장 작은 데이터 단위
청크
- 필드의 값 별로 클러스터 된 도큐먼트 그룹.
- 샤드 키라는 필드 또는 필드 집합에 대한 값을 기반으로 하는 도큐먼트의 논리적 그룹.
컬렉션
- 데이터베이스 내에 명명된 그룹화된 도큐먼트
데이터베이스
- 도큐먼트 모음을 포함하며, 시스템의 최상위 레벨 그룹.
샤드 된 클러스터에 데이터를 분산시킬 수 있는 방법
- 컬렉션의 파티션 또는 청크 수준에서 컬렉션의 도큐먼트 자체가 분할되어 도큐먼트의 샤드 키라는 필드 또는 필드 집합의 값에 따라 여러 샤드로 분산된다.
MongoDB가 개별 도큐먼트가 아닌 청크 기반으로 분할하는 이유
- 도큐먼트 수준에서 분할하면 모든 단일 도큐먼트를 독립적으로 추적하여 설정 서버에 메타데이터를 저장해야 하는 문제가 존재.
컬렉션 내에서 샤딩하기
- 개별 컬렉션의 파티셔닝을 허용하기 위해 MongoDB는 미리 정의된 필드의 값 또는 샤드 키라는 필드 세트를 기반으로 도큐먼트의 논리적 그룹인 청크의 개념을 정의한다.
- MongoDB는 각 도큐먼트에서 샤드 키 정보를 사용하여 도큐먼트가 어떤 청크에 속하는지 확인한다.
- 코어에서 MongoDB 샤딩은 범위 기반이다. 즉 각 청크는 샤드의 범위를 나타낸다.
샤딩 클러스터 질의 및 인덱싱
애플리케이션 관점에서 보면 샤드 클러스터에 질의하는 것과 단일 mongod에 질의하는 것 사이에 차이가 없다.
- 두 경우 모두 질의 인터페이스와 결과 집합을 반복하는 과정은 같다.
- 하지만 이면에는 여러 가지 다른 점들이 있고 정확히 어떤 일들이 일어나고 있는지 이해하는 것이 중요하다.
쿼리 라우팅
샤드 클러스터에 질의한다고 할 때 질의에 대한 결과를 반환하기 위해 mongos는 얼마나 많은 샤드에 연결해야 할까?
- 샤드 키가 쿼리 실렉터에 있는지 여부에 달렸음을 을 수 있다.
- 설정 서버는 키의 범위를 샤드에 대해 매핑한 것을 갖고 있다.
- 샤드 키가 쿼리에 포함되어 있으면 mongos는 신속하게 청크 데이터를 참고해서 질의의 결괏값이 정확히 어느 샤드에 포함되어 있는지 결정한다. (타깃 쿼리라고 한다)
- 하지만 만일 샤드 키가 쿼리에 들어 있지 않다면, 쿼리 플래너는 질의를 완전히 수행하기 위해 모든 샤드를 다 방문해야 한다. (글로벌 쿼리 or 스캐터/개더 쿼리라고 한다)
샤드 클러스터에서 인덱싱 하기
- 쿼리가 얼마나 잘 타기팅이 되든 관계없이 결국 하나 이상의 샤드에서 실행해야 한다.
- 즉 샤드가 쿼리에 응답하는 속도가 느리면 클러스터도 느려질 것이다.
비 샤드 배포처럼 인덱싱은 성능을 최적화하는 중요한 부분이다.
- 각 샤드는 자신만의 인덱스를 가진다.
- 각 샤드에 대한 샤드 컬렉션은 같은 인덱스가 있어야 한다
- 샤드 컬렉션은 _id 필드와 샤드 키에 대해서만 고유 인덱스를 허용한다.
- 다른 필드에 대한 고유 인덱스는 금지되는데, 이것을 허용할 경우 샤드 간 통신이 필요하고 이는 MongoDB의 샤딩 기본 설계에 위배되는 것이기 때문이다.
샤드 키 선택
잘못 선택된 샤드 키로 인해 애플리케이션에서 샤드 클러스터가 제공하는 많은 장점들을 이용할 수 없게 된다.
- 극단적인 경우 삽입과 질의 성능까지도 심각하게 영향받을 수 있다.
- 샤드 키를 일단 선택하고 나면 변경할 수 없으므로 매우 신중하게 선택해야 한다.
핫스팟
- 일부 샤드 키는 모든 읽기 또는 쓰기가 단일 샤드에 있는 단일 청크에 향하는 상황을 만든다.
- 이로 인해 하나의 샤드는 완전히 주체할 수 없는 상황이 되고, 나머지는 유휴 상태가 된다.
- 대표 적으로 _id 필드를 샤드 키로 사용하는 경우, 해당 값이 엄격한 오름차순이다. (모든 새 도큐먼트에는 컬렉션의 다른 도큐먼트보다 큰 샤드 키가 있다.)
- 이로 인해 새로 생성된 모든 데이터가 동일한 청크에 속하게 될 수 있다. (100개의 샤드가 있더라도 나머지가 유휴 상태로 유지되는 동안 모든 기록은 하나의 샤드로 보내진다)
분할할 수 없는 청크 (낮은 수준의 타기팅)
- username 필드를 샤드 키로 사용하는 경우, 상대적으로 균형 잡힌 삽입을 이끌어 낸다.
- 하지만 세분화 수준이 너무 낮아서 하나의 청크가 경계 없이 자라는 상황에 처하게 될 수 있다. (예를 들어서 will이라는 이름을 가진 유저가 많이 있어 청크의 최대 크기인 64MB를 넘는 경우)
부족한 타깃팅
- 샤드 키가 포함된 쿼리만 올바른 샤드로 라우팅 될 수 있다.
이상적인 샤드 키
샤드 키를 선택할 때 고려할 사항
- 읽는 방법
- 쓰기가 얼마나 잘 분산되는지
- MongoDB가 컬렉션에서 청크를 얼마나 효율적으로 분할하고 마이그레이션 할 수 있는지
{username: 1, _id: 1}로 샤드 키를 잡는 경우 username 필드가 읽기에 종종 표시되고, username이 알파벳 전체에 고르게 분포되어 있어서 쓰기 밸런싱이 좋으며, 유일성을 가진 id 필드를 포함하고 있어 MongoDB가 청크를 분할할 만큼 충분히 세밀하므로 좋은 타깃팅이다.
Reference
'DBMS > MongoDB' 카테고리의 다른 글
[MongoDB] MongoDB ReplicaSet 설정 방법 (샤딩 X ) (0) | 2022.07.20 |
---|---|
[MongoDB] MongoDB 배포 형태 (0) | 2022.03.18 |
[MongoDB] MongoDB - 복제 (1) (0) | 2022.02.09 |