MongoDB를 처음 사용하는 사람들에게는 MongoDB 공간 사용이 상당히 혼란스러워 보일 수 있습니다. 이 기사에서는 MongoDB가 공간을 할당하는 방법과 ObjectRocket 대시보드에서 공간 사용량 정보를 해석하여 인스턴스를 압축하거나 인스턴스에 사용 가능한 공간을 늘리기 위해 샤드를 추가해야 할 때를 판단하는 방법을 설명합니다.
먼저 단일 5GB 샤드로 구성된 새로운 Medium 인스턴스부터 시작하겠습니다. 이 인스턴스를 "ocean"이라는 데이터베이스의 일부 테스트 데이터로 채울 것입니다. 다음은 테스트 데이터를 추가하고 인덱스를 몇 개 생성한 후의 이 인스턴스의 공간 사용량입니다.
315MiB의 데이터와 254MiB의 인덱스가 5GiB 샤드 중 2.1GiB를 사용하고 있다는 의미는 무엇입니까? 설명하기 위해 MongoDB가 디스크에 데이터를 일련의 익스텐트로 저장하는 방법부터 시작하겠습니다. ObjectRocket 인스턴스는 smallfiles 옵션으로 실행되기 때문에 첫 번째 확장 영역은 16MB로 할당됩니다. 이러한 확장 영역은 512MB에 도달할 때까지 크기가 두 배로 증가하고 그 이후에는 모든 확장 영역이 512MB 파일로 할당됩니다. 따라서 예제 "바다" 데이터베이스는 다음과 같은 파일 구조를 갖습니다.
$ ls -lh ocean/
total 1.5G
-rw------- 1 mongodb mongodb 16M Aug 20 22:30 ocean.0
-rw------- 1 mongodb mongodb 32M Aug 20 20:44 ocean.1
-rw------- 1 mongodb mongodb 64M Aug 20 22:23 ocean.2
-rw------- 1 mongodb mongodb 128M Aug 20 22:30 ocean.3
-rw------- 1 mongodb mongodb 256M Aug 20 22:30 ocean.4
-rw------- 1 mongodb mongodb 512M Aug 20 22:30 ocean.5
-rw------- 1 mongodb mongodb 512M Aug 20 22:30 ocean.6
-rw------- 1 mongodb mongodb 16M Aug 20 22:30 ocean.ns
drwxr-xr-x 2 mongodb mongodb 4.0K Aug 20 22:30 _tmp
이 익스텐트는 데이터베이스의 데이터와 인덱스를 모두 저장합니다. MongoDB를 사용하면 데이터가 범위에 기록되는 즉시 다음 논리적 범위가 할당됩니다. 따라서 위의 구조에서 Ocean.6은 현재 데이터가 없을 가능성이 높지만 Ocean.5가 가득 찰 때를 위해 미리 할당되었습니다. 데이터가 Ocean.6에 기록되는 즉시 새로운 512MB 범위인 Ocean.7이 다시 사전 할당됩니다. MongoDB 데이터베이스에서 데이터가 삭제되면 압축할 때까지 공간이 해제되지 않습니다. 따라서 시간이 지남에 따라 이러한 데이터 파일은 데이터가 삭제될 때 조각화될 수 있습니다(또는 추가 키가 추가되어 문서가 원래 저장 위치보다 커지는 경우). 압축하는 동안 데이터가 복제 세트의 다른 구성원에서 복제되고 데이터 파일이 처음부터 다시 생성되기 때문에 압축은 이러한 데이터 파일을 조각 모음합니다.
추가 16MB 파일이 네임스페이스를 저장합니다. 이것은 Ocean.ns 파일입니다. 이와 동일한 패턴이 MongoDB 인스턴스의 각 데이터베이스에 대해 발생합니다. "바다" 데이터베이스 외에도 샤드에는 "admin" 및 "local"이라는 두 개의 추가 시스템 데이터베이스가 있습니다. "admin" 데이터베이스는 모든 데이터베이스 사용자에 대한 사용자 정보를 저장합니다(2.6.x 이전에는 이 데이터베이스가 관리자용으로만 사용되었습니다). 관리 데이터베이스는 작지만 이 데이터베이스에 대해 16MB 범위, 미리 할당된 32MB 범위 및 16MB 네임스페이스 파일이 있습니다.
두 번째 시스템 데이터베이스는 "로컬" 데이터베이스입니다. 우리가 ObjectRocket에서 제공하는 각 샤드는 3인 복제 세트입니다. 이러한 복제본을 동기화 상태로 유지하기 위해 MongoDB는 각 업데이트의 oplog라는 로그를 유지 관리합니다. 이것은 각 복제본에서 동기화된 상태로 유지되며 보조 복제본에서 수행해야 하는 변경 사항을 추적하는 데 사용됩니다. 이 oplog는 "로컬" 데이터베이스 내에서 제한된 컬렉션으로 존재합니다. ObjectRocket에서 oplog의 크기를 일반적으로 샤드 크기의 10%로 구성합니다. 5GB 샤드의 경우 oplog는 500MB로 구성됩니다. 따라서 "로컬" 데이터베이스는 16MB 범위, 512MB 범위 및 16MB 네임스페이스 파일로 구성됩니다.
마지막으로 예제 샤드에는 저널이라는 하우스키핑 영역이 하나 더 포함되어 있습니다. 저널은 각각 크기가 약 128MB인 1-3개의 파일 세트입니다. 쓰기가 발생할 때마다 MongoDB는 먼저 업데이트를 저널에 순차적으로 씁니다. 그런 다음 백그라운드 스레드는 일반적으로 60초마다 한 번씩 실제 데이터 파일(이전에 언급한 범위)에 대한 이러한 업데이트를 주기적으로 플러시합니다. 이러한 이중 쓰기의 이유는 저널에 순차적으로 쓰는 것이 실제 데이터 파일에 쓰는 데 필요한 탐색보다 훨씬 빠르고 훨씬 더 빠르기 때문입니다. 변경 사항을 저널에 즉시 기록함으로써 MongoDB는 모든 쓰기 작업이 변경 사항이 데이터 파일에 기록될 때까지 기다릴 필요 없이 충돌 발생 시 데이터 복구를 보장할 수 있습니다. 현재 주 복제본의 경우 두 개의 저널 파일이 활성화되어 있습니다.
$ ls -lh journal/
total 273M
-rw------- 1 mongodb mongodb 149M Aug 20 22:26 j._1
-rw------- 1 mongodb mongodb 124M Aug 20 22:30 j._2
MongoDB는 업데이트 빈도 대 디스크로의 백그라운드 플러시 빈도에 따라 이러한 파일을 자동으로 회전합니다.
이제 MongoDB가 디스크 공간을 사용하는 방법을 다루었으므로 이전에 보여준 ObjectRocket 대시보드의 공간 사용량 표시줄에 표시된 것과 어떻게 일치합니까?
- NS 값, 48MB — 내가 언급한 세 개의 데이터베이스, 즉 바다, 관리 및 로컬에 대한 세 개의 16MB 네임스페이스 파일의 합입니다.
- 데이터 값, 315MiB —
db.stats()
의 dataSize에 대해 보고된 값의 합계 모든 데이터베이스(시스템 데이터베이스 포함). - 인덱스 값, 253.9MiB, —
db.stats()
의 indexSize에 대해 보고된 값의 합계 모든 데이터베이스(시스템 데이터베이스 포함). - 스토리지 값, 687.2MiB — 모든 데이터베이스에 대한 데이터와 인덱스, 삭제로 인해 회수되지 않은 공간의 합계입니다.
- 총 파일 값, 2.0GiB — 기본 복제본에서 총 디스크 사용량입니다. Storage 값과 NS 값이 포함하는 공간 외에도 사전 할당된 범위도 포함되지만 저널에서 사용하는 공간은 포함되지 않습니다.
이러한 메트릭이 주어지면 이 인스턴스가 압축이 필요할 만큼 충분히 조각화되었는지 여부를 결정하기 위해 몇 가지 간단한 계산을 수행할 수 있습니다. 조각화로 인해 손실될 가능성이 있는 공간을 계산하려면 다음을 사용하십시오.
100% – (데이터 + 인덱스) / 스토리지
예제 인스턴스의 경우 17%(100% – (315MiB 데이터 + 253.9MiB 인덱스) / 687.2MiB 스토리지 =17%)로 작동합니다. 단편화가 20%에 가까워지면 인스턴스를 압축하는 것이 좋습니다.
우리가 할 수 있는 또 다른 계산은 전체 공간 사용량을 기반으로 이 인스턴스에 샤드를 추가해야 하는지 여부입니다. 전체 공간 사용량을 계산하려면 다음을 수행하십시오.
(총 파일 / (계획 크기 * 샤드 수)) * 100%
이 예제의 경우 40%((2GiB / 5GiB * 1 샤드) * 100% =40%)로 작동합니다. 일반적으로 전체 공간 사용량이 80%에 도달하면 샤드를 추가하는 것이 좋습니다. 공간 사용량이 80%에 도달한 경우 지원팀에 문의하면 인스턴스에 샤드를 추가하는 데 도움을 드릴 수 있습니다.