대규모로 옵저버빌리티를 실행한다는 것은 매초마다 수백만 개의 스팬, 트레이스 및 메트릭이 포함된 엄청난 양의 텔레메트리 데이터 스트림을 처리한다는 것을 의미합니다. 뉴렐릭이 고객에게 애플리케이션 및 인프라 성능에 대한 실시간 인사이트를 제공하려면 이러한 데이터가 필요합니다. 하지만 실시간으로 방대한 데이터를 수집하고 처리하려면 많은 비용이 듭니다. 특히 분산 추적 파이프라인의 핵심인 Redis 같은 고성능 시스템이 관련된 경우는 더욱 그렇습니다.
분산 추적은 여러 서비스에 걸쳐 요청을 추적하여 전체 분산 시스템에서 오류나 성능 저하의 근본 원인을 찾는 데 도움이 됩니다. 뉴렐릭의 분산 추적 파이프라인 팀은 여러 에이전트의 트레이스 데이터를 수집, 변환, 연결 및 요약하는 시스템을 관리합니다. 이 팀은 작년에 전체 아키텍처를 간소화하고 운영상의 복잡성을 줄여주는 새로운 파이프라인을 출시했습니다. 재설계를 통해, 뉴렐릭은 기존 서비스를 폐기하고, 책임을 더 작고 명확하게 정의된 구성 요소로 통합했습니다. 무엇보다 중요한 점은 무한 추적(Infinite Tracing)과 표준 분산 추적을 모두 단일 통합 파이프라인을 통해 실행할 수 있게 되었다는 것입니다. 그 결과, 변동 가능한 구성 요소가 줄어들어 더 깔끔하고, 유지 관리가 쉬우며, 더 안정적인 시스템이 탄생했습니다. 하지만 출시 직후, Redis 스토리지 및 네트워크 비용이 상당히 증가한 것을 발견했습니다.
뉴렐릭은 자체 플랫폼을 사용해 자사에서 구축한 모든 것을 모니터링합니다. 그래서 비용이 급증하자 뉴렐릭 플랫폼에서 데이터를 분석했습니다. 그 다음에는 두 단계로 구성된 최적화 과정을 진행했습니다. 먼저, 클러스터를 업그레이드하고 적절한 크기로 조정하여 Redis 인프라를 조정한 다음, 데이터를 저장하는 방식을 재고해 압축과 메모리 사용을 훨씬 더 효율적으로 만들었습니다.
이 블로그에서는 그 여정을 살펴보려고 합니다. 무엇을 바꾸었고, 무엇을 배웠는지, 그리고 그러한 변화를 통해 어떻게 Redis 비용을 절반 이상 절감하고 전반적인 성능과 확장성을 개선했는지 알려드리겠습니다.
인프라 최적화
처음 비용이 급증했음을 발견했을 때, 먼저 중점을 둔 부분은 인프라 수준에서 효율성을 개선하는 것이었습니다. Redis 설정을 성능과 비용 측면에서 최대한 최적화 하고자 했습니다.
바로 두 가지 조치를 취했습니다.
더 나은 인스턴스 유형으로 마이그레이션 했습니다.
Redis 클러스터를 최신 버전으로 업그레이드하고 인스턴스 유형을 m6에서 r6g로 변경했습니다. 두 인스턴스 유형 모두 동일한 세대의 ARM 기반 EC2 인스턴스에 속하지만, r6g는 메모리가 최적화되어 있습니다(vCPU당 8GB RAM, m6g에 4GB). 몇 달 동안 새로운 파이프라인을 실행한 결과, 메모리 사용률에 비해 CPU 사용률이 매우 낮다는 것을 발견했습니다. m6에서 r6g로 전환하자 처리량을 그대로 유지하며 클러스터의 노드 수를 줄일 수 있었고, 대용량 데이터를 간단한 Redis 워크로드에 더 적합하게 만들 수 있었습니다. 이러한 변화는 Redis 버전을 업그레이드하여 Redis 7.x에서 제공되는 향상된 안정성과 운영 개선 사항을 활용할 수 있는 완벽한 기회이기도 했습니다.
Redis 클러스터의 적정 규모를 산정했습니다.
여러 프로덕션 셀에서 Redis 클러스터는 트래픽 급증을 처리하기 위해 의도적으로 더 큰 규모로 설정되어 있었습니다. 이를 통해 여유분을 확보하긴 했지만 불필요한 비용이 발생했습니다. 인프라 AWS 통합에서 얻은 텔레메트리 데이터를 사용하여 사용 패턴과 메모리 소비를 분석했습니다. 이러한 인사이트를 바탕으로, 안전한 성능 마진을 유지하면서 실제 사용량에 맞춰 클러스터를 수동으로 축소했습니다.
이 두 단계를 통해 최적화, 비용 절감, 리소스 활용도 향상이라는 첫 번째 최적화가 이루어졌습니다. 이 과정에서 Redis에 데이터를 저장하는 방식에서 또 다른 개선 영역을 발견했고, 이는 이후 훨씬 더 규모가 큰 최적화 작업의 기반이 되었습니다.
데이터 저장 방식을 재고한 이유
Redis 인프라를 최적화한 후에는 뉴렐릭을 사용해 다양한 환경에 변경 사항을 적용하면서 성능을 면밀히 주시했습니다. 모든 것이 정상적으로 보였습니다. 즉시 비용이 개선되었고, 메모리 및 네트워크 사용량은 유입 데이터 양에 대해 예상했던 수준과 일치했습니다.
하지만 뉴렐릭은 항상 시스템의 효율성을 높일 수 있는 방법을 찾고 있습니다. 그러한 탐구의 일환으로 Redis에서 데이터가 어떻게 저장되는지를 연구하던 한 엔지니어가 스팬(span) 데이터가 압축되는 방식과 관련해 흥미로운 점을 발견했습니다.
트레이스 파이프라인은 Kafka 배치당 여러 개의 스팬을 수신하고 트레이스 키별로 그룹화한 다음 해당 스팬을 Redis에 푸시합니다. Redis에서 각 트레이스 키는 스팬 목록에 매핑되며, 저장을 위해 메모리 내 오브젝트를 직렬화할 때 Redis 클라이언트가 이를 압축해줍니다.encodedTraceKey: String = [non-empty list of compressed spans: ByteArray]
이렇게 하면 각 스팬이 Redis로 푸시되기 전에 압축됩니다.
설정은 의도한 대로 작동했고 각 스팬은 저장 전에 압축되었지만, 엔지니어들은 최적화의 여지가 있는지 의문을 품기 시작했습니다. 개별 스팬을 저장하는 대신, 여러 스팬을 한꺼번에 저장하면 어떨까? 그러면 압축을 더 효율적으로 만들고 저장 공간이나 메모리 오버헤드를 줄일 수 있지 않을까?
Redis 배치 작업을 통한 스토리지 재고
최적화의 기회를 인지한 후, 다음 단계는 여러 스팬을 그룹화하면 압축을 더 효과적으로 만들 수 있는지를 테스트하는 것이었습니다. 이는 Redis에서 데이터 표현을 개별 스팬 목록에서 직렬화된 스팬 목록으로 전환하는 것을 의미합니다. 이 새로운 구조에서는 여러 개의 스팬이 함께 저장되고 단일 단위로 압축되어, Redis에 쓰거나 읽는 페이로드의 수는 줄어들고 페이로드 크기는 커집니다. 그렇다면, 이러한 접근 방식은 압축을 더 효율적으로 만들고 Redis 운영 전반을 간소화할 수 있을 것이라는 가설을 세웠습니다.
이 가설을 검증하기 위해 엔지니어는 통제된 테스트를 실행해 배치 작업이 압축 효율성과 리소스 사용에 어떤 영향을 미치는지에 대한 실증적 데이터를 수집했습니다. 실험은 하나의 스테이징 셀과 하나의 프로덕션 셀에 구현되었고, 몇 시간 동안 실행되어 단일 스팬과 배치 스팬 스토리지 간의 압축 동작을 비교했습니다. 그 결과는 고무적이었습니다. 평균적으로 압축 효율성은 프로덕션 단계에서 약 20%에서 42%로 개선되었고, 스테이징 단계에서는 28%에서 52%로 개선되었습니다 .
셀 | 평균 배치 길이 | 평균 압축되지 않은 크기 | 평균 현재 압축 크기 | 평균 새 압축 크기 | 새로운 압축 비율 |
테스트 셀 02 | 9.96 | 11.1KB | 8.48KB | 2.14KB | 42.86% |
테스트 셀 02 | 5.08 | 6.88KB | 4.9KB | 1.46KB | 52.189% |
더 나아가, 트레이스 크기가 몇 개의 스팬에서 수천 개의 스팬에 이르는 것까지 매우 다양한 시나리오도 고려했습니다. 단일 스팬 트레이스를 고려하지 않으면 어떤 개선 사항이 있을지 궁금해졌습니다. 이러한 전제에 근거해 분석을 수행한 결과, 2개 이상의 요소로 구성된 배치의 경우 압축률이 약 68%로 향상되는 것을 발견했습니다.
이러한 결과는 배치 작업을 통해 Redis 메모리와 대역폭 사용량을 크게 줄일 수 있다는 확실한 증거를 제공했으며, 이를 통해 팀은 더 광범위한 테스트를 진행할 수 있는 자신감을 얻었습니다.
영향 측정
Redis 배치 작업이 구현된 후, 스테이징에서 시작하여 프로덕션으로 옮겨가며 점진적으로 여러 환경으로 확장했습니다. 롤 아웃은 기능 플래그를 통해 완벽하게 제어되었으며, 실시간으로 결과를 모니터링하면서 안전하게 배치 작업을 활성화하거나 비활성화할 수 있었습니다. 뉴렐릭 대시보드를 사용해 배포의 각 단계에서 Redis 메모리 사용량, 네트워크 트래픽 및 전반적인 시스템 성능을 추적했습니다.
그리고 그 결과는 우리를 실망시키지 않았습니다. 뉴렐릭의 데이터 수집은 셀룰러 아키텍처에서 작동합니다. 수집된 데이터는 여러 개의 서로 다른 독립 클러스터(또는 셀)로 나누어 진다는 의미입니다. 그래서 셀 수준에서도 결과를 측정했습니다. 여기에 표시된 데이터는 단일 스테이징 셀에서 나온 것으로, 예상되는 성능 향상을 명확하게 보여줍니다. 해당 셀에서 Redis 메모리 사용량이 크게 감소했으며, 클러스터 전체에서 사용된 최대 메모리는 66%가 감소했습니다. 서비스 간 네트워크 트래픽도 같은 방식으로 개선되어 66% 감소했습니다.
분산 추적 파이프라인이 전반적으로 안정되게 수행되어 안정성이나 처리량을 저하시키지 않고도 효율성을 크게 향상할 수 있음을 확인한 것입니다.
핵심 내용
이러한 최적화 과정은 아키텍처를 조금 조정하는 것만으로도 비용과 성능을 상당히 개선할 수 있음을 보여주었습니다. 세부적인 옵저버빌리티 데이터와 데이터가 저장되고 전송되는 방식에 대한 신중한 검토를 결합함으로써, 우리는 효율성을 높일 수 있는 간단하면서도 큰 영향을 미치는 기회를 발견했습니다.
- 인프라의 기본 요소부터 시작해야 합니다. 더 나은 인스턴스 유형으로 업그레이드하고 클러스터 크기를 적절하게 조정하면, 심도 있는 코드 변경 없이도 빠르게 성과를 얻을 수 있습니다.
- 인프라 너머를 봐야 합니다. 때로는 데이터 표현이 하드웨어 만큼이나 중요한 경우가 있습니다. 뉴렐릭의 경우, 단일 스팬 압축에서 일괄 압축으로 전환하면서 Redis 사용량이 절반 이상 줄었습니다.
- 모든 것을 측정해야 합니다. 옵저버빌리티는 문제를 식별하고, 해결책을 검증하고, 영향을 정량화하는 데 중요한 역할을 했습니다.
뉴렐릭은 고객을 돕기 위해서 뿐만 아니라 자체 시스템들의 운영 방식을 지속적으로 개선하기 위해서 옵저버빌리티를 적용합니다. 이번 경험을 통해, 코드부터 인프라까지 모든 계층에 대한 가시성이 대규모의 지속 가능한 성능의 기반이 된다는 사실을 다시 한번 확인할 수 있었습니다.
결론
큰 변화 한번으로 규모에 맞게 비용이 최적화되는 경우는 드뭅니다. 시스템의 각 계층이 성능에 어떻게 기여하는지 이해하고, 이러한 상호작용을 보다 효율적으로 만드는 실질적인 방법을 찾는 것이 중요합니다. 인프라 조율과 데이터 저장에 대한 보다 스마트한 접근 방식을 결합함으로써, 우리는 Redis 메모리와 대역폭 사용량을 66% 줄이고 연간 비용을 절반으로 절감할 수 있었습니다. 안정성이나 성능은 그대로 유지되었습니다.
이 경험은 또한 일상적인 설계를 재검토하는 것에서 의미 있는 성과를 얻는 경우가 많다는 사실을 보여주었습니다. 동일한 접근 방식을 모든 대규모 시스템에 적용할 수 있습니다. 여러분도 뉴렐릭에서 Redis와 스토리지 메트릭을 직접 살펴보면, 숨겨진 비슷한 기회를 발견할 수 있을 것입니다.
이 블로그에 표현된 견해는 저자의 견해이며 반드시 New Relic의 견해를 반영하는 것은 아닙니다. 저자가 제공하는 모든 솔루션은 환경에 따라 다르며 New Relic에서 제공하는 상용 솔루션이나 지원의 일부가 아닙니다. 이 블로그 게시물과 관련된 질문 및 지원이 필요한 경우 Explorers Hub(discuss.newrelic.com)에서만 참여하십시오. 이 블로그에는 타사 사이트의 콘텐츠에 대한 링크가 포함될 수 있습니다. 이러한 링크를 제공함으로써 New Relic은 해당 사이트에서 사용할 수 있는 정보, 보기 또는 제품을 채택, 보증, 승인 또는 보증하지 않습니다.