Redis 성능 모니터링 및 튜닝

Redis 성능 모니터링 및 튜닝

개요

Redis는 인메모리 Key-Value 저장소로 성능 향상을 위한 cache 기능으로 많이 활용되고 있습니다. 성능을 위해 redis를 사용하는 만큼 성능 모니터링과 튜닝은 상당히 중요 요소입니다. 이 문서에서는 성능과 관련 된 Redis 아키텍처를 이해하고, 성능 모니터링 및 튜닝하는 방법에 대해 안내합니다.

Redis 아키텍처 특징

Single Thread

Redis Thread
그림. Redis Thread

Redis는 Single Thread로 동작하기 때문에 하나의 요청이 병목되면 이후 요청들도 계속 대기하게 됩니다. Packet 단위로 받아 하나의 command가 완성되면 실행되는 구조로 동작을 하기 때문에, 불필요하게 길게 수행되는 command (keys, hgetall)가 운영환경에서 자주 수행되는지 모니터링이 필요합니다.

SlowLog

Client 측면에서, 응답시간이 100ms ~ 300ms로 느리게 측정이 되는데 Redis 측면에서 SlowLog가 쌓이지 않는 경우가 있습니다. 이것은 Redis가 느리지 않다는 것인데, 정말 Redis가 빠르게 응답을 줬을까요? 결론부터 말씀드리면 Redis가 응답을 늦게 준 것입니다. 이것은 Redis가 SlowLog를 측정하는 구간이 달라서 발생하는 문제입니다.

Client 입장의 응답시간은 Redis를 호출하고, Redis의 응답을 받기까지의 시간을 의미합니다. 아래 그림에서 보면, ①에서 ②까지의 시간을 우리는 보통 응답시간 이라고 표현합니다. 그래서 이 시간이 100ms을 넘어가면 일반적으로 Client에서는 느리다고 인식합니다.

Process Command
그림. Process Command

Redis 입장에서 SlowLog는 아래 빨간색으로 표시한 Process Command 부분의 처리 시간만 가지고 SlowLog를 판단합니다. 따라서 Long Command가 실행 되는 경우 다른 request는 client queue에서 대기하게 되는데, 이렇게 대기하는 시간은 SlowLog 판단에서 제외됩니다. 그 결과 Client 응답시간은 느린데, Redis SlowLog는 쌓이지 않게 됩니다.

Process Command
그림. Process Command

Redis는 Single Thread이기 때문에 명령을 수행할 때 시간 복잡도를 필수적으로 고려해야 합니다. 여러 요청이 동시에 들어올 경우 하나의 작업 수행의 시간이 지연될 경우 이후의 요청 역시 지연되기 때문입니다. 따라서 O(N) 연산이 수행되는 command를 유의해야 하고 대표적인 command 사례는 다음과 같습니다. “ KEYS, FLUSHALL, FLUSHDB, Delete COlLECTIONS, Get All Collections “

Slow 명령어/오퍼레이션 모니터링

SlowLog

SlowLog는 모든 명령의 수행시간이 설정 시간 이상이면 기록을 남깁니다. 수행시간은 Redis에서 command가 처리하는 시간만 포함합니다. 명령이 Client에서 Redis로 도착하는 시간, 결과를 client에 보내는 시간은 포함하지 않습니다.

[설정 활성화 방법]
활성화는 redis.conf에 있는 두 가지 파라미터가 사용됩니다. config set 명령으로 동적으로 반영 가능하고, default로 활성화 되어 있습니다.

slowlog-log-slower-than: 
여기 설정한 시간(microseconds) 이상인 명령을 기록
단위는 microseconds
default는 10000(10ms)   
0(zero)으로 설정하면 모든 명령을 기록
비활성화하려면 음수(마이너스)로 설정

slowlog-max-len: 
여기 설정한 것만큼 보관합니다. default는 128입니다.
다 차면 오래된 것부터 지우고 새것이 기록됩니다.

[slow query 조회]
redis-cli > slowlog get 128

29) 1) (integer) 31            <- ID: 증가하는 일련번호
    2) (integer) 1660542153    <- 실행시각(Linux timestamp)
    3) (integer) 10859         <- 수행시간(microseconds)
    4) 1) "HGETALL"            <- 수행 command

조회 결과를 보면 HGETALL command가 10.859ms가 수행되고 있습니다. 해당 명령으로 전체 데이터를 다 가지고 오는데, HGET 로 필요한 데이터만 가져와서 처리 가능한지 검토를 해 볼 수 있습니다.

Latency Monitor

Latency Monitor(응답시간 모니터)는 시간을 microseconds로 설정해서, Redis에서 실행되는 명령/오퍼레이션의 수행시간이 설정한 시간 이상이면 기록해서 분석할 수 있는 Redis 성능 분석 도구입니다.

SlowLog와 차이는 command 상세를 보여 주지 않고, 아래 명령어/오퍼레이션 레벨로 데이터를 수집하는 것입니다.
https://redis.io/docs/reference/optimization/latency-monitor/

  • command: regular commands.
  • fast-command: O(1) and O(log N) commands.
  • fork: the fork(2) system call.
  • rdb-unlink-temp-file: the unlink(2) system call.
  • aof-fsync-always: the fsync(2) system call when invoked by the appendfsync allways policy.
  • aof-write: writing to the AOF - a catchall event for write(2) system calls.
  • aof-write-pending-fsync: the write(2) system call when there is a pending fsync.
  • aof-write-active-child: the write(2) system call when there are active child processes.
  • aof-write-alone: the write(2) system call when no pending fsync and no active child process.
  • aof-fstat: the fstat(2) system call.
  • aof-rename: the rename(2) system call for renaming the temporary file after completing BGREWRITEAOF.
  • aof-rewrite-diff-write: writing the differences accumulated while performing BGREWRITEAOF.
  • active-defrag-cycle: the active defragmentation cycle.
  • expire-cycle: the expiration cycle.
  • eviction-cycle: the eviction cycle.
  • eviction-del: deletes during the eviction cycle.

[설정 활성화 방법]
활성화는 redis.conf에 있는 한 개의 파라미터가 사용됩니다. config set 명령으로 동적으로 반영 가능하고, default로 비활성화 되어 있습니다.

latency-monitor-threshold: 
여기 설정한 시간 이상인 명령/오프레이션 을 기록
단위는 millisecons  
default는 0 으로 비활성화 되어 있음   

[latency 조회]
redis-cli > latency latest

1) 1) "command"             <- 이벤트명
   2) (integer) 1463729306  <- 마지막 명령 실행 시작 Linux timestamp
   3) (integer) 400         <- 마지막 명령 수행 응답시간(ms)
   4) (integer) 1000        <- 응답시간이 가장 큰(max) 시간

어떤 오퍼레이션이 느린지 확인 할 수 있는 장점이 있지만 command에 대해서는 상세 command는 확인 할 수 없음으로, SlowLog와 함께 사용하는 것이 좋습니다.

Client List

Redis에 접속된 Client의 정보와 통계값을 조회할 수 있습니다. 조회된 필드 중에 qbuf(쿼리 버퍼 길이)를 주의깊게 볼 필요가 있습니다. 앞에서 Redis는 Single Thread이기 때문에 long command가 실행되면, 나머지 command는 대기 한다고 설명했습니다. qbuf를 통해서 아직 처리되지 않고 대기하고 있는 데이터량을 확인 할 수 있습니다. qbuf가 계속해서 증가 하거나, 줄어 들지 않는다면 대기하고 있는 command가 많다고 판단할 수 있습니다.

redis-cli > client list 

성능 튜닝 파라미터

Persistence off

Redis는 In-Memory Cache로 모든 데이터를 Memory에 저장을 합니다. Redis 가 재기동시에도 데이터를 유지하기 위해서는 AOF(Append Only File) 또는 RDB(Redis Database) 방식을 설정 할 수 있습니다. AOF설정은 명령이 실행될때 마다 기록되는 파일입니다. 그러므로 데이터의 손실이 거의 없지만, 성능이 느려집니다. RDB 파일은 특정한 간격마다 메모리에 있는 Redis 데이터 전체를 디스크에 쓰는 설정입니다. 특정 시점 마다 백업을 받을 때 사용합니다. RDB 설정의 경우 AOF 설정보다 성능에 미치는 영향은 더 작습니다.

Redis의 사용 용도를 파악 후 Persistence 설정이 필요 없는 경우(ex. Session 저장소) 해당 설정을 off 하는것이 좋습니다.

[설정 off 방법]

  • redis.conf
appendonly no    <- AOF off
save “”          <- RDB off

Max Clients

Redis 서버에 연결할 수 있는 최대 Client 개수를 설정 할 수 있습니다. default 10000입니다. Redis가 내부적으로 32개를 사용하므로 이를 고려해서 설정하면 됩니다. 최대치에 도달하면 새로 접속하는 client는 “max number of clients reached” 에러 메시지를 받고 접속 할 수 있습니다. Client 동시 접속이 많은 경우 이 설정값을 높게 설정 해야 합니다.

[설정 방법]

  • redis.conf
maxclients 3000    

TCP Backlog

초당 요청이 많은 환경에서는 느린 client 연결 문제를 피하기 위해 높은 백로그가 필요합니다. default 설정은 511 인데, 더 많은 요청을 동시에 받기 위해서는 더 높게 설정할 필요가 있습니다. 이때 리눅스 커널 파라미터인 /proc/sys/net/core/somaxconn과 tcp_max_syn_backlog 값도 같이 설정이 필요합니다.

[설정 방법]

  • redis.conf
tcp-backlog 2048    
  • /etc/sysctl.conf
net.core.somaxconn = 4096
net.ipv4.tcp_max_syn_backlog = 4096

정리

성능 튜닝 파라미터를 적용 후 모니터링(slow log, latency, client list)을 통해 불필요한 Long Command를 제거 해야합니다. 이후에도 요구하는 Throughput, 응답시간이 안나오는 경우는 Redis를 업무 별로 분리해서 각각 구성하거나, Scale Out 할 수 있는 Redis Cluster 제품을 검토하시기 바랍니다.