DB/몽고DB 완벽 가이드 3판

[17장] 샤딩 관리

꾸준함. 2025. 5. 17. 00:03

1. 현재 상태 확인

  • 데이터 위치, 샤드 구성 및 클러스터 실행 작업을 조회할 수 있는 몇 가지 보조자가 있음

 

1.1 sh.status()를 사용해 요약 정보 얻기

  • sh.status()는 샤드, 데이터베이스, 샤딩된 컬렉션의 개요를 제공
    • 청크의 개수가 적을 경우 어느 청크가 어디에 위치하는지도 출력
    • 청크의 개수가 많을 경우 단순히 컬렉션의 샤드 키와 각 샤드가 갖는 청크 개수를 보고

 

 

 

1.2 구성 정보 확인하기

  • 클러스터에 대한 모든 구성 정보는 구성 서버의 config 데이터베이스 내 컬렉션에 보관되며 셸 보조자를 사용하면 구성 정보를 더 읽기 쉽게 볼 수 있음
  • 클러스터에 대한 메타데이터를 조회하려면 언제든지 config 데이터베이스를 직접 쿼리 할 수 있음
  • 일반적으로 config 데이터베이스에 들어 있는 데이터는 직접 수정하면 안되지만 무언가를 수정하고 나면 모든 mongos 서버를 재시작해야 변경사항이 적용됨
  • config 데이터베이스에는 몇 가지 컬렉션이 있으며 해당 절에서는 각 컬렉션이 무엇을 포함하며 어떻게 사용되는지 다룸

 

config.shards

  • shards 컬렉션은 클러스터 내 모든 샤드를 추적하며 shards 컬렉션에 들어 있는 전형적인 도큐먼트는 다음처럼 보임
    • 샤드의 "_id"는 복제 셋의 이름에서 가져오기 때문에 클러스터 안에 있는 각 복제 셋의 이름은 고유해야 함
    • 복제 셋 구성을 변경하면 "host" 필드는 자동으로 변경됨

 

 

config.databases

  • databases 컬렉션은 클러스터가 알고 있는 모든 샤딩 및 비샤딩 데이터베이스를 추적함
    • enableSharding이 데이터베이스에서 실행된 적이 있으면 "partitioned"는 true가 됨
    • "primary"는 데이터베이스의 `홈 베이스`
    • 기본적으로 데이터베이스 내 새로운 컬렉션은 모두 데이터베이스의 프라이머리 샤드에 생성됨

 

 

config.collections

  • collections 컬렉션은 모든 샤딩된 컬렉션을 추적하며 전형적인 도큐먼트의 모습은 아래와 같으며 중요한 필드는 다음과 같음
    • "_id": 컬렉션의 네임스페이스
    • "key": 샤드 키 ("imdbId")
    • "unique": 샤드 키가 고유한 인덱스는 아님을 나타냄, 기본적으로 샤드 키는 고유하지 않음)

 

 

config.chunks

  • chunks 컬렉션은 모든 컬렉션 내 모든 청크의 기록을 보관
  • chunks 컬렉션 내 전형적인 도큐먼트는 아래처럼 보이며 가장 유용한 필드는 다음과 같음
    • "_id": 청크의 고유 식별자, 일반적으로 네임스페이스, 샤드 키, 하위 청크 범위
    • "ns": 청크가 위치한 컬렉션
    • "min": 청크 범위 내 최솟값
    • "max": 청크 낸 모든 값은 해당 값보다 작음
    • "shard": 청크가 위치하는 샤드
    • "lastEpoch": 컬렉션의 생성 시기를 지정하며, 컬렉션이 삭제되고 즉시 재생성될 때 동일한 컬렉션 이름에 대한 요청을 구별하는 데 사용
    • "lastmod": 청크 버전 관리를 추적하는 역할
      • i.g. "video.movies-imdbId_MinKey" 청크가 두 개의 청크로 분할됐다면, 이전의 단일 청크와 분할돼서 작아진 "video.movies-imdbId_MinKey" 청크를 구별하는 방법이 필요
      • 따라서 Timestamp 값의 첫 번째 구성 요소는 청크가 새 샤드로 마이그레이션 된 횟수를 반영하고 두 번째 구성 요소는 분할 수를 반영

 

 

config.changelog

  • changelog 컬렉션은 발생한 분할과 마이그레이션을 모두 기록하므로 클러스터가 무엇을 하고 있는지 추적하는 데 유용함
  • 분할은 아래와 같은 도큐먼트에 기록됨
    • "details"는 원본 도큐먼트가 어떻게 생겼으며 무엇으로 분할됐는지 알려줌
    • 출력 결과는 컬렉션의 첫 번째 청크 분할 모습이며 각각의 새 청크에서 "lastmod"의 두 번째 구성 요소가 갱신됐고, 값은 각각 Timestamp(9, 2)와 Timestamp(9, 3)

 

 

  • 마이그레이션은 더 복잡하며, 실제로 네 개로 나뉜 체인지로그 도큐먼트가 생김
    • 하나는 마이그레이션의 시작을 명시하고
    • 하나는 '원본' 샤드
    • 하나는 '목적지' 샤드
    • 나머지 하나는 마이그레이션에 대한 커밋 정보를 포함
    • 원본 샤드와 목적지 샤드에 대한 도큐먼트는 프로세스에서 단계별로 소요된 시간의 명세를 제공하며 이를 통해 마이그레이션에서 병목 현상을 일으키는 원인이 디스크인지, 네트워크 혹은 다른 무언가인지 추정할 수 있음

 

  • 아래는 원본 샤드에 의해 생성된 도큐먼트 예시
    • "details"에 나열된 각 단계에서 시간이 기록되며 "stepN of N" 메시지는 단계의 소요시간을 ms 단위로 보여줌

 

 

  • 원본 샤드가 mongos로부터 moveChunk 명령을 받으면 다음과 같은 작업을 수행함
    • 명령 매개변수를 확인
    • 구성 서버가 마이그레이션을 위해 분산된 락을 획득할 수 있는지 확인
    • 목적지 샤드에 접속 시도
    • 데이터를 복사하며 이는 'the critical section'으로 명시돼 기록됨
    • 목적지 샤드 및 구성 서버와 조정해 이동을 확정

 

  • 목적지와 원본 샤드는 "step 4 of 6"부터는 서로 통신이 가능한 상태여야 함
    • 샤드는 마이그레이션을 수행하기 위해 다른 샤드 및 구성 서버와 직접 통신함
    • 마지막 단계에서 원본 서버의 네트워크 연결이 비정상적이라면, 마이그레이션을 되돌리거나 계속 진행할 수 없는 상태가 되며 이럴 때는 mongod가 종료됨

 

  • 목적지 샤드의 changelog 도큐먼트는 원본 샤드의 changelog 도큐먼트와 비슷하지만 단계가 약간 다르며, 아래와 같은 모습

 

 

  • 목적지 샤드가 원본 샤드로부터 명령을 받으면 다음 작업을 수행함
    • 인덱스를 마이그레이션하는데 해당 샤드가 마이그레이션 된 컬ㄹ렉션에서 예전에 청크를 가진 적이 없다면 어떤 필드가 인덱싱됐는지 알아야 함, 해당 컬렉션으로부터 청크가 샤드에 마이그레이션된 것이 처음이 아니라면, 이는 no-op가 돼야 함
    • 청크 범위 안에 있는 모든 데이터를 삭제하며 마이그레이션에 실패한 데이터 혹은 복구 절차가 남아 있을 수도 있음
    • 청크 내 모든 도큐먼트를 목적지 샤드로 복사함
    • 복사한느 동안에 도큐먼트에 일어난 작업을 재실행
    • 목적지 샤드가 새로 마이그레이션된 데이터를 대부분의 서버로 복제하도록 대기
    • 청크와 메타데이터가 목적지 샤드에 위치한다고 바꿔서 마이그레이션을 확정지음

 

config.settings

  • 해당 컬렉션은 현재의 밸런서 설정과 청크 크기를 나타내는 도큐먼트를 포함하며 컬랙션 내 도큐먼트를 변경해서 밸런서를 켜고 끄거나 청크 크기를 변경할 수 있음
    • 컬렉션 안의 값을 변경할 때는 구성 서버에 직접 연결하지 말고 항상 mongos에 연결해야 함

 

2. 네트워크 연결 추적

 

2.1 연결 통계 정보 얻어오기

  • connPoolStats 명령은 현재 데이터베이스 인스턴스에서 샤드 클러스터나 복제 셋의 다른 멤버로 나가는 열린 연결에 대한 정보를 반환함
  • connPoolStats는 실행 중인 작업과 간섭을 피하기 위해 락을 사용하지 않기 때문에 정보를 수집할 때 개수와 실제 연결 개수와 약간의 차이가 생길 수 있음
  • 출력에서 각 필드는 다음을 나타냄
    • "totalAvailable": 현재 mongod/mongos 인스턴스에서 샤드 클러스터나 복제 셋의 다른 구성원으로 나가는 사용 가능한 총 발신 연결 수
    • "totalCreated": 현재 mongod/mongos 인스턴스가 샤드 클러스터나 복제 셋의 다른 구성원으로 생성한 총 발신 연결 수
    • "totalInUse": 현재 mongod/mongos 인스턴스에서 현재 사용 중인 샤드 클러스터나 복제 셋의 다른 구성원으로 나가는 총 연결 수
    • "totalRefreshing": 현재 mongod/mongos 인스턴스에서 현재 새로고침되는 샤드 클러스터나 복제 셋의 다른 구성원으로 나가는 총 발신 연결 수
    • "numClientConnections": 현재 mongod/mongos 인스턴스에서 샤드 클러스터나 복제 셋의 다른 구성원으로 나가는 활성 및 저장된 동기 연결 수를 나타내며 이는 totalAvailable, totalCreated, 그리고 totalInUse에서 보고된 연결의 서브셋
    • "numAsScopedConnection": 현재 mongod/mongos 인스턴스에서 샤드 클러스터나 복제 셋의 다른 구성원으로 나가는 활성 및 저장된 범위 동기 연결 수를 보고하며 이는 totalAvailable, totalCreated, 그리고 totalInUse에서 보고된 연결의 서브셋
    • "pools": 연결 풀별로 그룹화된 연결 통계 (사용 중/사용 가능/생성됨/새로고침)를 나타내며 mongod와 mongos에는 두 종류의 발신 연결 풀
    • "hosts": 호스트별로 그룹화된 연결 통계를 나타내며 현재 mongod/mongos 인스턴스와 샤드 클러스터나 복제 셋의 각 구성원 간의 연결에 대해 보고함

 

 

  • 샤드가 데이터를 이동하려고 다른 샤드에 연결할 때, connPoolStats 출력 결과에서 다른 샤드에 대한 연결을 확인할 수 있음
  • 이동이 발생하면 샤드는 이동할 부분에 있는 샤드의 건강 상태를 추적하려고 ReplicaSetMonitor를 설정함
  • mongod는 해당 모니터링 프로세스를 절대 죽이지 않으므로, 복제 셋의 로그에서 다른 복제 셋 멤버에 대한 메시지를 볼 수 있음
    • 이는 정상이며 사용자의 애플리케이션에 영향을 끼치지 않음

 

2.2 연결 개수 제한하기

  • 클라이언트가 mongos에 접속하면 mongos는 클라이언트의 요청을 전달하기 위해 적어도 하나의 샤드에 연결을 생성하므로 mongos에 들어온 각 클라이언트 연결은 mongos에서 샤드로 나가는 연결을 적어도 한 개는 만듦
  • mongos 프로세스가 여러 개이면 샤드가 다룰 수 있는 양보다 더 많은 연결을 생성할 수도 있음
  • mongos는 기본적으로 최대 6만 5536개의 연결을 허용하며, 각각 1만 개의 클라이언트 연결을 갖는 5개의 mongos 프로세스가 있다면 하나의 샤드에 5만 개의 연결 생성을 시도함
    • 이를 방지하려면 mongos 명령행 구성에서 --maxConns 옵션을 사용해 생성 가능한 연결 개수를 제한하면 됨

 

  • 다음 공식은 하나의 mongos에서 샤드가 다룰 수 있는 연결의 최대 수를 계산하는 데 사용함
    • maxConns = maxConnsPrimary - (numMembersPerReplicaSet * 3)
    • (other * 3) / numMongosProcesses

 

  • 공식의 각 부분을 분석해 보면 다음과 같음
    • maxConnsPrimary: 프라이머리의 최대 연결 수, mongos로부터의 연결로 샤드를 압도하지 않도록 일반적으로 2만으로 설정
    • (numMembersPerReplicaSet * 3): 프라이머리는 각 세컨더리에 연결을 하나씩 생성하고, 세컨더리는 프라이머리에 두 개의 연결을 생성해서 총 세 개의 연결이 있음
    • (other * 3): other는 모니터링이나 백업 에이전트와 같이 mongod에 접속하거나, 직접 셸에 연결하거나, 이동을 위해 다른 샤드로 연결하는 등 부수적인 역할을 하는 프로세스의 개수
    • numMongosProcesses: 샤드 클러스터에서 mongos의 총 개수

 

  • --maxConns는 단지 mongos가 연결을 이 이상 생성하지 않도록 함을 명심해야 함
    • 한계에 이를 때 특별히 도움 되는 동작을 하지는 않으며, 그저 요청을 막고 연결이 해제되기를 기다림
    • 그러므로 애플리케이션이 너무 많은 연결을 사용하지 못하게 해야 하며 특히 mongos 프로세스의 개수가 늘어날 때는 주의해야 함

 

  • 몽고DB 인스턴스가 순조롭게 종료되면 몽고DB는 중지하기 전에 모든 연결을 닫으며 인스턴스에 연결된 멤버는 즉시 해당 연결에 대해 소켓 오류를 받고 연결을 갱신함

 

3. 서버 관리

 

3.1 서버 추가

  • 언제든지 새로운 mongos 프로세스를 추가할 수 있음
    • mongos의 --configdb 옵션이 올바른 구성 서버 셋을 명시하는지 확인해야 하며 mongos에 클라이언트가 즉시 연결할 수 있어야 함
    • 새로운 샤드를 추가하려면 addShard 명령을 사용함

 

3.2 샤드의 서버 변경

  • 샤드 클러스터를 사용할 때, 각 샤드에서 서버를 변경할 수도 있음
  • 샤드의 멤버 구성을 변경하려면 샤드의 프라이머리에 직접 연결해 복제 셋을 재구성해야 함
    • 클러스터 구성은 변경 사항을 가져와서 config.shards를 자동으로 수정함
    • 수동으로 config.shards를 수정하지 않도록 주의 필요 (유일한 예외는 샤드 클러스터를 복제 셋이 아닌 독립 실행형 서버로 시작하는 케이스)

 

샤드를 독립 실행형 서버에서 복제 셋으로 변경하기

  • 가장 쉬운 방법은 빈 복제 셋 샤드를 새로 추가하고 독립 실행형 서버 샤드를 제거하는 방법
  • 마이그레이션은 데이터를 새로운 샤드로 옮기는 작업

 

3.3 샤드 제거

  • 주기적으로 샤드를 추가하거나 제거하면 시스템에 필요 이상으로 무리를 주기 때문에 일반적으로 샤드는 클러스터에서 제거되면 안 됨
    • 너무 많은 샤드를 추가한다면, 제거했다가 나중에 다시 추가하지 말고 샤드 안에서 시스템이 커지도록 하는 편이 나음
    • 하지만 필요하다면 샤드를 제거할 수 있음

 

  • 우선 밸런서가 켜진 것을 확인한 뒤 밸런서는 배출이라는 프로세스에서, 제거하려는 샤드의 모든 데이터를 다른 샤드로 이동하는 임무가 있음
    • 배출을 시작하려면 removeShard 명령을 실행
    • removeShard는 샤드명을 가져와서 샤드의 모든 청크를 다른 샤드로 배출함

 

 

  • 청크가 많거나 이동할 청크가 크면 배출이 오래 걸릴 수 있음
    • 점보 청크가 있으면, 청크를 옮기려면 청크 크기를 일시적으로 늘려야 할 수도 있음

 

  • removeShard는 원하는 만큼 여러 번 실행할 수 있음
  • 청크를 옮기려면 분할해야 할 수도 있으므로, 배출하는 동안 시스템에서 청크 개수가 증가할 수도 있음
  • 모든 청크가 옮겨졌으면, 제거된 샤드를 프라이머리로 하는 데이터베이스가 있다면 샤드를 제거하기 전에 먼저 제거해야 함
    • 샤드 클러스터의 각 데이터베이스에는 프라이머리 샤드가 있음
    • 제거하려는 샤드가 클러스터 데이터베이스 중 하나의 프라이머리이면 removeShard는 "dbsToMove" 필드에 데이터베이스를 나열함
    • 샤드 제거를 완료하려면 샤드에서 모든 데이터를 마이그레이션 한 후 데이터베이스를 새 샤드로 이동하거나, 데이터베이스를 삭제해야 함

 

 

  • 제거를 완료하려면 movePrimary 명령을 사용해 나열된 데이터베이스를 이동함

 

 

  • 데이터베이스를 모두 옮겼으면 removeShard를 한 번 더 실행함
    • 해당 과정은 꼭 필요하지는 않지만 처리가 완료됐는지 확인할 수 있음
    • 해당 샤드를 프라이머리로 사용하는 데이터베이스가 없으면 모든 청크 이동이 완료되자마자 응답을 받음

 

 

4. 데이터 밸런싱

 

4.1 밸런서

  • 대부분의 관리 작업에서는 밸런서를 끄는 작업이 선행되며 셸보조자를 사용하면 쉽게 끌 수 있음

 

> sh.setBalancerState(false)

 

  • 밸런서가 꺼진 상태에서는 새로운 밸런싱 작업이 시작되지 않지만 진행 중에 밸런서를 끄면 밸런싱 작업이 강제로 중지되지 않음
    • 일반적으로 마이그레이션은 쉽게 중지할 수 없기 때문에 config.locks 컬렉션을 확인해 밸런싱 작업이 아직 진행 중인지 확인해야 함

 

  • 밸런싱 작업은 아래 과정을 진행해야 하기 때문에 시스템에 부하를 줌
    • 목적지 샤드는 원본 샤드 청크 안에 있는 모든 도큐먼트를 쿼리하고 목적지 샤드에 입력해야 함
    • 그리고 원본 샤드는 도큐먼트를 삭제해야 함

 

  • 다음은 마이그레이션이 성능 문제를 일으킬 수 있는 두 가지 상황
    • 핫스팟 샤드 키를 사용하면 지속적으로 마이그레이션이 일어남, 시스템은 핫스팟 샤드에서 발생하는 데이터 흐름을 처리할 수 있어야 함
    • 새로운 샤드를 추가하면 밸런서가 샤드를 채우려고 시도할 때 지속적인 마이그레이션이 발생함

 

  • 마이그레이션이 애플리케이션 성능에 영향을 미친다고 판단되면 config.settings 컬렉션에서 밸런싱 작업할 시간대를 예약하는 것을 권장
    • 밸런싱 작업이 오후 1시에서 4시 사이에 실행되도록 실행되도록 하려면 아래와 같이 설정해야 함
    • 먼저 밸런서가 켜져 있는지 확인한 뒤 다음 시간대를 설정해야 함

 

 

  • 수동 밸런싱 작업을 자동 밸런서와 같이 사용하려 한다면 주의가 필요함
    • 자동 밸런서는 항상 셋의 현재 상태를 기준으로 무엇을 이동할지 결정하며, 셋의 이력을 고려하지 않음
    • i.g. 각각 500개의 청크를 갖는 shardA와 shardB가 있고 shardA가 많은 쓰기 요청을 받게 돼 밸런서를 끄고 가장 활발한 청크 30개를 shardB로 옮겼다고 가정했을 때 다시 밸런서를 켜면 청크 개수를 맞추려고 밸런서는 즉시 30개의 청크를 낚아채서 shardB에서 shardA로 이동함
      • 이를 방지하려면 밸런서를 시작하기 전에 활발하지 않은 청크 30개를 shardB에서 shardA로 옮기면 되며 샤드 간 불균형은 없고 밸런서는 청크를 그대로 둠
      • 또한 shardA의 청크를 30번 분할해 청크 개수를 맞추는 방법도 있음

 

  • 밸런서는 청크 개수를 단순히 지표로 이용함
  • 청크 이동은 마이그레이션이라고 불리며, 몽고DB가 클러스터 전체에서 데이터 균형을 조절하는 방법
    • 따라서 큰 청크가 조금 있는 샤드는 작은 청크가 많은 샤드로부터 이동할 목적지가 됨 

 

4.2 청크 크기 변경

  • 청크에는 도큐먼트가 0개부터 수백만 개까지 존재할 수 있음
  • 일반적으로 청크가 클수록 다른 샤드로 이동하는 데 시간이 많이 걸림
  • 기본적으로 청크 크기는 64MB이며, 이는 마이그레이션 용이성과 대규모 마이그레이션을 적절히 고려해 정한 수치
    • 때로는 64MB 청크로는 마이그레이션이 너무 오래 걸리는데 청크 크기를 줄이면 속도를 높일 수 있음
    • 셸을 통해서 mongos에 연결하고 config.settings 컬렉션을 다음처럼 변경할 수 있으며 예제는 청크 크기를 32MB로 변경

 

 

  • 자동 분할은 삽입이나 갱신을 할 때만 발생하기 때문에 청크 크기를 줄이고 나서 모든 청크가 새로운 크기로 분할되는 데는 시간이 걸림
    • 청크 크기를 늘리면 기존 청크는 새 크기에 이를 때까지 삽입이나 갱신을 통해서만 커짐

 

4.3 청크 이동

  • 몽고DB 샤딩 환경에서는 데이터를 효율적으로 분산 저장하기 위해 데이터가 ‘청크(chunk)’ 단위로 나눠짐
    • 각 청크는 특정 샤드에 저장되며, 시스템은 데이터 분포의 불균형을 감지하면 자동으로 또는 사용자의 명령에 의해 청크를 다른 샤드로 옮길 수 있으며 이러한 과정을 청크 이동이라고 부름

 

  • 청크 이동은 주로 다음과 같은 목적을 가짐
    • 데이터 분포의 균형 유지: 데이터가 특정 샤드에 몰릴 때, 청크를 다른 샤드로 옮겨 전체 클러스터의 저장 공간과 쓰기/읽기 부하를 고르게 분산함
    • 샤드 확장 시 데이터 재분배: 새로운 샤드가 추가되면 기존 데이터가 새로운 샤드로 자동 또는 수동으로 이동해 클러스터의 확장성을 보장

 

  • 몽고DB는 자동으로 청크를 이동시키지만, 필요에 따라 관리자가 직접 청크 이동을 명령할 수도 있으며 이를 위해 moveChunk 셸 명령을 사용
    • "video.movies": 청크를 이동할 컬렉션
    • {imdbId: 500000}: 이동하려는 청크가 포함하는 샤드 키 값
    • "shard02": 청크를 이동시킬 대상 샤드

 

> sh.moveChunk("video.movies", {imdbId: 500000}, "shard02")
{ "millis": 4079, "ok": 1 }

 

  • 청크 크기가 너무 크면 이동이 오래 걸리거나 실패할 수 있으므로, 적절한 청크 크기 유지가 중요
    • 이 경우 청크를 옮기기 전에 splitAt 명령을 사용해 수동으로 분할한 뒤 청크가 작은 조각으로 분할되고 나면 옮길 수 있음
    • 최대 청크 크기를 늘린 후 옮기리 수도 있지만, 큰 청크는 쪼갤 수 있을 때마다 쪼개야 함


 

4.4 점보 청크

  • 몽고DB의 샤딩 구조에서 데이터를 효율적으로 분산하기 위해 ‘청크(chunk)’라는 논리적 데이터 조각으로 데이터를 나눔
  • 각 청크는 기본적으로 샤드 키 범위에 따라 분리되며, 디폴트로 약 64MB 내외의 크기를 유지하도록 설계되어 있음
  • 그러나 특정 상황에서는 이 크기를 초과하는 점보 청크가 생길 수 있음
    • 점보 청크란 몽고DB가 자동 분할할 수 없을 만큼 커진 청크를 의미하며, 이로 인해 분산이나 이동이 제한되는 특별한 상태의 청크

 

  • 점보 청크가 발생하는 주요 원인은 다음과 같음
    • 샤드 키의 카디널리티가 낮을 때: 샤드 키로 사용된 필드의 값이 다양하지 않으면, 많은 데이터가 동일한 청크에 몰려 분할이 어려워짐
    • 문서 크기가 매우 클 때: 한 청크에 저장된 문서들이 비정상적으로 크면, 청크도 빨리 커짐
    • 분할 조건 불충족: 청크 분할은 샤드 키의 값을 기준으로만 이루어지는데, 만약 한 청크 내 모든 문서가 동일한 샤드 키 값을 가진다면 분할이 불가능해짐
    • 빠른 데이터 삽입: 데이터가 너무 빠르게 쌓여 밸런서와 분할 프로세스가 따라잡지 못할 때 점보 청크가 생기기도 함

 

  • 점보 청크의 문제점은 다음과 같음
    • 점보 청크는 자동으로 분할되지 않으므로, 데이터 분산의 불균형을 초래할 수 있음
    • 점보 청크는 자동 밸런서에 의해 다른 샤드로 이동되지 않습니다. 결과적으로 특정 샤드에 데이터와 부하가 집중될 수 있음
    • 클러스터의 확장성과 부하 분산이 저해됨

 

점보 청크를 분할하는 방법

  • 점보 청크는 자동 분할이 불가피할 때만 생김
  • 점보 플래그가 붙은 청크를 분산하려면 다음 방법을 사용할 수 있음
    • 점보 플래그 해제 후 이동 시도: 몽고DB 4.2 이상에서는 forceJumbo 옵션을 이용하여 점보 청크라도 강제로 이동시킬 수 있음, i.g. 해당 옵션을 사용하면 데이터가 아주 많더라도 해당 청크를 지정한 샤드로 강제로 이동시킴 (단, 이 과정에서 네트워크와 스토리지에 상당한 부하가 발생할 수 있으니 주의해야 함)
    • 수동 데이터 분할: 점보 청크 내부에서 샤드 키 값을 기준으로 수동으로 데이터를 삭제하거나, 업데이트해서 청크 분할이 가능해지도록 유도할 수 있고 이후 split 명령을 사용해 청크를 쪼갤 수 있음, 해당 명령을 통해 청크를 수동으로 분할한 뒤, 각 청크를 다른 샤드로 이동시켜 분산할 수 있음
    • 밸런서 재실행: 점보 청크가 분할되거나 데이터가 정리되고 나면, 밸런서가 정상적으로 작동해 자동으로 청크를 분산함

 

점보 청크를 예방하는 방법

  • 점보 청크는 설계 단계에서 적절히 예방하는 것이 가장 효과적이며 예방 방법은 다음과 같음
    • 적절한 샤드 키 선정: 샤드 키는 반드시 카디널리티가 높고, 데이터가 고르게 분포되는 필드를 선택해야 하며 너무 적거나 불균형한 값은 피해야 함
    • 문서 크기 관리: 한 문서의 크기가 지나치게 크지 않도록 설계하고, 큰 바이너리 데이터는 별도 스토리지(i.g. GridFS)에 저장하는 것이 좋음
    • 데이터 삽입 패턴 조정: 데이터가 집중적으로 삽입되는 패턴이 있다면, 시간, 지역, 사용자 등 다양한 기준을 샤드 키에 복합적으로 활용해 분산시키는 것이 효과적
    • 청크 크기 조정: 기본 청크 크기 (64MB)가 너무 크거나 작게 느껴진다면, 환경에 맞게 조정할 수 있는데 관리자가 상황에 맞게 chunksize 옵션을 변경할 수 있음
    • 정기적인 점검: 정기적으로 sh.status()나 db.collection.getShardDistribution()을 실행해 점보 청크 여부를 점검하고, 필요시 수동 분할이나 이동을 수행

 

4.5 구성 갱신

  • 때로는 mongos가 구성 서버에서 가져온 구성을 올바르게 갱신하지 않음
  • 예상치 않은 구성 값을 받거나, mongos가 최신이 아니거나, 거기 있다고 알고 있는 데이터를 찾을 수 없다면, flushRouterConfig 명령을 통해 수동으로 모든 캐시를 정리함

 

> db.adminCommand({"flushRouterConfig": 1})

 

 

  • flushRouterConfig가 작동하지 않는다면 모든 mongos 혹은 mongod 프로세스를 재시작해서 모든 캐시 데이터를 정리하는 것을 권장

 

참고

몽고DB 완벽 가이드 3판 - 한빛미디어

반응형

'DB > 몽고DB 완벽 가이드 3판' 카테고리의 다른 글

[16장] 샤드 키 선정  (0) 2025.05.16
[15장] 샤딩 구성  (0) 2025.05.16
[14장] 샤딩 소개  (0) 2025.05.16
[13장] 복제 셋 관리  (0) 2025.04.26
[12장] 애플리케이션에서 복제 셋 연결  (0) 2025.04.25