관제에서 평균값, 중앙값, 그리고 백분위

11 November 2019 · 2 minutes read

평균값(mean)의 문제

어떤 서비스의 관제 시스템은 지표를 1초 단위로 시계열 저장소에 수집한다고 가정해보자.

지표들을 시계열 그래프의 차트로 나타낸다면, 최근 한 시간 추이만 보려고 해도 하나의 지표당 3600개(1시간 = 3600초)의 데이터 포인트를 데이터베이스에서 조회하고 화면에 그려야 한다. 대부분의 시계열 저장소에서는 이를 위해 조회시 집계를 할 수 있도록 함수를 제공하고 있다.

일반적으로 많이 사용하는 것은 n초(혹은 분)간 평균값(mean)인데, CPU, RAM, Disk 등 서버 한 대에서 수집하는 리소스의 평균값은 대표값으로 사용하는데 큰 문제가 없다. (시간에 따른 값의 편차가 크지 않고 일시적으로 튄 데이터 포인트는 서버에 큰 위협이 없기 때문)

그런데 만약 요청 응답 시간과 같은 수치를 평균값으로 집계해서 그리면 어떻게 될까?

응답 시간이라는 하나의 지표이지만 다양한 클라이언트로부터 요청을 받아 처리하고, 응답을 보내는데까지 걸리는 시간은 클라이언트마다 편차가 클 것이다. 편차가 크면 수치가 고르게 분포되어 있지 않을 것이고 특정 구간에서 크게 튀는 값들은 적당한 값으로 다운샘플링 될것이다. 즉, 평균 30ms의 응답 시간으로 보이는 지표에서, 사실 일부 클라이언트는 2000ms가 넘는 지연 시간을 보일 수 있는 것이다.

이렇듯 일부 항목에 대해서 발생하는 이상 현상을 관제시 놓치지 않으려면 백분위수(percentile)를 이용해야 한다.

백분위수(percentile)

백분위수는 수치 데이터를 정렬해서 나열했을 때, 백분율로 구간을 나누어서 수치의 위치를 기술할때 사용할 수 있다. (정의에 따라 50분위수는 중앙값(median)을 나타낸다)

위의 응답 시간의 예에서 100개의 응답 시간 수치 데이터가 있다고 가정해보자. 이를 정렬해서 나열하면 아래와 같은데,

response_time_milis = [20, 20, 20, 20, ..., 20, 2000]

99개의 수치는 20ms이고 한 개의 수치가 2000이라는 100배 큰 값을 나타내고 있다. 평균값으로 이 수치 데이터를 나타내면 (20ms * 99 + 2000ms)/100 = 29.9ms로 나오게 된다.

하나의 요청이 비정상적인 응답 시간을 보였지만 약 30ms 수치로 완벽히 가려져버렸다. 이 예제에서는 하나의 요청에 해당한 것이지만, 수치 데이터의 크기가 커질 수록 다른 요청에 비해 100배가 넘는 응답 시간을 보이는 비정상 응답 수도 훨씬 증가할 것이다.

여기에서 2000은 99분위수 구간 이후에 위치한다. 상위 1% 데이터는 2000ms 이상의 응답 시간을 가진다고 할 수 있는 것이다. 따라서 99분위수를 시계열 그래프에 그리면 상위 1% 데이터의 최소 응답 시간에 대한 분포를 볼 수 있다.

이제 일부(상위 몇 퍼센트까지)가 얼마나 비정상적인 값들을 보이는지 알 수 있게 된다.

이러한 특성 덕분에 백분위수는 성능 테스트를 할때에도 유용하게 쓰일 수 있다.

Updated 11 November 2019