home

컨텐츠 동기화 성능 개선 이야기

안녕하세요. 저는 아이들나라 CMS(Contents Management System) 도메인 담당 백엔드 개발자 이다혜입니다.
최근 일하면서 겪었던 데이터 동기화 모듈 성능 튜닝과 관련한 경험을 공유하고자 이 글을 작성했습니다.
현업의 백엔드 엔지니어분들, 특히 카프카 메시지 Pub/Sub 구조로 데이터 동기화 작업을 하시는 분들에게 도움이 되었으면 하네요ㅎㅎ 
그럼 이제 이야기를 본격적으로 시작하겠습니다.

배경 및 발단

현재 저희 아이들나라 컨텐츠 동기화 시스템 아키텍처는 다음과 같습니다.
기존 아이들나라 Legacy 시스템을 하나씩 내재화하면서 서비스 운영에 영향을 주지 않으려고 하다보니 위와 같은 구조로 설계했는데요.
실제 CMS 시스템에 아이들나라 컨텐츠 데이터가 적재되기 까지는 총 2개의 파이프라인을 거치게 됩니다.
첫 번째는 TV 플랫폼 전용 파이프라인입니다. 여기서는 컨텐츠 저장소로부터 동기화 한 컨텐츠 정보를 TV 플랫폼 전용 카프카 메시지 큐에 발행합니다. 이렇게 발행한 카프카 메시지는 아이들나라 플랫폼 data sync application에서 consume하여 두 번째 파이프라인을 거칩니다. 이 때는 실제 서비스 운영중인 시스템에 전달할 컨텐츠 정보를 카프카 메시지로 발행합니다. 이렇게 발행된 메시지를 저희가 운영중인 CMS 시스템이 consume함으로써 업데이트되는 새로운 아이들나라 컨텐츠를 동기화하여 사용자에게 제공하고 있습니다.
그러던 어느 날, 모니터링 알람에서 별다른 특이점이 발견되지 않았음에도 불구하고 현업으로부터 컨텐츠 저장소에서 편성되는 디즈니러닝+ 6차월 VOD 컨텐츠가 CMS 관리자 화면에서 확인되지 않는다는 제보를 전달받았습니다. 실제로 관리자 화면 및 CMS DB에서도 해당 컨텐츠들이 확인되지 않고 있었습니다.

원인

해당 이슈의 원인을 찾기 위해 다음과 같이 접근했습니다.
가장 먼저, CMS 시스템 전체 서버를 점검했습니다. 모니터링 툴로 빌드/배포 및 네트워크 등에서 에러가 발생한 구간이 있는지 탐색한 결과 특별한 로그 혹은 이벤트는 보이지 않았습니다.
그 다음, 아이들나라 컨텐츠 정보를 동기화하는 구간의 이슈를 점검하였습니다. CMS 데이터 동기화 모듈 뿐만 아니라 아이들나라 플랫폼 그리고 TV 플랫폼 데이터 동기화 모듈까지 전체적으로 점검했습니다. 그 결과, 아이들나라 플랫폼에서 publish한 메시지가 저희 CMS 데이터 동기화 모듈에서 consume되고 있지 않은 현상을 발견하였습니다. 이때 당시, 초당 생성되는 Kafka 메시지 숫자가 약 1,000개로 CMS 데이터 동기화 모듈이 소비할 수 있는 최대 메시지 수를 훨씬 웃도는 메시지가 발행되어 생긴 문제였습니다. (새로고침하니 어느새 300만개 이상의 소비되지 않은 메시지가 큐에 쌓여있더군요…ㅎㅎㅎ)

해결

Why Kafka 메시지를 CMS 데이터 동기화 모듈에서 소비하고 있지 않은가? 라는 문제를 아래와 같이 세분화하여 해결하려고 시도했습니다.
파티션 할당이 제대로 되었는가?
당시 1:N 구조로 1개의 Topic에 총 3개의 Consumer Group이 할당되어 있었습니다(각각, 2:2:1로 총 Consumer 수는 5). 이때, 파티션의 개수도 1개였는데 다른 Consumer들과의 메시지 Read/Write 경쟁이 있을지도 모른다는 생각에 Partition의 개수를 1개 늘려 쌓인 메시지의 수가 감소하는 지 추이를 지켜보았습니다. (컨텐츠 관련 메시지의 경우는 순서 보장이 중요하지 않아, 운영 환경에서 파티션 개수를 늘리는 것에 큰 위험상황은 없었습니다.)
Kafka Topic의 파티션 개수가 늘어날수록 각각의 Consumer들은 메시지를 병렬적으로 처리가 가능하여 성능 향상이 있을 수 있습니다. 하지만 과도하게 생성할 경우 오히려 성능 저하 이슈가 있을 수 있기에 생성 전에는 신중한 고려가 필요합니다.(한번 생성한 파티션은 삭제가 불가능하기에 더더욱 주의해야할 것으로 보입니다.)
파티션의 개수를 늘렸음에도 여전히 Kafka 메시지 큐에는 지속적으로 쌓였고, 소비하는 속도가 따라잡지 못하고 있었습니다. 컨텐츠 동기화 어플리케이션 서버 리소스 부족으로 인하여 발생하는 이슈인가 싶어서 pod 개수도 하나 증가시켜 성능을 높여보았으나 처리량에 큰 변화는 없었습니다. 그래서 다른 방향으로 문제 해결을 접근해보았습니다.
어떤 타입의 Kafka 메시지가 소비되고 있지 않은 것인가?
모니터링 툴인 datadog에 남겨진 아이들나라 컨텐츠 동기화 서버 로그 정보를 기반으로 어떤 메시지가 소비되고 있지 않은지 분석하였습니다. 그 결과, 모든 타입의 메시지가 정상적으로 소비되고 있었으나 아이들나라 컨텐츠 정보 업데이트 메시지 하나를 소비하는 데 지연이 발생하고 있었습니다.
Why 아이들나라 컨텐츠 정보 수정에서 지연이 발생하는가?
이에 대하여 총 두 가지의 결론을 도출하였습니다. 첫째, 메시지 소비 과정에서 발생하는 HTTP request로 인한 처리시간 증가. 수정된 컨텐츠 관련 메시지를 동기화 모듈에서 소비하여 처리할 때마다 이미지 파일 업로드를 위한 HTTP 요청이 발생하고 있었습니다. 둘째, 불필요한 CMS DB Read/Write. 소비한 메시지 중에서는 실제로 CMS DB에서 데이터 수정이 불필요함에도 불구하고 Read/Write를 위하여 Transaction을 생성하고 있었습니다. 이에 대하여 저희는 다음과 같이 순차적으로 튜닝하였습니다.
1차 튜닝: 실제 이미지 파일 변경이 일어나는 메시지에 대해서만 이미지 파일 업로드 작업을 하도록 조건문을 추가하였습니다. 1차 튜닝 후에는 아래와 같이 이전과 달리 약 4배 이상 메시지 처리 성능이 개선된 것을 확인할 수 있었습니다.
2차 튜닝: 1차 튜닝에서는 특정 Kafka 메시지 유형 검증을 위한 조건 처리를 했다면 이번엔 실제 컨텐츠 데이터 변경이 있는 Kafka 메시지에서만 DB Transaction을 생성하도록 비즈니스 로직을 개선하였습니다. 결과적으로, 1차 튜닝 때보다 데이터 동기화 모듈의 성능이 2배 이상 개선되었습니다.
Kafka 메시지 큐에 쌓여있던 메시지를 소비하는 데까진 약 12시간 정도 걸렸던 것으로 측정됩니다. 이슈가 있던 다음날 오전 컨텐츠 저장소에서 편성되는 디즈니러닝+ 6차월 VOD 컨텐츠 데이터가 CMS DB에 저장되는 것을 확인하였고 관리자 화면에서도 정상적으로 보여지고 있었습니다.

앞으로는

이번 경험을 통해 개인적으로 현재 아이들나라 컨텐츠 동기화 시스템에 대하여 아래와 같은 생각을 했습니다.
해당 이슈가 발생하게 된 근본적인 원인은 컨텐츠 동기화 모듈을 설계할 당시, 대량 컨텐츠 데이터 관련 Kafka 메시지가 발행될 것이라고 예측하지 못한 데에서 시작되었다고 봅니다. 그래서 기존 Legacy 시스템을 분석/조사할 때 정말 다양한 케이스 시나리오를 세워야 함을 배웠습니다 또, 이런 이벤트성 대규모 메시지 발행이 있을 시에는 반드시 관련 부서에 공지를 해줘야한다는 것을 절실히 느꼈습니다. 대량의 Kafka 메시지 발행에 대한 적절한 커뮤니케이션이 있었다면 위 이슈에 대하여 사전에 충분히 대비할 수 있었을 것으로 보입니다. 마지막으로는 이런 이슈가 발생했을 때 사용자가 인지하기 전에 엔지니어가 먼저 확인할 수 있는 방법이 없을 지 찾아봐야겠다고 생각했습니다. 현재 아이들나라에는 모니터링 툴이나 슬랙 알람 등으로 어느 정도 시스템 이상을 감지할 수 있는 체계가 잡혀있는 상황입니다. 여기에 위와 같은 이상 징후를 감지할 수 있는 알람 지표가 있다면 더 안정적으로 서비스 운영을 할 수 있지 않을까 싶습니다.
Rebalance에 대하여 생각해보는 시간을 가졌습니다. Consumer Group 내에서 하나의 컨슈머가 다운될 경우 파티션 재조정을 통해 다른 컨슈머가 이어서 파티션 메시지를 소비할 수 있도록 하는 전략이라고 이해했는데요. 현재 CMS 데이터 동기화 Consumer Group의 경우 오직 1개의 컨슈머만 존재하는 상태인데, 혹시 모를 장애에 대응하고자 Rebalancing을 위한 하나의 컨슈머를 추가하는 것이 좋을 수도 있겠다는 생각이 듭니다. (Rebalacing 전략을 취할 경우, 파티션 재할당 시 재할당이 끝날 때까지 다른 컨슈머들도 무한 대기 상태에 있어야 한다는 점에서 trade-off를 잘 따져봐야할 것 같습니다.)
이렇듯 저희는 기존 Legacy 시스템을 내재화하고 운영하면서 다양한 문제 상황을 맞닥뜨리며 하루하루 성장해가고 있습니다.
아이들나라에서 이런 경험을 통해 성장하고 싶으신 분 혹은 이런 문제에 대한 더 멋진 해결책을 제시하여 더 나은 키즈 OTT 서비스를 만들고 싶으신 분은 언제든 지원해주세요!
저희는 여러분을 기다리고 있답니다 긴 글 읽어주셔서 감사합니다~