Mongodb 1TB 데이터를 반으로 갈라 서버 둘로 나눈 작업 로그
mongodb 데이터가 1TB를 채워가다보니 문제가 하나둘이 아니다. 이번에 겪은 문제와 처리 과정을 기록으로 남긴다. 말 그대로 작업 기록일 뿐이고, 가까운 미래에 2TB쯤 됐을 때 다시 맨붕을 겪을 나 자신을 위해 기록한다.
이번 작업은, 용량을 양분하고 있는 두개의 collection을 각각 별도의 서버로 분리하는게 목적이었다. 복잡한 작업은 아니지만 워낙 옮겨야 할 데이터 양이 많고, 1분에 1만개 정도의 데이터가 계속 insert 되고 있는 운영 환경을 유지한 상태에서 처리해야 하는 상황이라 하나하나의 작업이 쉽지 않았다.
기존 DB 서버는 aws에서 t2.medium서버에 Throughput Optimized HDD(ST1) 1TB 디스크를 달고 있는 mongodb 서버 replset 두개로 구성이 되어있었다. aws에서는 ssd가 최대 1TB이기 때문에 ssd 쓰던걸 그만두고 ST1으로 옮긴 상태였다. primary 서버는 쓰기 전용으로, secondary 서버는 읽기 전용으로 사용했다.
데이터가 점점 많아지자 기존에 매일 실행되던 aggregate query가 점점 오래 걸려서 timeout 이 발생하고, 이를 못 버틴 secondary 서버가 recovery모드로 바뀌며 sync를 포기했다.
이참에 secondary 서버의 디스크를 1.5TB로 변경한 후 다시 싱크해줬는데, 거의 하루동안 sync 하겠다고 노력하더니만 마지막쯤 index build 도중에 다시 sync 를 포기한다. 어떤 요인에 의해 secondary가 sync를 못하고 있는 동안 primary에 op가 일정 갯수 이상 쌓이면 이런 현상이 발생하는 것 같다. 사실 정확한 원인은 모른다. 아무튼 이런짓을 2회 반복했다.
결국 이 상황에서는 복제셋을 만들 수 없다는 결론을 내고, 기존 데이터를 과감하게 반으로 갈라 서버를 둘로 나누기로 결정. 조회가 적은 데이터 절반은 t2.small에 Cold HDD (SC1) 1TB 두대로 복제셋을 구성하고, 조회가 주기적으로 있는 데이터 절반은 primary는 기존환경, secondary는 aggregate 작업 속도를 고려 SSD로 디스크를 교체해 구성하기로 한다.
새 mongodb 서버 세트를 구성하고, 사용중인 어플리케이션을 수정하여 특정 collection은 새 db 서버로 가도록 한다. 이 이후로 들어오는 데이터의 절반정도는 새 db 서버로 간다. 이제 기존 db에 있는 특정 collection의 데이터를 새 db에 부워줘야한다.
데이터 이전을 위한 서버 한대를 t2.small, Cold HDD 5TB로 준비한다. 사실 기존 데이터 약 600GB를 dump 떳을 때 어느정도 용량이 나올지 감을 못잡아서 넉넉히 준비했다. 결과적으로는 실제 디비 용량보다 dump 용량이 적다는걸 알았고(index를 제외한 정도의 용량인 것 같다), 디스크 90% 가 놀았다;; AWS 좋다는게 뭔가, 하루만 쓰고 삭제하면 되니까;;;;
어쨋든 데이터 이전을 위해 만든 서버를 copy 서버라고 명명한다. copy 서버에서 mongodump 명령을 통해 특정 collection의 데이터만 복제한다. 약 10시간에 걸처서 500기가짜리 bson 파일 하나가 생성된다.
새로 만든 디비 서버에 mongorestore 명령을 통해 데이터를 부어준다. 세시간 넘었는데 아직 20%다.
기존 서버에서 필요 없어진 collection을 drop 한다. 전에 데이터 삭제 작업을 하면서 mongodb에서 데이터 삭제하는 작업이 엄청 오래 걸렸다는걸 기억하고 있고, 그동안 db에 write lock이 걸린다는걸 알고 있기 때문에 상당히 망설여지는 작업이었다. 구글링을 열심히 해보니 collection drop은 빠르단다. 더 열심히 찾아보니 drop 하기 전에 index를 삭제해주는게 좋다고 한다. 그래서 index 먼저 삭제한다. 그리고 collection drop 명령을 때리니, 즉시 true를 리턴한다. 정말 찰나의 순간에 600기가, 6억건의 document가 삭제된다.
이제 다시 기존 디비 서버의 secondary를 복구할 차례. SSD로 디스크만 교체 후 mongodb를 실행하면 자동으로 복제를 시작한다. 데이터 량이 줄어들어서 소요 시간도 많이 줄어들었다. 그래도 오래걸리는건 마찬가지다.
써놓고 보니까 작업량이 많지 않은데 왔다갔다하는 데이터가 워낙 많은지라 3일정도 소요되었다. 서버들을 값싼 t2 계열로 많이 쓰다보니 작업중 CPU Credit Balance가 0이 되지 않도록 신경 써야 했고, 어떤 경우에는 운영중인 DB에 영향이 적도록 일부러 느린 디스크와 Credit Balance가 바닥인 서버를 사용하기도 했다. aws의 volumn중 HDD계열들은 Burst Balance도 있기 때문에 운영 DB를 계속 읽어야 하는 복제 작업 도중 Burst Balance가 0이 되지 않는지 확인해야 했다. 물론 운영중인 서비스에 영향이 없는지 계속 모니터링 해줘야 한다. 뭐 aws 서버들을 오가다보니 실수로 다른 서버를 terminate 시켰다거나 다른 volumn을 detach 해버렸다거나 (사용중인 volumn은 실수로 detach 해도 aws에서 시도하다가 관둔다는 사실을 알았다) 하는 일도 있었지만 부끄러워서 안적는다.