나는 일정 서비스 도메인을 담당하고 있는 백엔드 개발자이다. 이 글에서는 시간에 따른 MySQL의 잔여 용량을 계산하는 법, 스프링 배치를 통하여 병렬적으로 테이블의 데이터를 제거하는 법, 이를 위하여 사전에 테스팅 환경에서 데이터의 생성과 삭제를 테스트하는 법을 공유한다.

현상

그라파나로 설정한 MySQL 데이터베이스 대시보드를 모니터링하던 중, 90% 이상을 유지하던 /mysql/data 의 잔여 디스크 용량이 특정일부터 빠르게 감소하여 84%에 도달한 현상을 발견했다.

원인

신규 기능의 출시가 원인이었다. 잔여 용량이 감소하던 날짜에 사용자가 직접 일정을 등록하지 않아도, 통화요약을 바탕으로 AI가 가-일정을 생성해주는 기능을 출시했다. AI가 1일 80만건에 달하는 많은 일정을 생성해주어서 MySQL 데이터베이스의 용량이 고갈되고 있었다.

본격적인 작업에 앞서 데이터베이스의 용량이 얼마나 빠르게 고갈되고 있는지 확인이 필요했다. 일단 서비스의 안정성을 담보하면서 최대한으로 사용할 수 있는 데이터베이스의 용량을 전체 용량의 70%로 잡았다. 우리가 사용하는 데이터베이스의 용량은 1.8TB 였으므로 1.26TB 의 용량이 사용가능했고, 현재 0.28 TB 의 용량을 사용하여 0.98 TB의 용량의 여유가 있었다. 데이터베이스 잔여용량 감소 추이를 보니 대략 1일에 8GB의 용량이 감소되고 있었다. 따라서 122.5일(980/8), 약 4달의 여유가 있다고 분석했다.

조치

시간적인 여유가 있으니 충분한 시간을 가지고 일정 삭제 배치 프로그램을 개발하기로 하였다. 먼저 기획측에 해당 상황을 알리고 삭제와 관련된 정책을 협의하였다. 현재 날짜로부터 3주이상 지난 AI가 생성한 일정에 사용자가 수정을 가하지 않았으면 삭제 처리를 하기로 정해졌다.

하루에 80만건에 달하는 일정을 삭제해야하기에 DB에 직접 접근하여 병렬적으로 삭제 쿼리를 날릴 수 있는 스프링 배치 프로그램을 작성하기로 하였다. 일정 생성, 수정, 동기화, 삭제 등 도메인에서 요청하는 다른 기능들이 작동하고 있었기 때문에, 삭제 배치의 속도를 조정할 필요가 있었다. 적절한 삭제 속도를 찾기 위하여 준상용 환경에서 테스트 일정의 생성과 삭제 성능 테스트를 진행해야 했다.

테스트 데이터 생성

먼저 테스트 일정의 생성의 경우에는 자바 스크립트 기반의 성능 테스트 툴인 k6를 사용했다. 이전 성능 테스트에서는 Jmeter나 locust 를 통하여 테스를 진행했다. 그러나 이번 테스트에서는 Jmeter처럼 UI를 활용하지 않고 코드만을 바탕으로 테스트를 진행할 수 있다는 점, 이미 MySQL 모니터링을 통하여 사용하고 있는 그라파나에 친화적이라는 점에서 k6로 테스트를 진행하였다. 최근에도 지속적으로 업데이트가 이루어지고 있다는 점도 k6를 선택한 이유중 하나였다. 테스트에 사용한 코드는 대략 다음과 같았다.

코드 설명,

테스트 결과

시간 vuser iter TPS CPU Usage Acquired Connections 비고
2024/09/30 10:37 10 10 251.310663/s 46% 10 vuser, iter는 적으나 최초 성능 테스트이기에 CPU Usage가 높았던 것으로 보임.
2024/09/30 10:41 10 10 281.260879/s 34% 9  
2024/09/30 10:51 20 10 465.458234/s 56% 18  
2024/09/30 11:28 40 10 691.320196/s 77% 38  
2024/09/30 13:24 60 10 832.700391/s 87% 57  
2024/09/30 13:38 80 10 927.098068/s 91% 77  
2024/09/30 13:52 100 10 984.282038/s 93% 94  
2024/09/30 14:49 120 10 1001.252083/s 93% 100  

테스트를 위하여 이중화되어 있는 서버의 분리. 코드 파라미터 설명과 충분한 부하를 주어야 한다.

삭제 성능 테스트

4코어의 CPU, 8GB의 메모리 30GB의 디스크 용량인 배치용 서버에서 스프링 배치 프로그램을 작성하여 테스트를 수행한 결과는 다음과 같

시작 시간 실행 시간 대상건수 chunk size fetch size parallelism 배치 파라미터
2024/10/02 오후 4:55 2m 35s 51595 10000 1000 1 2024-09-30 10:45:01
2024/10/02 오후 5:00 1m 42s 40341 10000 1000 1 2024-09-30 10:50:01
2024/10/02 오후 6:12 1m 56s 50080 10000 10000 1 2024-09-30 10:55:13
2024/10/02 오후 6:15 1m 41s 50200 10000 10000 2  2024-09-30 10:57:00
2024/10/02 오후 6:33 58s 49195 10000 10000  10 2024-09-30 11:03:06
2024/10/02 오후 6:40 3m 7s 99999 10000 10000 10 2024-09-30 11:31:32
2024/10/02 오후 6:53 11m 46s 399742 10000 10000 10 2024-09-30 13:27:00

상용 환경에서의 삭제 진행

결과