1. 샤딩이란
- 샤딩은 여러 장비에 걸쳐 데이터를 분할하는 과정을 일컬으며, 때때로 파티셔닝이라는 용어로도 불림
- 각 장비에 데이터의 서브셋을 넣음으로써, 수직 확장 없이도 더 많은 수의 덜 강력한 장비 (수평 확장)로 더 많은 데이터를 저장하고 보다 많은 부하를 처리할 수 있음
- 더 자주 접근하는 데이터를 성능이 더 좋은 하드웨어에 배치하거나, 지역에 따라 데이터셋을 분할해 주로 접근하는 애플리케이션 서버와 가까운 컬렉션에서 도큐먼트의 서브셋을 조회할 수 있음
- 수동 샤딩은 어떤 데이터베이스 소프트웨어를 사용하든 대부분 수행 가능
- 수동 샤딩을 사용하면 애플리케이션이 여러 데이터베이스 서버와 연결을 유지하며, 각 서버는 완전히 독립적
- 애플리케이션은 각기 다른 데이터를 다른 서버에 저장하고, 데이터를 조회하기 위해 적절한 서버에 쿼리 하는 과정을 관리함
- 해당 방식은 클러스터에 노드를 추가하거나 삭제할 때 혹은 데이터 분산이나 부하 패턴이 변화할 때는 유지하기 어려운 단점이 있음
- 몽고DB는 애플리케이션에서 구조를 추상화하고 시스템 관리를 간단하게 하는 자동 샤딩을 지원
- 운영 측면에서는, 몽고DB가 샤드에 걸쳐 데이터 분산을 자동화하므로 용량을 추가하거나 제거하기 쉬움
1.1 클러스터 구성 요소 이해하기
- 몽고DB 샤딩을 통해, 많은 샤드의 클러스터를 생성하고, 각 샤드에 데이터 서브셋을 넣음으로써 컬렉션을 쪼갤 수 있기 때문에 애플리케이션이 독립 실행형 서버나 복제 셋의 리소스 한계에 구애되지 않음
- 샤딩의 한 가지 목적은 N개의 샤드 클러스터가 하나의 장비처럼 보이게 하는 것
- 이러한 세부 사항을 애플리케이션으로부터 숨기기 위해, 샤드 앞단에 있는 mongos라는 라우팅 프로세스를 실행
- mongos에는 어떤 샤드가 어떤 데이터를 포함하는 알려주는 `컨텐츠 목차`가 있으며 애플리케이션은 라우터에 연결해 정상적으로 요청을 발행할 수 있음
- 라우터는 어떤 데이터가 어떤 샤드에 위치한지 알기 때문에 요청을 적절한 샤드들로 전달 가능
- 요청에 대한 응답이 있으면 라우터는 응답을 수집하고 통합해 애플리케이션으로 되돌려 보냄
2. 단일 장비 클러스터에서의 샤딩
- 단일 장비에 클러스터를 설정하기 위해서는 먼저 --nodb 및 --norc 옵션을 사용해 mongo 셸을 시작해야 함
$ mongo --nodb --norc
- 클러스터를 생성하려면 ShardingTest 클래스를 사용하며 직전에 시작한 mongo 셸에서 다음을 실행
- ShardingTest는 몽고DB 엔지니어링 내부용으로 설계된 클래스이므로 외부적으로 문서화되지 않았지만 몽고DB 서버와 함께 제공되므로 샤드 클러스터를 실험하는 가장 간단한 수단
- ShardingTest는 서버 테스트 셋을 지원하도록 설계됨
- 명령을 실행하면 ShardingTest가 자동으로 많은 작업을 수행
- 두 개의 샤드가 있는 새 클러스터를 생성하며, 각 샤드는 복제 셋
- 복제 프로토콜을 설정하는 데 필요한 옵션으로 복제 셋을 구성하고 각 노드를 시작함
- mongos를 시작해 전체 샤드의 요청을 관리하기 때문에 클라이언트는 독립형 mongod와 통신하듯 클러스터와 상호작용 가능
- 마지막으로 구성 서버에 대한 추가 복제 셋을 시작하는데, 해당 서버는 쿼리를 올바른 샤드로 전달하는 데 필요한 라우팅 테이블 정보를 유지
- ShardingTest가 클러스터 설정을 마치면 연결 가능한 실행 중인 프로세스는 10개
- 노드 3개로 구성된 복제 셋 2개
- 노드 3개로 구성된 구성 서버 복제 셋 1개
- mongos 1개
- 다음으로 mongos에 연결해야 하며 전체 클러스터가 현재 셸에 로그를 떠넘기므로 두 번째 터미널 창을 열어 다른 mongo 셸을 시작
$ mongo --nodb
- 해당 셸을 사용해 클러스터의 mongos에 연결하며 mongos는 포트 20009에서 실행함
> db = (new Mongo("localhost:20009")).getDB("accounts")
- mongo 셸의 프롬프트는 mongos에 연결됨을 반영하도록 변경돼야 함
- 셸은 클라이언트이고 mongos에 연결됨
- 이제 mongos에 요청을 전달할 수 있으며, mongos는 요청을 샤드로 라우팅
- 샤드의 정보는 전혀 몰라도 되며 샤드가 있는 한 요청을 mongos에 보내서 적절하게 전달하도록 허용할 수 있음
- sb.status()를 실행해 클러스터를 전체적으로 볼 수 있으며 샤드, 데이터베이스, 컬렉션에 대한 요약을 제공함
- accounts 데이터베이스에는 위에 표시된 것과 다른 프라이머리 샤드가 있을 수 있음
- 프라이머리 샤드는 `홈 베이스` 샤드이며, 각 데이터베이스마다 무작위로 선택되며 모든 데이터는 프라이머리 샤드에 있음
- 몽고DB는 데이터를 분산할 방법을 모르기 때문에 아직 데이터를 자동으로 분산할 수 없으므로 컬렉션마다 데이터를 어떻게 분산할지 알려야 함
- 특정 컬렉션을 샤딩하려면 먼저 컬렉션의 데이터베이스에서 샤딩을 활성화해야 하며 이를 위해 enableSharding 명령을 실행
- 이제 accoutns 데이터베이스에서 샤딩이 활성화돼 데이터베이스 내에서 컬렉션을 샤딩할 수 있음
> sh.enableSharding("accounts")
- 컬렉션을 샤딩할 때 샤드 키를 선택하는데, 이는 몽고DB가 데이터를 분할하는 데 사용하는 필드
- i.g. "username"에서 샤딩하도록 선택하면 몽고DB는 데이터를 사용자명 범위로 나눌 수 있음; "a1-steak-sauce" ~ "defcon"까지, "defcon1" ~ "howie1998"까지로 나눌 수 있음
- 샤드 키를 선택하는 것은 컬렉션 내 데이터 순서를 선택하는 것으로 생각할 수 있는데 이는 인덱싱과 유사한 개념이며, 컬렉션이 커질수록 샤드 키가 컬렉션에서 가장 중요한 인덱스가 됨
- 샤드 키를 생성하려면 필드에 인덱스를 생성해야 함
> db.users.createIndex({"username": 1})
- 이제 "username"으로 컬렉션을 샤딩할 수 있음
- 여기서는 별 다른 고민 없이 샤드 키를 선택했지만 실제 시스템에서는 키를 선택할 때 신중하게 고려해야 함
> sh.shardCollection("accounts.users", {"username": 1})
- 몇 분 기다렸다가 sh.status()를 다시 실행해 보면 이전보다 훨씬 많은 정보가 표시됨
- 컬렉션은 13개의 청크로 분할됐고, 각 청크는 데이터의 서브셋
- 청크는 샤드 키 범위에 따라 나열됨
- {"username": minValue} -->> {"username": maxValue}는 각 청크의 범위를 나타내며 샤드 키 값은 항상 $minKey와 $maxKey 사이에 있음
- 출력의 "on": shard 부분을 보면 청크가 샤드 간에 균등하게 분산됨을 알 수 있음
- "username"이 샤드 키이기 때문에 특정 사용자 이름에 쿼리를 호출하면 mongos가 쿼리를 올바른 샤드로 직접 라우팅 할 수 있음
- 샤드 키를 포함하여 단일 샤드나 샤드 서브셋으로 보낼 수 있는 쿼리를 타겟 쿼리라고 지칭
- 모든 데이터를 찾는 쿼리를 호출하면 두 샤드를 모두 방문하는 것을 확인 가능
- 일반적으로 쿼리에서 샤드 키를 사용하지 않으면 mongos는 모든 샤드에 쿼리를 보냄
- 모든 샤드로 보내야 하는 쿼리는 분산-수집 쿼리라고 지칭
- mongos는 쿼리를 모든 샤드로 분산한 다음 결과를 수집
- 셋을 종료하기 위해서는 원래 셸로 다시 전환한 뒤 엔터 키를 몇 번 눌러 명령행으로 돌아간 다음 st.stop()을 실행해 모든 서버를 완전히 종료하면 됨
> st.stop()
참고
몽고DB 완벽 가이드 3판 - 한빛미디어
반응형
'DB > 몽고DB 완벽 가이드 3판' 카테고리의 다른 글
[16장] 샤드 키 선정 (0) | 2025.05.16 |
---|---|
[15장] 샤딩 구성 (0) | 2025.05.16 |
[13장] 복제 셋 관리 (0) | 2025.04.26 |
[12장] 애플리케이션에서 복제 셋 연결 (0) | 2025.04.25 |
[11장] 복제 셋 구성 요소 (0) | 2025.04.24 |