
지난 글에서는 Redis 인스턴스가 느려지는 것을 방지하기 위한 주제와 접근 방식을 다뤘습니다. 이번에는 성능을 측정하는 방법을 살펴보겠습니다.
무엇을 측정해야 할까?
이번 글의 초점은 명령 지연 시간(latency)과 그 구성 요소입니다. 그 이유는 간단합니다. Redis 서버나 라이브러리가 처리할 수 있는 명령 수, 즉 처리량은 결국 개별 명령 하나하나의 실행 속도에 따라 결정되기 때문입니다.
가장 빠르고 간단한 방법: CLI
명령 지연 시간을 확인하는 첫 번째 방법은 명령줄 클라이언트인 redis-cli를 사용하는 것입니다. 빠르게 즉각적인 기준점을 확보할 수 있습니다. 여기서는 설명의 편의상 localhost를 사용하지만, 실제 환경에서는 -h <host> 옵션과 필요에 따라 -a <auth>, -p <port> 옵션을 함께 사용해야 합니다.
기본 지연 시간 측정
기본적인 지연 시간 결과를 얻으려면 redis-cli --latency를 실행합니다. 최소(min), 최대(max), 평균(avg), 반복 횟수를 나타내는 숫자들이 출력됩니다. 이 반복은 열려 있는 연결을 대상으로 Redis PING 명령을 실행하는 방식으로 이루어집니다. 따라서 서버에 접속하는 데 걸리는 시간은 포함되지 않습니다. 만약 코드가 매번 명령을 실행할 때마다 새로 연결한다면 이 명령이 보여주는 것보다 훨씬 나쁜 성능을 경험하게 될 것입니다.
이 명령은 CTRL-C로 종료할 때까지 계속 실행됩니다. 지연 시간 단위는 밀리초(ms)이며, 다음과 같은 결과는:
min: 0, max: 1, avg: 0.11 (11369 samples)최소 지연 시간이 1밀리초 미만, 최대가 1밀리초, PING당 평균 지연 시간이 0.11밀리초라는 의미입니다. 물론 이것은 localhost 연결 결과이며, 11,369개의 '샘플', 즉 PING 명령으로부터 계산된 값입니다.
대신 --latency-history 옵션을 사용할 수도 있습니다. 이 옵션은 결과를 시간 단위로 나누어 보여줍니다. redis-cli --latency-history를 실행하면 기본적으로 15초 윈도우가 적용되며 결과는 대략 다음과 같습니다:
min: 0, max: 1, avg: 0.11 (1475 samples) -- 15.01 seconds range
min: 0, max: 1, avg: 0.10 (1474 samples) -- 15.01 seconds range--latency와 마찬가지로 이 명령도 강제로 종료할 때까지 실행됩니다. 다른 간격으로 실행하고 싶다면 -i 옵션을 사용하면 됩니다. 예를 들면 다음과 같습니다:
redis-cli --latency-history -i 10
min: 0, max: 1, avg: 0.11 (984 samples) -- 10.01 seconds range
min: 0, max: 1, avg: 0.11 (983 samples) -- 10.01 seconds range
min: 0, max: 1, avg: 0.11 (983 samples) -- 10.01 seconds range이 작업들은 단순히 PING 명령을 사용하므로 어떤 버전의 Redis에서도 동작합니다.
고유 지연 시간(Intrinsic Latency)
이름만 보면 intrinsic latency 모드가 서버 자체의 고유 지연 시간을 측정할 것 같지만 실제로는 그렇지 않습니다. GitHub의 redis-cli 소스 코드를 살펴보면 서버와 통신조차 하지 않는다는 것을 알 수 있습니다:
start = ustime();
compute_something_fast();
end = ustime();
latency = end-start;intrinsic latency 모드에 대한 소스 주석은 다음과 같습니다:
시스템 콜(syscall)로 인한 것이 아닌, 실행 중인 프로세스의 최대 지연 시간을 측정합니다. 기본적으로 이 소프트웨어는 커널이 프로세스에게 실행 기회를 주지 않는 시간이 어느 정도인지에 대한 힌트를 제공합니다.
즉, 이것은 클라이언트 호스트에서 고유 지연 시간을 테스트하는 것입니다. 문제가 실제로 클라이언트 쪽에 있는지 아니면 서버 자체에 있는지 파악하는 데 유용합니다.
유용하지만 지연 시간 확인의 첫 단계로 삼기에는 적합하지 않을 수 있습니다. 업데이트: Salvatore와 논의한 결과, 이 명령은 서버에서 실행하도록 의도된 것임이 확인되었습니다. 즉, Redis 서버에 셸 접근 권한이 있다면 유용하지만, 그렇지 않다면 큰 도움이 되지 않습니다. 관리형 Redis 서비스를 사용하는 경우가 흔한데, 이런 경우에는 해당됩니다.
Commissar 사용하기
Commissar는 Redis 지연 시간과 전반적인 성능을 추적·테스트하기 위해 필자가 개발 중인 작은 도구 모음입니다. 경고: 아직 초기 개발 단계이며 많은 부분이 변경될 가능성이 높습니다. 따라서 비프로덕션 수준의 소프트웨어 사용이 부담스럽지 않은 경우에만 사용하세요. Commissar는 GitHub의 Commissar 저장소에서 찾을 수 있습니다.
이 글에서는 특히 latency 도구/디렉터리를 살펴보겠습니다.
이 도구는 환경 변수로 설정되며, 지정된 Redis 인스턴스에 연결하여 redis-cli와 동일한 'PING 명령 시간 측정' 메커니즘을 실행합니다. 테스트 조건의 일관성을 유지하기 위해서입니다. 차이점이라면 더 많은 정보를 출력하고 (현재는) MongoDB에 저장할 수 있다는 점입니다. 앞으로 더 많은 저장소가 추가될 예정입니다.
latency 실행 결과는 다음과 같을 수 있으며, 이 글 작성 이후 출력 형식은 변경되었을 수 있습니다:
./latency
Connected to <host:ip>
100000 iterations over 53698us, average 536us/operation
Percentile breakout:
====================
99.00%: 3,876.99us
95.00%: 640.00us
90.00%: 514.00us
75.00%: 452.00us
50.00%: 414.00us
Min: 243us
Max: 44,686us
Mean: 536.98us
Jitter: 764.37us이 실행에서 시간 단위는 'us'(마이크로초)임에 주목하세요. 또한 백분위수(percentile) 분석 결과도 함께 제공됩니다. 단순한 min/max/avg보다 지연 시간의 전체적인 분포를 훨씬 잘 파악할 수 있습니다. 여기서 'Jitter'는 샘플의 표준편차를 의미합니다.
이 출력은 전반적으로 상태가 양호함을 보여줍니다. 이 예제는 사설 네트워크를 통한 결과입니다. 최대치가 평균보다 훨씬 높지만, 반복의 95%는 640마이크로초 이하로 처리되었습니다. 이것이 의미하는 바는 무엇일까요?
간헐적인 네트워크 문제, 간헐적인 서버 측 지연, 또는 테스트 클라이언트의 가비지 컬렉션 같은 요인이 결과에 영향을 줄 수 있다는 신호일 수 있습니다. 바로 이런 이유로 요청 분포 정보가 제공되는 것입니다. '높은' 결과가 얼마나 자주 발생하는지 확인할 수 있기 때문입니다.
문제의 위치를 파악하려면 먼저 서버에서 명령이 실행되는 데 걸리는 시간을 확인해야 합니다. 이를 통해 서버가 원인인지 판단할 수 있습니다.
예를 들어 이 경우 redis info 출력을 확인하면서 특히 Commandstats 섹션을 살펴볼 수 있습니다:
redis-cli info commandstats
# Commandstats
cmdstat_ping:calls=32497193,usec=22213723,usec_per_call=0.68여기서 서버에서 PING을 실행하는 평균 시간이 0.68마이크로초임을 알 수 있습니다. PING 명령 자체가 원인일 가능성은 낮아 보입니다. 하지만 테스트 중에 실행된 다른 명령들이 Redis 프로세스에 부하를 일으켜 지연을 발생시켰을 가능성은 있습니다.
latency 도구에 최근 추가된 기능은 동시(concurrent) 지연 시간 테스트입니다. LATENCY_CLIENTCOUNT 환경 변수를 설정하면 Redis 서버에 여러 연결을 맺고 동시성이 지연 시간 결과에 어떤 영향을 주는지 확인할 수 있습니다. 예를 들어 클라이언트가 10개일 때와 100개, 심지어 1000개일 때 단순한 Redis PING 명령의 성능 차이를 비교할 수 있습니다. 이는 개발/스테이징 환경과 운영 환경 사이에서 겪을 수 있는 성능 차이를 이해하는 데 유용합니다.
컨테이너에서 테스트하기
Docker 컨테이너에서 테스트를 실행하고 싶으신가요? 이제 golatency 도구만 포함된 빌드된 Docker 이미지를 공개 Docker 레지스트리에 배포하고 있습니다. docker pull therealbill/golatency를 실행하면 몇 초 만에 실행할 준비가 된 이미지를 받을 수 있습니다(현재 이미지 크기는 4MB 미만입니다).
ReadMe에 안내된 대로 환경 변수를 지정하여 docker run을 호출하면 됩니다. 그런 다음 stdout에서 출력을 가져오거나, 데몬으로 실행한 경우 docker logs를 통해 결과를 확인하면 되고, 직접 빌드할 필요가 없습니다. 도구에 중요한 변경이 있을 때마다 Docker 저장소에 새 이미지가 업데이트됩니다. 또는 저장소에 Dockerfile이 포함되어 있으므로 원하는 대로 커스터마이즈할 수도 있습니다.
마치며
Redis 성능 분석은 까다로운 작업일 수 있습니다. 다행히 지연 시간과 처리량, 그리고 이것들이 애플리케이션에 미치는 영향을 제대로 이해하면 Redis 자체보다는 애플리케이션이 Redis를 사용하는 방식을 분석하는 데 집중할 수 있습니다. 'Redis Zen'의 문구인 "성능의 핵심은 Redis를 느려지게 하지 않는 것"을 마음에 새기고, 네트워크 문제를 격리하고 데이터 구조의 대안을 검토한다면 더 스마트하고 효율적인 애플리케이션을 만들 수 있으며, 그 결과 더 나은 성능을 얻을 수 있습니다.