본문 바로가기

개발자는 오늘도 달립니다.

[MongoDB] 몽고DB 샤딩(Sharding) 구성하기! 본문

데이터베이스/몽고DB

[MongoDB] 몽고DB 샤딩(Sharding) 구성하기!

✍21시간 2021. 1. 29. 16:33

다수의 RDB (mysql, postgresql, oracle)에서 샤딩구성이 가능합니다. 뭐..ಠ_ಠ 관계형 데이터베이스에서
이러한 기능은 많은 분들이 익히 알고계시리라 생각됩니다. (ง •̀_•́)ง


mongodb 에서도 확장 개념인 샤딩구성이 가능한데요~
빅데이터 시대에서 확장개념은 클라우드 및 다수의 시스템에서 선택이 아닌 필수가 되었습니다.
그래서 오늘은 이 샤딩구성에 대한 개념과 방법을 블로깅 하겠습니다.

먼저 샤딩이란 무엇일까요? ・ヘ・?

The word “Shardmeans “a small part of a whole “. Hence Sharding means dividing a larger part into smaller parts.
샤드는 전체에서 작은 부분을 뜻하고 직역을 한다면 조각이 되겠네요! 그리고 샤딩이라는 의미는 큰 부분에서 작게 나누는 것을 샤딩이라고 합니다.
기능적인 관점에서는 여러 호스트에 데이터를 배포하는 것이고요. 여러 MongoDB 인스턴스에 걸쳐 큰 데이터 세트를 작은 데이터 세트로 분할하는 것이 샤딩처리라고 이해하면 좋을 것 같아요~

샤딩 작동 원리

처리량이 많은 애플리케이션이나 매우 큰 데이터를 처리할 때 하드웨어의 성능이 매우 중요해집니다. 또한 높은 쿼리 속도는 디스크 드라이브의 CPU, RAM 및 I/O 용량에 부담을 주어 전체적인 성능을 저하시킬 수 있습니다.
그래서 이 문제를 완화하기 위해 큰 범위에서 두 가지 유형의 확장 방법이 있습니다.

수직 확장 (Vertical scaling)

수직 확장은 단일 서버의 하드웨어 기능을 향상하는 전통적인 방법입니다. 가장 일반적이면서 간단하면서 직관적인 방법입니다. 그냥 하드웨어에 관련한 CPU, RAM 및 저장 용량을 업그레이드하는 방식인데 하드웨어를 무작정 업그레이드하는 것은 종종 기술적 한계와 비용 제약으로 인해 어려움을 겪게 되고 동작의 연속성의 문제를 만들기도 합니다.

수평 확장 (Horizontal scaling)

이 방법은 데이터 셋을 여러 서버로 나누고 각 서버 인스턴스에 데이터베이스 로드를 분산합니다. 부하를 분산하면 필요한 하드웨어 리소스에 대한 부담이 줄어들고 장애 발생 시 페일오버까지 가능해집니다. 저희는 바로 이 방법을 사용해서 샤딩구성을 하려고 하는 것이고요!
물론 수평 확장이 장점만 가진 것은 아니에요. 수평 확장을 무작정 하려다 보면 아키텍처의 복잡성을 굉장히 증가시킬 수 있습니다. 다행히도 저희가 이런 부분을 고려해서 복잡한 뭔가를 할 필요 없이 MongoDB가 자체적으로 제공하는 샤딩 기능을 통한 수평 확장을 하려고 합니다.

mongodb 샤딩 구성요소

몽고 디비는 샤딩구성을 하는데 대표적으로 3가지의 요소들이 필요합니다.

  • Shard
  • Mongos
  • Config servers

Shard

샤드는 가장 기본이 되는 인스턴스입니다! 데이터의 하위 집합을 보유하고 있는 단일 mongoDB 인스턴스라고 보시면 되시고요. 그래서 여러 샤드를 구성하게 되면 그만큼 가용성을 높일 수 있고 또한 데이터의 이중화가 가능해집니다. 샤드를 여러 개로 조합하고 데이터 셋을 생성하게 되는데, 이것이 예를 들어 2TB 라면 4개의 샤드로 나눌경우 500GB로 각 샤드가 데이터를 가질 수 있게 됩니다.

Mongos

mongos 는 다수 구성된 샤드의 인터페이스 역할을 합니다. 클라이언트 요청의 올바른 샤드로 라우팅 하는 것이 주요 기능입니다.

Config Servers

전체 클러스터의 메타 데이터, 구성 설정 등을 저장하는 서버입니다.

아래는 공식 MongoDB 문서의 다이어그램입니다. (각 구성 요소 간의 관계를 설명합니다.)

  1. 애플리케이션은 실행할 쿼리에 대해 라우터(mongos)와 통신합니다.
  2. mongos는 구성 서버를 참조하여 해당 샤드에 쿼리를 보내는 데 필요한 데이터 셋이 포함된 샤드를 확인합니다.
  3. 마지막으로 쿼리 결과가 응용 프로그램에 반환됩니다.

(구성 서버는 레플리카 셋으로도 작동합니다.)

- 주요 요소

Shard Keys

MongoDB 컬렉션을 샤딩 할 때 초기 단계 중 하나로 샤드 키가 생성됩니다. "샤드 키"는 MongoDB 컬렉션의 도큐먼트를 전체 샤드에 배포하는 데 사용됩니다. 키는 모든 도큐먼트에서 단일 필드 또는 여러 필드로 구성됩니다. 샤딩 된 키는 샤딩 후에는 변경이 불가합니다! 분할된 컬렉션에는 단일 분할 키만 포함됩니다.
채워진 컬렉션을 분할할 때 컬렉션에는 분할 키로 시작하는 인덱스가 있어야 합니다. 적절한 인덱스가 없는 빈 컬렉션일 때 MongoDB는 지정된 샤드 키에 대한 인덱스를 생성합니다.
샤드 키는 클러스터의 성능에 직접 영향을 미칠 수 있습니다. 따라서 클러스터와 관련된 응용 프로그램에서 병목 현상이 발생할 수 있습니다. 이를 완화하려면 컬렉션을 샤딩하기 전에 다음을 기반으로 샤드 키를 생성해야 합니다.

  • 데이터 세트의 스키마
  • 데이터 세트를 쿼리 하는 방법

Chunks

청크는 공유 데이터의 하위 단위입니다. MongoDB는 샤딩 된 데이터를 공유 클러스터의 샤드에 분산된 청크로 분리합니다. 각 클러스터에 특정한 밸런서가 청크 분배를 처리합니다.
밸런서는 백그라운드 작업으로 실행되며 모든 샤드에서 청크의 균형을 맞추기 위해 필요에 따라 청크를 배포합니다.

샤딩 이점 및 문제점

이제 개념을 이해했으므로 MongoDB에서 샤딩의 이점과 문제점을 살펴보겠습니다! ᕙ(•̀‸•́‶)ᕗ

샤딩을 쓰게 되었을 때 오게 되는 이점!

  • 기존 복제 시나리오에서 기본 노드는 대량의 쓰기 작업을 처리하는 반면 보조 서버는 읽기 전용 작업 또는 데이터 세트의 백업 유지로 제한됩니다. 그러나 샤딩은 복제본 세트가 있는 샤드를 활용하므로 모든 쿼리가 클러스터의 모든 노드에 분산됩니다.
  • 각 샤드는 전체 데이터 세트의 하위 집합으로 구성되므로 샤드를 추가하기 만하면 복잡한 하드웨어 재구성을 수행할 필요 없이 클러스터의 스토리지 용량이 늘어납니다.
  • 복제에는 대규모 데이터 세트를 처리할 때 수직 확장이 필요합니다. 이러한 요구 사항은 수평 적 확장 방식에 비해 하드웨어 제한과 엄청난 비용으로 이어질 수 있습니다. 그러나 MongoDB는 수평 확장을 사용하기 때문에 워크로드가 분산됩니다. 필요한 경우 추가 서버를 클러스터에 추가할 수 있습니다.
  • 샤딩에서 읽기 및 쓰기 성능은 클러스터의 서버 노드 수와 직접적으로 관련됩니다. 이 프로세스는 단순히 노드를 추가하여 클러스터의 성능을 향상하는 빠른 방법을 제공합니다.
  • 샤딩 된 클러스터는 단일 또는 여러 샤드를 사용할 수 없는 경우에도 계속 작동할 수 있습니다. 이러한 샤드의 데이터는 사용할 수 없지만 클라이언트 애플리케이션은 다운 타임 없이 클러스터 내에서 사용 가능한 다른 모든 샤드에 계속 액세스 할 수 있습니다. 프로덕션 환경에서는 모든 개별 샤드가 복제본 세트로 배포되어 클러스터의 가용성이 더욱 향상됩니다.

샤딩이 불러올 또 다른 문제점

  • 샤딩은 복잡하기 때문에 샤딩 된 클러스터를 유지하기 위해 신중한 계획과 유지 관리가 필요합니다.
  • 분할된 컬렉션을 분할 해제할 방법이 없습니다.
  • 샤드 키는 컬렉션 내의 모든 문서를 식별하는 데 사용되므로 기본 클러스터의 전체 성능에 직접적인 영향을 줍니다.
  • 샤딩 된 환경에는 몇 가지 운영 제한이 있습니다. 예) geoSearch 명령은 샤딩 된 환경에서 지원되지 않습니다.
  • 샤드 키 또는 복합 샤드 키의 접두사가 없는 경우 Mongo는 클러스터의 모든 샤드를 쿼리 하는 브로드 캐스트 작업을 수행하므로 쿼리 작업이 오래 실행될 수 있습니다.


본격적으로 MongoDB 샤딩 구성하기!

이제 샤딩의 개념을 이해했으므로 몇 가지 실습을 시작하겠습니다.
리눅스(Ubuntu 20.04 LTS) 시스템 환경을 준비해주세요! 그리고 서버 내에 MongoDB 4.4.1 설치를 필수적으로 해주시면 됩니다.

  • mongodb01 – 10.10.12.10 – 구성 서버
  • mongodb02 – 10.10.12.10 – 쿼리 라우터 (mongos)
  • mongodb03 – 10.10.12.10 – 샤드

(저는 vm 환경 ubuntu 에서 진행을 하였고 한대에 모든 구성을 하였습니다. 상황에 따라서 실제 서버를 구성할 때는 유연하게 배치하세요! 시작하기 앞서 tmjb라는 계정을 하나 만들어 주시고 거기서 작업해주세요~ 혹시 다른 이름을 사용할 경우 설정 내용 중에 tmjb를 원하는 이름으로 변경하시면서 하셔야 해요~)

1. config Server 설정 및 기동

mkdir -pv mongodb/data/configdb/
mkdir -pv mongodb/data/logs
touch mongodb/data/logs/configsvr.log
ls -alRv mongodb/
config server 디렉토리 설정


위의 명령을 실행하면 해당 디렉터리와 함께 구성 파일이 생성된다. 다음으로, 구성 파일을 만들고 서버의 포트와 IP 주소를 입력해 주세요. (클러스터 롤은 configsvr로 하세요.)

sudo vi /etc/mongodConfig.conf


- 위 파일에 들어갈 내용

storage:
dbPath: /home/tmjb/mongodb/data/configdb
journal:
enabled: true

systemLog:
destination: file
logAppend: true
path: /home/tmjb/mongodb/data/logs/configsvr.log

net:
port: 27019
bindIp: 10.10.12.10

sharding:
clusterRole: configsvr

replication:
replSetName: ConfigReplSet


설정 파일 입력이 마무리되었으면 저장하시고, 아래 커맨드로 config 서버를 동작합니다.

mongod --config /etc/mongodConfig.conf&

config서버가 정상적으로 동작하고 있는지 로그로 확인!

tail -100 mongodb/data/logs/configsvr.log
mongod 시작 및 점검


구동이 완료되었다면 아래의 커맨드로 접속해주세요.

mongo 10.10.12.10:27019


접속된 상태에서 initiate() 함수를 사용해서 기본 설정을 해주시고, status() 함수로 설정 상태를 확인합니다.

rs.initiate()
rs.status()

위와 같이 설정과 상태가 확인되었다면 정상적으로 config 서버가 올라간 거예요!

2. Query router(mongos) 설정 및 기동


config 서버와 마찬가지로 아래 커맨드로 관련 디렉터리와 파일들을 생성해줄게요.

mkdir -pv mongodb/data/logs
touch mongodb
/data/logs/mongorouter.log
ls
-alRv mongodb/

설정 파일 또한 만들어주시고, 내용에는 로그 패스와 서버 인스턴스의 IP, PORT 가 들어가야 하며, 해당 query router에 소속된 config server의 정보를 적어주세요.

sudo vi /etc/mongoRouter.conf


- 위 파일에 들어갈 내용

systemLog:
destination
: file
logAppend
: true
path
: /home/tmjb/mongodb/data/logs/queryrouter.log

net
:
port
: 27017
bindIp
: 10.10.12.10

sharding
:
configDB
: ConfigReplSet/10.10.12.10:27019


아래 커맨드로 query router 를 올려주세요.

mongos --config /etc/mongoRouter.conf&

접속 커맨드입니다. 냉무!

mongo 10.10.12.10:27017


3. shard 설정 및 기동


아래의 커맨드로 디렉터리 구조와 로그파일을 만들어줍니다.

mkdir -pv mongodb/data/sharddb/
mkdir -pv mongodb/data/logs
touch mongodb
/data/logs/shard.log
ls
-alRv mongodb/


설정 파일 생성과 필수 설정을 아래와 같이 해주세요.
storage 는 db 데이터가 쌓이는 패스입니다. 그리고 sharding 클러스터 롤은 shardsvr로 설정해주시고, network 세팅도 잊지 말고 꼭 입력해주세요.

sudo vi /etc/mongodShard.conf
storage:
dbPath: /home/tmjb/mongodb/data/sharddb
journal:
enabled: true

systemLog:
destination: file
logAppend: true
path: /home/tmjb/mongodb/data/logs/shard.log

net:
port: 27018
bindIp: 10.10.12.10

sharding:
clusterRole: shardsvr

replication:
replSetName: ShardReplSet


아래 커맨드로 샤드를 올려줍니다.

mongod --config /etc/mongodShard.conf&

이번에도 어김없이 로그로 동작에 이상이 없나 체크해주시고요.

tail -100 mongodb/data/logs/shard.log


접속 커맨드

mongo 10.10.12.10:27018


샤드 서버에 접속이 되었다면 아래 커맨드로 initiate() 함수로 기본 설정과 status() 함수로 설정된 내용을 체크합니다.

rs.initiate()
rs.status()

1번에서 구성 한 샤드를 클러스트에 추가해보겠습니다.

먼저 Query router 에 접속합니다.

mongo 10.10.12.10:27017


아래 addShard() 커맨드를 활용해서 ShardReplSet 이름으로 10.10.12.10:27018 샤드 인스턴스를 추가해주도록 합니다.

sh.addShard( "ShardReplSet/10.10.12.10:27018")


persons 이라는 database를 생성하고 샤딩에 enable 하도록 합니다.

use persons
sh.enableSharding("persons")


status() 커맨드를 이용하면 샤딩 상태를 확인 가능한데 아래와 같이 Currently enabled 상태가 yes인지를 체크해주세요!

sh.status()

샤딩 데이터셋 생성


personscollection 이라는 이름으로 collection 을 만들어 줍니다.

db.createCollection("personscollection")


위에서 만든 collection에서 personid 라는 인덱스를 만들어 주세요~ (-1) 값을 주게 되면 내림차 순이며, 1을 주게 되면 오름차순으로 선택할 수 있습니다.

db.personscollection.createIndex({personid: -1})


테스트를 위해 데이터 하나를 인서트 해주세요!

db.personscollection.insertOne({personid: 10001})

방금 만든 personscollection 을 샤딩 활성화시키도록 하겠습니다.
personid 가 해시 처리가 되어있지 않으면 샤딩이 불가합니다. 그래서 아래 커맨드로 personid 를 해시 처리 하도록 합니다.

db.personscollection.ensureIndex({personid : "hashed"})


위에서 personid 를 인덱스로 잘 만들고 해시 처리가 되었다면 아래 명령어로 샤드 키로 사용을 할 수 있습니다.

sh.shardCollection("persons.personscollection", {personid : "hashed"})


getShardDistribution() 명령을 사용하여 샤딩 상태를 확인합니다.

db.personscollection.getShardDistribution()

위의 출력은 컬렉션이 Shard 서버 (10.10.12.10)의 ShardRepSet에서 샤딩되었음을 설명합니다.

마지막으로 MongoDB의 샤딩을 정리하자면.. ◖⚆ᴥ⚆◗

MongoDB 샤딩은 전체 성능에 큰 영향을 주지 않고 여러 서버에 워크로드를 분산하여 대용량 데이터를 효율적으로 관리하는 방법입니다. 또한 샤딩은 기본 하드웨어 인프라를 복잡하게 재구성하지 않고도 향후 요구 사항에 맞게 클러스터를 효율적으로 확장할 수 있는 기능을 제공합니다.

관련 문서 참고

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."

Comments