일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 인프콘2023
- 2025 계획
- Test
- enumSet
- mapstruct
- Service 계층 테스트
- Server
- 자바
- Java
- Coputer Science
- JPA
- 직장인 회고
- OS
- ExceptionResolver
- 2024회고
- Spring
- Junit 5
- proxyFactory
- Test Doulbe
- 소프티어
- 공룡책
- 테크쇼
- modelmapper
- softeer
- 일상
- db
- FCM
- Test code
- MySQL
- 갓생
- Today
- Total
공부내용공유
Mongo DB Sharding (feat: replication, partitioning) 본문
Mongo DB Sharding (feat: replication, partitioning)
forfun 2024. 4. 5. 17:34서론
현재 우리 팀은 새로 시작하는 프로젝트들은 대부분 DB를 Mongo로 만들어 진행하고 있고 추후 RDB를 사용하고 있는 프로젝트들도 Mongo로 전환 예정이다.
MongoDB로 이전하는 이유를 여쭤봤었는데 여러가지 이유가 있지만 제일 큰 이유는 샤딩되어 있는 DB의 원활한 관리라고 하셨다.
(현재 도메인의 데이터가 굉장히 많아 여러 sub db에 데이터를 저장하고 있다.)
샤딩이 무엇인지 정리하고 MongoDB에서는 샤딩을 어떠한 방식으로 지원해주는지 정리하기 위해 이 글을 작성하였다.
본론
먼저 sharding만 알아보면 살짝 아쉬우니 이 김에 partitioning과 replication도 같이 알아보자! (두 개념도 알아야 MongoDB의 sharding 방식도 편하게 이해할 수 있다.)
Partition
1. vertical partitioning
단어 뜻 그대로 테이블을 수직으로 나누는 기법이다. 간단한 예시로 게시물을 저장하는 DB가 있다고 하자.
id | subject | writer_name | content |
---|---|---|---|
12 | 주식 잘하는 법 | 워렌 버핏 | 1 KB |
13 | 코딩 잘하는 법 | 제임스 고슬링 | 10 KB |
14 | 운동 잘하는 법 | 로니 콜먼 | 1 GB |
게시글을 전체 조회를 하게되면 글 제목 : 작가 형태의 인터페이스를 요구하고 글 내용은 상세 페이지에서 조회한다고 가정하자.
그렇다면 게시글 조회 쿼리를 보통들은
select subject, writer_name
from posts;
이렇게 작성할 것이다.
물론 해당 필드들로 이루어진 index가 있다면 문제가 없겠지만 인덱스가 없다면 디스크에서 일단 데이터를 메모리에 올리고 필요한 필드들을 추출하는 방식이기 때문에(일반적인 RDB라면) IO에 큰 부하가 생길 것이다.
이를 해결하려면 어떻게 해야할까? 테이블을 나누면 된다.
id | subject | writer_name | content_id |
---|---|---|---|
12 | 주식 잘하는 법 | 워렌 버핏 | 1 |
13 | 코딩 잘하는 법 | 제임스 고슬링 | 2 |
14 | 운동 잘하는 법 | 로니 콜먼 | 3 |
id | content |
---|---|
1 | 1 KB |
2 | 10 KB |
3 | 1 GB |
위와 같이 성능을 위해 테이블을 나누거나 데이터의 정합성을 위한 정규화도 일종의 vertical partitioning이라 할 수 있다.
2. horizontal partitioning
테이블을 수평으로 나누는 개념이다, 해당 개념은 어디에서 활용될 수 있을까?
id | student_name | class_name | class_semester |
---|---|---|---|
12 | 김신 | 연약한 사람을 위한 호신 무술 | 2024 - 1 |
13 | 백도찬 | 두근 두근 베이킹 | 2024 - 1 |
14 | 유우성 | 신나는 중국어 | 2023 - 2 |
위에서 볼 수 있듯이 대학 강의를 저장하는 테이블이 있고 굉장히 많은 양의 데이터가 있다고 가정해보자.
일단 보통은 인덱스를 사용할 것이다, 인덱스를 통해 조회에서는 데이터의 양이 많아도 어느정도 커버가 가능하겠지만 삽입, 수정시에 성능이 굉장히 느려질 것이다.
또한 데이터 특성상 예전 데이터들 보다는 최근 데이터들에 접근을 더 많이 하는 경향이 있을 수 있다. 이러한 문제들은 어떻게 해결할 수 있을까?
id | student_name | class_name | class_semester |
---|---|---|---|
12 | 김신 | 연약한 사람을 위한 호신 무술 | 2024 - 1 |
13 | 백도찬 | 두근 두근 베이킹 | 2024 - 1 |
14 | 최민욱 | 네일 아트 | 2024 - 1 |
id | student_name | class_name | class_semester |
---|---|---|---|
12 | 오주엽 | 롤 잘하는 법 | 2019 - 2 |
13 | 신찬규 | 성경 공부 | 2019 - 2 |
14 | 박성훈 | 경영이란 무엇인가 | 2019 - 2 |
이렇게 테이블을 수평으로 나누어서 자주 같이 조회되는 데이터를 모아두는 방식으로, 자주 조회되는 데이터는 좀 더 성능이 좋은 서버에 저장하는 방식을 통해 해결할 수 있다.
데이터를 나눌 때는 필드 중 하나를 Partition Key로 정해서 어플리케이션 단에서 hash function을 사용하여 저장되는 테이블을 랜덤으로 나눠줄 수 있고 위에서와 같이 기준을 두고 나누어 줄 수도 있다.
우리 팀의 프로젝트의 경우에는 그룹별로 정보 (그룹 이름, 설정 정보, 저장되어 있는 파티션 위치...)를 별도의 테이블에 저장하여 파티셔닝을 한다.
- horizontal partitioning 주의할 점
- hash 방식을 사용할 시 중간에 파티션을 추가하기 힘들다.
- hash 함수를 잘못 만들면 한쪽에만 데이터가 쌓일 수 있다.
- partition key를 잘못 고르면 모든 DB를 전부 조회해야하는 상황이 빈번히 생길 수 있다.
Sharding
sharding은 사실 horizontal partitioning과 크게 다르진 않다.
- sharding : 나누어진 테이블을 각기 다른 서버에서 저장하고 관리한다.
- horizontal partitioning : 나누어진 테이블을 한 서버에서 저장하고 관리한다.
이런 차이가 있고 위에서 나왔던 테이블을 접근하는 키는 shard key가 되고 각 서버가 shard01, shard02... 와 같이 구분이 된다.
Replication
레플리케이션은 DB의 데이터를 모두 다른 DB에 똑같이 복사를 하는 개념이다, 이러한 복사본은 어디에 사용될까?
- 사용중이던 DB가 작동하지 않을 때 복사했던 DB를 바로 사용하여 장애 대응을 함으로 가용성을 높일 수 있다.
- 요청이 너무 많을경우 (보통의 경우 조회 요청이 큰 비중을 차지하므로) READ는 모든 DB가 요청을 나눠서 받게 하고
수정, 삭제 등과 같은 정합성 이슈가 생길만한 작업들만 한 DB에서 받게한다. (보통 이런 DB를 master db라 한다.)
사용하는 방식이나 구조는 다양할 수 있겠지만 어쨋든 데이터를 똑같이 가지고 있는 서버를 여러개 두어 가용성, 효율성을
높이는 개념이다.
MongoDB에서의 샤딩
해당 글에서는 샤딩을 위해 MongoDB에서 어떤 구조로 지원하는지 공식 문서에 나온 내용들을 요약, 정리하였고 세부적인 내용들이나 직접 적용하고 테스트하는 내용은 별도의 글에서 다룰 예정이다.

[1] Router (mongose)
mongose는 몽고 DB에서 지원해주는 몽고 DB 조작을 위한 인터페이스이다. 도큐먼트에서 shard에 절대 직접 접근하지 말고 mongose를 이용해 접근할 것을 권하고 있다. (데이터 정합성과 같은 이유 때문에)
mongose는 어떤식으로 데이터 조작을 할까?
- mongose는 config DB로 부터 shard에 있는 데이터 정보를 얻는다.
- 해당 정보를 기반으로 쿼리를 날릴 shard를 결정한다.
- 각 shard별로 cursor를 만들고 쿼리를 날린다.
- 각 shard로 부터 받은 document들을 합쳐서 결과를 어플리케이션에 반환한다.
특정 연산들은 어떻게 처리될까?
- Sorting
- 기본적으로 각 shard에서 sorting을 진행하고 데이터를 받는다.
- 만약 sorting이 안되어 있다면 각 shard로 부터
round robin
방식으로 데이터를 수집해 반환한다. (나중에 실제로 테스트를 해볼 예정이다.)
- Limits
- 각 shard에게 요청을 보낼 때 limit을 전달한다.
- 결과를 받고 한번 더 limite을 적용해 결과를 반환한다.
- Skips
- shard한테는 skip을 보내지 않는다.
- 단, document들을 전부 받은 후 거기에서 skip을 적용하고 결과를 반환한다.
[2] config DB
간단 설명
config DB는 sharding이 적용된 cluster에 대한 meta 데이터들을 가지고 있다. meta data로는
- shard 구성정보 및 상태 정보
- chunk 리스트, 크기
- cluster의 Authentication 정보
등등이 있다. 상세한 데이터 예시들은 공식 문서를 참고하면 된다.
주의할 점
- config DB에 명령어를 날릴 경우 cluster에 큰 영향을 끼치므로 cluster를 read-only로 바꾸거나 중지하고 실행하는 것을 권장한다.
- 중요한 데이터들이 있는만큼 replica set을 권장한다.
- 단, config server가 Wired Tiger Storage Engine 사용해야한다.
- replica set중 primary가 죽는다면 cluster에 read/write 다 가능하나 chunk migration, chuck split은 불가능하다.
- primary 가 죽을경우 config data를 read만 할 수 있기 때문이다.
- seconday중 primary가 정해지면 당연히 정상작동이 가능하다.
[3] shard
간단 설명
shard의 정의는 sharding이 적용된 cluster의 데이터를 가지고 있는 subset이다.
primary shard
conllection들 중에는 sharding이 적용된 것들과 안된 것들이 있을 것이다. 이때 primary shard는 sharding이 적용이 안된 모든 collection들을 갖고 있는다.

primary shard는 mongos가 여유 공간이 제일 많이 남은 shard를 선택해서 설정한다. 물론 movePrimary
로 변경이
가능하다.
주의할 점
- shard는 가용성, 안정성을 위해 replica set으로 구성할 것을 권장한다.
- shard에 직접 쿼리를 날리면 안된다, 정합성에 문제가 생길 수 있으므로 mongose를 통해 접근해야 한다.
Shard Key로 구분이 되는데 key에 따라 성능이 굉장히 크게 좌지우지 된다, 이는 다른 글로 따로 정리할 예정이다.
결론
내용이 생각보다 방대했다, 또 mongo의 sharding을 이해하기 위해서는 replication
, chunk
, index
등등
다른 개념들을 명확히 알아야 잘 사용할 수 있을 것 같다.
또 document의 설명으로는 조금 애매한 부분이 있어서 추후 직접 샤딩을 적용하고 테스트를 해봐야 정확히 알 것 같다.
최대한 빠른 시일 내에 테스트를 해보고 포스팅할 예정이다!
'ComputerScience > DataBase' 카테고리의 다른 글
MongoDB 정규화, 반정규화 (0) | 2024.04.28 |
---|---|
MongoDB Bulk Ops (feat: insertMany, Bulk Write) 알아보기 (0) | 2024.04.21 |
MySQL Bulk Update (feat: temporal table) (0) | 2024.03.21 |
MySQL Order By, Select For Update 최적화 하기 (0) | 2024.03.02 |
MySQL index 설계, 튜닝시 고려사항 (covering, index dive, prefix index) (0) | 2024.02.25 |