반응형

우리회사에서는 유저의 행동기록을 남기고 있다. 상품에 대한 처리, 주문에 대한 처리, 유저가 활동한 기록들 등..

이런 기록들이 서비스 오픈 이후로 별다른 정리조치 없이 꾸준히 쌓이고 있는데,

아무래도 서비스 운영기간이 늘어날수록 db용량이 늘어나는건 당연한 수순이지만, aws 비용 줄이기를 하고 있는 요즘

mongodb의 ec2 용량마저 줄이기 위해서 데이터 정리를 하게 되었다.

 

1. 현재 가용중인 mongodb의 ec2 용량 확인하기.

회사 mongodb는 aws의 ec2에 서버를 띄워 사용하고 있다. 그리고 EBS로 EC2의 용량을 지정해 두었다.

amazonEBS는 AWS 클라우드의 EC2 인스턴스에 사용할 영구 블록 스토리지 볼륨을 제공한다.
각 EBS 볼륨은 가용 영역 내에 자동으로 복제되어 구성요소 장애로부터 보호해주고 고가용성 및 내구성을 제공한다.

 

현재 설정된 mongodb EC2의 EBS 볼륨은 310GiB 이다.

왜 primary랑 secondary가 다르냐면... 바로 얼마전에 300GiB 에서 DB에 OOM이 발생하였기 때문이다 ㅎ

200GiB에서 올린지 1년도 채 되지 않았는데 그 사이에 유저들의 활동량이 폭발적으로 늘어나면서 금방 용량이 꽉 찬듯 하다.

이때 급해서 primary만 먼저 10GiB 정도 올리고 동시에 불필요한 히스토리 데이터를 삭제작업 하면서 최종적으로 가용중인 용량은 310GiB중 267GiB 이다.

 

+) ec2 mongodb 용량 확인하기 : df -h

[ec2-user@ip-**** ~]$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme0n1p1  310G  267G   44G  87% /

 

미리 체크하면서 데이터 정리 했으면 안늘려도 됐겠군....ㅎ 그치만 데이터 정리에 대한 정책이 아예 없었었다!!!!!!!!!!!!!

 

이후 데이터 정리에 대한 여러번의.. 지시가 내려오면서... 다양한 기준으로 데이터 정리를 하기 시작했다.

- 장기 미접속 유저의 데이터 삭제...

- 탈퇴유저의 즉시 데이터 삭제..

그리고 이번에 작업한 "1년지난 히스토리 데이터 삭제" 이다.

 

2. 데이터 삭제하기

+) index 걸기

데이터 삭제를 위해서 기준값을 갖고 delete를 해주는데, 이때 잡은 기준값 key에 index가 몇개 collection엔 없었다.

일단 해~ 하면서 삭제프로세스를 시작했고 예상되는 소요시간 120시간 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

 

바로 중단 후 index 작업을 해주었다.

그리고 나서 걸린 시간 2시간! 새로운 collection를 구상할땐 index 꼭좀 걸어주세용... 뒤늦게 걸려니 영...


 

데이터 삭제 후 다시 가용용량을 확인해 봤는데 용량이 전혀 줄지 않았다! 띠용..

이는 "mongodb에서 삭제된 데이터에 대한 디스크 용량을 즉시 반환하지 않기 때문" 이다.

데이터를 삭제한 이유가 용량확보를 위한 것이므로 즉시 용량을 확보해주면 된다.

 

3. 용량 확보하기 : compact

 

+ collection lock 확인

mongodb에서 용량을 확보하는 명령어는 compact 이다.

해당 명령어 사용시 collection에 lock은 걸리지 않지만 가장 안전한 방법으로는

- 현재 사용중인 db와 를 복제..

- 데이터 마이그레이션 ..

이렇게 하는거라고 하는데 몇천만개의 데이터를 마이그레이션 하려면 거진 하루정도는 서비스를 내려야 하지 않나 싶다 ㅎ

아니면 내리지 않고 ... 어.. 음.. 마이그레이션 하는동안 생성된 데이터를 임시보관 해뒀다가 마이그레이션 한 뒤 다시 insert 해주는...? 어우.. 이게 맞나..? 무튼 복잡하다!


당장의 용량확보가 최우선순위였고, 삭제된 데이터는 운영하는데 아무런 지장이 없는 데이터이므로 운영환경에서 compact 해주기로 한다.

 

먼저 ec2의 mongodb 로 접속한다. 그리고 다시한번 용량 확인

[ec2-user@ip-*** ~]$ ssh 운영환경 ec2
       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|
[ec2-user@ip-*** ~]$ ssh mongo
Last login: ~~~

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|
[ec2-user@ip-*** ~]$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme0n1p1  310G  267G   44G  87% /

 

이후 mongodb shell 을 열어준다.

[ec2-user@ip-*** ~]$ mongo
MongoDB shell version v5.0.13
connecting to: mongodb://127.0.0.1:27017/? ~~~~~~
================
... 안내문 생략 ...
================
replica:PRIMARY>

db가 replica set 설정이 되어있어 primary 로 연결되었다.

 

+) compact 명령어 실행 권한 에러

compact 명령어는 db의 관리자가 수행할수있는 명령어이다. 관리자 권한이 아닌 상태에서 명령어 실행시 에러가 발생한다.

replica:PRIMARY> db.runCommand( {compact : '{target Collection}', force : true} )
{
	"ok" : 0,
	"errmsg" : "command compact requires authentication",
	"code" : 13,
	"codeName" : "Unauthorized",
	"$clusterTime" : {
		"clusterTime" : Timestamp(~~~, ~~),
		"signature" : {
			"hash" : BinData(0,"~~~"),
			"keyId" : NumberLong("~~")
		}
	},
	"operationTime" : Timestamp(~~~, ~~)
}

 

때문에 대상 db로 들어가 관리자로 접속후 진행해야 한다.

현재 관리자 user 생성된게 없어서 먼저 생성부터 해준다. shell 에서 생성해주려나 authentication error 가 발생하는데 이부분은 어떻게 생성하는지 방법을 몰라서 mongodb tool 에서 해당 db의 users 항목에서 add 해주었다.

db.createUser(
   {
     user: "dbAdmin", pwd: "password", roles: [{"role":"dbAdmin","db":"targetDB"}]
   }
)

 

이후 다시 mongo shell 에서 어드민 권한을 사용해 compact를 수행하준다.

replica:PRIMARY> use {작업할 DB명 : 이하 targetDB}
switched to db targetDB
replica:PRIMARY> db.auth('dbAdmin123123', 'password')
Error: Authentication failed.
0  # 접속 실패
replica:PRIMARY> db.auth('dbAdmin', 'password')
1  # 접속 성공

1 이 나오면 관리자 권한으로 연결됐단 뜻이다.

 

이후 compact 명령어를 실행해준다. 시간이 오래 걸릴 경우 shell 이 멈춘것처럼 보이는데 이때 다른 터미널을 열어서 mongo 용량을 확인해보면 실시간으로 용량이 줄어드는걸 볼 수 있다 ㅎㅎ

replica:PRIMARY> db.runCommand( {compact : '{target Collection}', force : true} )
{
	"bytesFreed" : ******,
	"ok" : 1,
	"$clusterTime" : {
		"clusterTime" : Timestamp(***, *),
		"signature" : {
			"hash" : BinData(0,"******"),
			"keyId" : NumberLong("******")
		}
	},
	"operationTime" : Timestamp(***, *)
}
# 작업 후 db 용량
Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme0n1p1  310G  266G   45G  86% /

 1 기가 줄었군......................

 

이후로도 계속 작업을 진행해준다. 보다 상세한 비교를 위해 compact 수행 전 collection의 stats를 확인해보고 명령어 실행 이후와 함께 비교해 보았다.

확인 할 부분은 "storageSize" 이다. 데이터를 삭제하기 전과 용량이 동일하게 잡혀있다.

compact 명령어 실행 이후는 아래와 같다.

7.5GiB 로 용량이 줄어들었다!

전체 db 용량도 확인해보니 259GiB로 확인된다.

[ec2-user@ip-*** ~]$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme0n1p1  310G  259G   52G  84% /

 

임무 완료!

반응형

+ Recent posts