(MongoDB 완벽 가이드) 샤드 키 선택

음영 키 선택

컬렉션을 분할할 때 하나 또는 두 개의 필드를 선택하여 분할 키라고 하는 데이터를 분할합니다. 컬렉션을 분할하면 샤드 키를 변경할 수 없기 때문에 올바른 것을 선택하는 것이 중요합니다. 좋은 샤드 키를 선택하려면 샤드 키가 애플리케이션의 요청과 워크로드를 분산하는 방식을 이해해야 합니다.

1) 얼마나 많은 샤드를 늘릴 것인가?

3개의 샤드 클러스터는 1000개의 샤드 클러스터보다 훨씬 더 유연합니다. 클러스터가 커짐에 따라 쿼리가 모든 샤드를 방문하지 않도록 거의 모든 쿼리에 샤드 키가 포함되어야 합니다.

2) 읽기 또는 쓰기 응답의 대기 시간을 줄이기 위해 샤딩합니까?

쓰기 응답 대기 시간을 줄이는 것은 일반적으로 지리적으로 더 가까운 위치나 더 나은 장비로 요청을 보내는 것과 관련됩니다.

3) 읽기 또는 쓰기 처리량을 늘리기 위해 샤딩을 사용합니까?

처리량은 클러스터가 동시에 처리할 수 있는 요청 수를 나타냅니다. 처리량을 늘리려면 더 많은 병렬 처리를 추가하고 클러스터 전체에 고르게 요청을 분산해야 합니다.

4) 시스템 리소스를 늘리기 위해 샤딩을 사용합니까?

데이터 기가바이트당 더 많은 메모리를 MongoDB에 제공하려고 합니까? 이 경우 작업 세트 크기를 가능한 한 작게 유지해야 합니다.

요약하면 샤드 키를 선택할 때 다음과 같은 요소를 고려해야 합니다.

  • 분할 키가 필요한 대상 쿼리를 제공합니까?
  • 샤드 키가 포기율이나 시스템 응답 대기 시간을 의도한 대로 변경합니까?
  • 작은 작업 세트가 필요한 경우 샤드 키가 제공합니까?

샤딩 이니셔티브

데이터를 분할할 때 가장 일반적인 용도는 오름차순, 임의 및 위치 키입니다. 다른 유형의 키도 사용할 수 있지만 대부분의 사용 사례는 둘 중 하나에 속합니다.

오름차순 샤드 키

오름차순 샤드 키는 일반적으로 시간이 지남에 따라 꾸준히 증가하는 모든 것입니다. B. “날짜” 필드 또는 ObjectId. 자동 증분 기본 키도 오름차순 샤드 키의 예입니다.

ObjectId를 사용하여 _id와 같은 오름차순 필드를 컬렉션으로 분할한다고 가정합니다. “_id” 이후의 샤딩은 “_id” 범위의 청크로 분할됩니다.

무작위로 분산된 샤드 키

오름차순 키와 달리 무작위로 분산된 샤드 키가 있습니다. 사용자 이름, 이메일 주소 및 UUID와 같은 레코드의 고유하지 않은 모든 키는 무작위로 배포된 샤드 키일 수 있습니다. 많은 데이터가 입력되면 데이터의 임의성은 입력이 모든 청크에 고르게 분포되어야 함을 의미합니다.

10,000개의 데이터를 입력하면 각 샤드가 거의 같은 속도로 증가하여 쓰기가 무작위화되기 때문에 가능한 이동 수가 제한됩니다. 유일한 단점은 MongoDB가 메모리 크기를 초과하는 데이터에 임의로 액세스하는 데 효율적이지 않다는 것입니다. 사용 가능한 메모리가 있거나 성능 저하에 신경쓰지 않는다면 임의 키가 로드 균형을 맞추는 좋은 방법입니다.

위치 기반 샤드 키

사용자 IP, 학위 및 위도, 주소 등이 될 수 있습니다. 반드시 물리적 위치 필드를 가리키는 것은 아니며 “위치”는 데이터를 그룹화하는 추상적인 방법입니다. 어쨌든 위치 기반 키는 특정 유사성을 가진 문서가 필드 기반 영역에 포함된다는 키입니다. 이는 데이터를 사용자와 가깝게 유지하거나 관련 데이터를 디스크에 저장하는 데 유용합니다. MongoDB는 영역 분할을 사용하여 이를 관리합니다.

IP 주소로 나누어진 문서 모음이 있다고 가정합니다.

  • 56.*.*.* :샤트0000
  • 17.*.*.* : 샤드0000, 샤드0002
  • 다른 IP는 괜찮습니다.
> sh.addShardToZone("shard0000", "USPS")
> sh.addShardToZone("shard0000", "Apple")
> sh.addShardToZone("shard0002", "Apple")

규칙을 만들어 봅시다.

> sh.updateZoneKeyRange("test.ips", {"ip" : "056.000.000.000"}, ...
    {"ip" : "057.000.000.000}, "USPS")

56.0.0.0 이상 57.0.0.0 미만의 모든 IP는 USPS 샤드 영역에 추가됩니다.

영역의 키 범위에 속하지 않는 청크는 정상적으로 이동되고 밸런서는 샤드 전체에 청크를 고르게 분배하려고 계속 시도합니다.

쉐드키 전략

해시 샤드 키

데이터를 최대한 빨리 로드할 수 있습니다. 해시 샤드 키는 모든 필드에 무작위로 배포됩니다.

(불리)

해시 샤드 키를 사용하여 범위 쿼리를 수행할 수 없습니다. 해시 샤드 키는 범위 쿼리를 수행하지 않을 때 유용합니다.

해시된 샤드 키를 사용하면 문서 입력을 시작할 때 컬렉션에 문서가 없더라도 처음부터 샤드 전체에 쓰기가 고르게 분산됩니다. 일반적으로 다른 샤드에 쓰기를 시작하려면 청크가 커지고 분할되고 이동할 때까지 기다려야 합니다. 반면에 이 자동 프로세스로 인해 모든 샤드에는 즉시 청크 범위가 있습니다.

해시 샤드 키는 고유 옵션을 사용할 수 없으며 다른 샤드 키와 같은 배열 필드를 사용할 수 없으며 부동 소수점 값은 해싱 전에 잘린 정수입니다. (1 = 1.99999)

소방 호스 전략

다른 서버보다 더 강력한 서버가 있는 경우 더 많은 부하를 처리하도록 할 수 있습니다.

(예)

샤드가 다른 머신 부하의 10배를 처리할 수 있는 경우 모든 입력을 더 강력한 샤드로 이동하도록 강제할 수 있으며 밸런서는 이전 청크를 다른 샤드로 보낼 수 있습니다. 이렇게 하면 쓰기 응답 대기 시간이 줄어듭니다.

이 전략에서는 최상위 청크를 더 강력한 샤드에 고정해야 합니다. 먼저 이 샤드를 구역화합니다.

> sh.addShardToZone("<shard-name>", "10x")

이제 오름차순 키의 현재 값에서 무한대로 샤드를 잠급니다. 그러면 모든 새 쓰기가 해당 샤드로 이동합니다.

> sh.updateZoneKeyRange("<dbName.collName>", {"_id" : ObjectId()}, ...
   {"_id" : MaxKey}, "10x")

이제 모든 입력이 이 마지막 청크로 전달되고 항상 영역 10x의 샤드에 배치됩니다.

샤드 키 규칙 및 정책

분할 키를 선택하기 전에 알아야 할 몇 가지 실질적인 제한 사항이 있습니다.

샤드 키를 찾고 생성하는 것은 개념적으로 인덱싱과 유사합니다.

샤드 키 제한

분할 키는 배열이 될 수 없습니다.

값이 배열인 키가 있는 경우 sh.shardCollections()가 실패하고 해당 필드에 배열이 허용되지 않습니다. 또한 위치 인덱스별로 조각화할 수 없습니다. 해시 인덱스는 샤드 키로 사용할 수 있습니다.

샤드 키 카디널리티

샤드 키가 빠르게 증가하는지 꾸준히 증가하는지에 관계없이 값이 고르게 입력되는 키를 선택해야 합니다. 인덱스와 마찬가지로 샤딩은 카디널리티가 높은 필드에서 더 효율적으로 작동합니다.

(예)

“DEBUG”, “WARN” 또는 “ERROR”의 logLevel 키만 있는 경우 MongoDB는 데이터를 3개 이상의 블록으로 분할하는 것을 허용하지 않습니다. 거의 변경되지 않는 키를 사용하려면 logLevel 및 타임스탬프와 같은 보다 고유한 키가 있는 복합 샤드 키를 생성하여 사용합니다.

키 조합 카디널리티가 높으면 좋습니다.

데이터 배포 제어

MongoDB는 컬렉션을 클러스터의 모든 샤드에 고르게 분산하므로 동일한 속성으로 데이터를 저장할 때 잘 작동합니다. 그러나 다른 데이터보다 “가치가 덜한” 로그 모음이 있는 경우 값비싼 서버에서 저장 공간을 차지하는 것을 원하지 않습니다. MongoDB에서 특정 데이터를 넣을 위치에 대한 구체적인 지침을 제공할 수 있습니다.

셸에서 다음을 실행합니다.

> sh.addShardToZone("shard0000", "high")
> // shard0001 - 영역없음
> // shard0002 - 영역없음
> // shard0003 - 영역없음
> sh.addShardToZone("shard0004", "low")
> sh.addShardToZone("shard0005", "low")

이제 다른 컬렉션을 다른 샤드에 할당할 수 있습니다.

아래는 “이 컬렉션을 “높음”으로 표시된 샤드에 음수 무한대에서 무한대까지 저장합니다. 다음을 의미하는 명령입니다.

> sh.updateZoneKeyRange("super.importnat", {"<shardKey>" : MinKey}, 
   ... {"<shardKey>" : maxKey}, "high")

super.important 컬렉션의 데이터는 다른 서버에 저장되지 않으며 이는 다른 컬렉션이 배포되는 방식에 영향을 미치지 않습니다. 다른 컬렉션은 여전히 ​​이 샤드와 다른 샤드에 고르게 분산되어 있습니다.

높게 구역화된 샤드를 제외하고 모든 샤드로 이동할 수 있는 컬렉션이 있을 수 있습니다. 이 경우 영역별로 그룹을 만들 수 있습니다.

> sh.addShardToZone("shard0001", "whatever")
> sh.addShardToZone("shard0002", "whatever")
> sh.addShardToZone("shard0003", "whatever")
> sh.addShardToZone("shard0004", "whatever")
> sh.addShardToZone("shard0005", "whatever")

수동 샤딩

요구 사항이 복잡하거나 특별한 상황이 있는 경우 데이터가 배포되는 위치를 완전히 제어할 수 있습니다. 밸런서를 비활성화하여 데이터가 자동으로 배포되지 않도록 하고 moveChunk 명령을 사용하여 수동으로 데이터를 배포합니다.

밸런서를 끄려면 mongos에 연결하고 셸 마법사를 사용하여 밸런서를 끕니다.

> sh.stopBalancer()

moveChunk 명령을 사용하여 청크를 다른 조각으로 이동합니다. 이동할 청크의 하한을 지정하고 청크를 이동할 샤드의 이름을 입력합니다.

> sh.moveChunk(
  ... "test.manual.stuff"
  ... {user_id: NumberLong("-1844674047370955160")},
  ... "test-rs1")

특별한 경우가 아니면 MongoDB의 자동 샤딩을 수동으로 하는 대신 사용합니다. 특히 수동 일회성 분산과 동시에 저울을 가동하지 마십시오. 밸런서가 균형이 맞지 않는 청크 수를 감지하면 수작업을 섞어 컬렉션의 균형을 재조정합니다.