MongoDB 샤딩키 재구성
MongoDB 샤딩키 재구성을 어떻게 진행했는지에 대해 소개합니다.
재구성이유
서비스의 트래픽과 DB 용량이 높아지면서 샤드들의 CPU 사용률이 70 ~ 80% 이상 보일때가 많았습니다.
이러한 이유로 mongoDB 서버 성능이 현저히 낮아져 지연쿼리들이 발생하고 있는걸 확인되었습니다. 서비스 운영에 있어 많은 영향을 줄 것으로 보여 원인을 파악하여 샤딩키 재구성을 진행하기로 하였습니다.
서버구성
mongos 2대, shard 5대, config3대로 구성되어 운영중입니다.
서버 부하/지연 원인
mongoDB 샤딩키를 ObjectId로 초기 구성부터 운영되고 있었습니다. 초기에는 문제가 없었지만 서비스가 커지다 보니 성능저하가 발생하였습니다. ObjectId로 구성하면 어떠한 문제점들이 있는지 파악한 내용은 이렇습니다.
1. 등록 시 샤드 1번으로 몰림으로 인한 서버 부하
샤드 1번은 최대,최소 ObjectId 범위를 가지고 있기 때문에 샤드 1번으로만 데이터가 등록되어 hotspot 문제가 발생합니다.
🤔 그러면 샤드 2~5번은 아무 동작을 안하는걸까요?
샤드1번이 데이터를 chunk 할 수 있는 용량(기본 128MB)이 넘어가면 샤딩키 기준에서 split하여 chunk 합니다. chunk된 데이터 일부가 용량이 제일적은 샤드로 이동됩니다.
config 서버의 프라이머리가 밸런서 역할을 하고 있습니다. 밸런서는 샤드간의 균등 분배를 목적으로 하기 때문에 용량이 제일적은 샤드를 config 서버에서 확인하여 샤드를 이동하게 됩니다.
2. 수정/조회 시 Shard Merge로 인한 지연
샤딩키가 ObjectId로 되어 있기 때문에 사용자 기준 수정이나 조회시 모든 샤드를 접근하여 Shard Merge가 발생합니다. Shard Merge는 MongoDB에서 고비용 작업이기 때문에 성능에 영향을 미칩니다.
사용자 기준 explain 결과
샤딩키
위와 같은 이슈때문에 샤딩키를 재구성하기로 하였습니다. 서비스 특성상 사용자 기준으로 mongoDB에 저장하고 있기 때문에 “사용자 ID”로 샤딩키를 등록하기로 하였습니다.
샤딩키 hotspot방지를 위해 Range 기반 샤딩이 아닌 Hashed 기반 샤딩으로 결정하여 진행하였습니다.
🤔 Range 기반과 Hashed 기반 샤딩 차이는 뭘까요?
Range 기반 샤딩: 순차적으로 범위를 정렬하여 샤딩
- 장점
- 범위 쿼리 효율적
- 데이터 지역성 유지
- 단점
- hotspot 발생 가능성
- 불균등한 데이터 분산
Hashed 기반 샤딩: 랜덤하게 범위가 분포되어 샤딩
- 장점
- 균등 데이터 분산
- hotspot 발생 방지
- 단점
- 범위 쿼리 비효율
hotspot 문제로 인하여 샤드에 평균 10만건이 insert 되고 있었습니다.
재구성
주기마다 PM 작업이 있어 서비스 일시 중단 일정에 맞춰 Devops팀에 협업하여 mongoDB 샤딩키를 재구성하기로 하였습니다.
재구성하기 위한 전략은 기존 mongoDB를 dump이후 새로운 mongoDB VM에 restore이후 샤딩키를 재구성하기로 하였습니다. 안전한 재구성을 위해 새로운 mongoDB에 restore이후 문제가 발생하면 이전 mongo DB VM으로 롤백하기로 했습니다.
restore이후 mongodb 샤딩활성화 및 샤딩키 지정
1
2
3
4
5
6
// 새 데이터베이스에 샤딩 활성화
sh.enableSharding("users")
// 해시 기반 샤딩 설정
db.data.createIndex({ userId: "hashed" })
sh.shardCollection("users.data", { userId: "hashed" })
결과
다행히 이슈없이 restore 및 샤딩키 재구성이 마무리 되었습니다. 그이후 모니터링을 통해 샤드들의 CPU 사용률은 10~20%으로 감소되어 성능이 많이 개선된걸 확인할 수 있었습니다.
또한 10만 건의 알림 데이터가 특정 샤드로 집중되는 Hotspot 문제를 Hash 기반 샤딩으로 해결했습니다. 데이터를 해시 함수로 분산시켜 각 샤드당 800~1,000건씩 균등하게 처리되도록 개선한 결과, Insert 성능이 약 100배 향상되었습니다.
mongodb 구성할 때 사딩키의 중요성과 재구성할려면 많은 비용이 소모된다는걸 알게되었습니다. 모니터링하면서 서비스가 문제점이 없는지 계속 지켜볼 예정입니다.







