MongoDB를 오래 운영하다보면 데이터를 쓰고 지우고 어쩌고 하면서,

실제 디스크 상의 공간점유가 커지고 이에 따라 mapped size가 높아져서 한 번씩 정리해 줄 필요가 있다.

fsck나 vacuum 같은거라고 생각하면 되는데 MongoDB에는 compact와 repairDatabase가 있다.

둘 다 defragment와 index rebuild 등을 통해 공간을 정리해주는데, repairDatabase의 경우엔 실제 데이터 파일의 사이즈도 줄여준다.


downtime없이 rolling 방식으로 진행하게 되는데,

대상 서버를 replicaSet에서 뽑아낸 후 stand-alone 상태에서 compact 작업을 해주고 다시 replicaSet의 멤버로 복귀시키는 형태라고 보면 된다.

우선 secondary들부터 compact를 해주고 마지막에 primary를 해주는 식으로 진행되는데,

oplog 사이즈가 작업을 마치고 다시 replicaSet의 멤버로 복귀하는 동안을 커버할 수 있는지 반드시 체크해봐야 한다.

해당 mongod 인스턴스에 mongo로 접속해서 rs.printReplicationInfo()로 oplog가 얼마나 버틸 수 있는지 체크할 수 있다.

(MongoDB 2.6 이전 버전의 경우엔 db.printReplicationInfo())

만약 oplog 사이즈가 도저히 안되겠다 싶으면 oplog 사이즈 변경을 해줘야 한다.


대강 되겠다 싶으면 아래와 같은 순서로 진행하면 된다.

replicaSet은 primary + secondary 하나로 구성되어 있다고 가정한다.

우선 secondary shutdown

shard_001:SECONDARY> use admin

shard_001:SECONDARY> db.shutdownServer()


그리고 replicaSet 관련 설정을 제외하고 포트번호를 변경한 다음 stand-alone 모드로 재시작한다.

[root@secondary]# mongod --port 37017 --dbpath /mongodb/secondary


mongod로 접속하여 각 DB별로 repairDatabase나 collection별로 compact를 실행.

다 끝나고 나면 또 shutdown을 하고 이번에는 정상적인 replicaSet 멤버의 설정으로 재시작한다.

primary에서 rs.status()를 이용해 resync가 완료되고 SECONDARY state로 올라왔음이 확인되면 완료.


primary는 rs.stepDown() 으로 secondary가 primary로 전환되는 것을 확인한 후 shutdown 하고,

secondary에서 했던 동일한 방식으로 repairDatabase나 compact를 실행한 후 다시 replicaSet으로 복귀시키면 된다.


각 프로세스를 재시작하는 과정에서 순간적으로 소수의 피해자가 생기는데,

그런건 application 레벨에서 챙기도록만 해놓으면 downtime 없는 compaction이 가능하다.

실제로 각종 사이즈가 줄어들면서 mapped size도 줄어드는게 눈에 보여서 기분도 상쾌해지므로 반드시 주기적으로 해줄 것.











Posted by bloodguy
,