콘텐츠로 이동

Redis 관측 가능성 모범 사례


Redis란?

Redis는 널리 사용되는 인메모리 키/값 데이터 스토어입니다. Redis는 뛰어난 성능과 간편한 시작으로 유명하며, 다음과 같은 다양한 산업 분야에서 활용되고 있습니다:

  • 데이터베이스: 비동기 디스크 영속성을 사용할 수 있지만, Redis는 기존의 디스크 기반 데이터베이스와 달리 영속성을 희생하여 속도를 높입니다. Redis는 풍부한 데이터 기본 자료형과 매우 다양한 명령어 목록을 제공합니다.

  • 메시지 큐: Redis의 블로킹 리스트 명령어와 낮은 지연 시간은 메시지 브로커 서비스의 훌륭한 백엔드가 됩니다.

  • 인메모리 캐시: 널리 사용되는 '최근 최소 사용(LRU)' 전략과 Redis 4.0부터 도입된 '최소 빈도 사용(LFU)' 전략 등 구성 가능한 키 제거 정책을 통해 Redis는 캐시 서버로서 탁월한 선택이 됩니다. 기존 캐시와 달리 Redis는 안정성 향상을 위해 디스크 영속성도 지원합니다.

Redis는 무료 오픈소스 제품입니다. 상용 지원과 완전 관리형 Redis 서비스도 제공됩니다.

Redis는 Twitter, GitHub, Docker, Pinterest, Datadog, Stack Overflow 등 많은 트래픽이 높은 웹사이트와 애플리케이션에서 채택하고 있습니다.

주요 Redis 메트릭

Redis를 모니터링하면 두 가지 측면에서 문제를 발견할 수 있습니다. Redis 자체의 리소스 문제와 지원 인프라의 다른 곳에서 발생하는 문제입니다.

이 문서에서는 다음 각 범주에서 가장 중요한 Redis 메트릭을 자세히 설명합니다:

  • 성능 메트릭

  • 메모리 메트릭

  • 기본 활동 메트릭
  • 영속성 메트릭
  • 오류 메트릭

성능 메트릭

낮은 오류율과 함께 좋은 성능은 시스템 상태를 나타내는 최상의 지표 중 하나입니다. 메모리 섹션에서 설명한 대로 성능 저하는 일반적으로 메모리 문제로 인해 발생합니다.

이름 설명 Metric Type
latency Redis 서버가 요청에 응답하는 평균 시간 Work: Performance
Instantaneous_ops_per_sec 초당 처리된 총 명령어 수 Work: Throughput
hit rate (계산된 값) keyspace_hits / (keyspace_hits + keyspace_misses) Work: Success

알림 메트릭: latency

지연 시간은 클라이언트 요청과 실제 서버 응답 사이의 시간을 측정한 것입니다. 지연 시간을 추적하는 것은 Redis 성능 변화를 감지하는 가장 직접적인 방법입니다. Redis는 단일 스레드 특성을 가지므로 지연 시간 분포의 이상값은 심각한 병목 현상을 초래할 수 있습니다. 하나의 요청 응답 시간이 길어지면 모든 후속 요청의 대기 시간이 증가합니다. 지연 시간이 문제로 확인되면 성능 문제를 진단하고 해결하기 위해 여러 조치를 취할 수 있습니다.

image.png

관찰 메트릭: Instantaneous_ops_per_sec

처리된 명령어의 처리량을 추적하는 것은 Redis 인스턴스의 높은 지연 시간 원인을 진단하는 데 필수적입니다. 높은 지연 시간은 명령어 큐의 백로그부터 느린 명령어, 네트워크 링크 과도 사용까지 다양한 문제로 인해 발생할 수 있습니다. 초당 처리된 명령어 수를 측정하여 조사할 수 있습니다. 명령어 수가 거의 변하지 않는다면 원인은 계산 집약적인 명령어가 아닙니다. 하나 이상의 느린 명령어가 지연 시간 문제를 일으키는 경우 초당 명령어 수가 감소하거나 완전히 중단되는 것을 볼 수 있습니다. 과거 기준과 비교하여 초당 처리된 명령어 수가 감소하는 것은 명령어 볼륨이 낮거나 시스템을 차단하는 느린 명령어의 징후일 수 있습니다. 명령어 볼륨이 낮은 것은 정상일 수도 있고, 상위 시스템에 문제가 있음을 나타낼 수도 있습니다.

메트릭: hit rate

Redis를 캐시로 사용할 때 캐시 적중률을 모니터링하면 캐시가 효과적으로 사용되고 있는지 알 수 있습니다. 적중률이 낮다는 것은 클라이언트가 더 이상 존재하지 않는 키를 찾고 있다는 의미입니다. Redis는 적중률 메트릭을 직접 제공하지 않습니다. 그러나 다음과 같이 계산할 수 있습니다:

hit rate = keyspace_hits / (keyspace_hits + keyspace_misses)

캐시 적중률이 낮은 것은 데이터 만료, Redis에 할당된 메모리 부족(키 제거로 이어질 수 있음) 등 여러 요인으로 인해 발생할 수 있습니다. 적중률이 낮으면 애플리케이션이 더 느린 대체 리소스에서 데이터를 가져와야 하므로 애플리케이션 지연 시간이 증가할 수 있습니다.

메모리 메트릭

이름 설명 Metric Type
used_memory Redis가 사용하는 메모리 양(바이트 단위) Resource: Utilization
mem_fragmentation_ratio 운영 체제가 할당한 메모리와 Redis가 요청한 메모리의 비율 Resource: Saturation
evicted_keys 최대 메모리 제한에 도달하여 삭제된 키 수 Resource: Saturation
blocked_clients BLPOP, BRPOP 또는 BRPOPLPUSH를 기다리며 차단된 클라이언트 Other

관찰 메트릭: used_memory

메모리 사용량은 Redis 성능의 핵심 요소입니다. used_memory가 사용 가능한 총 시스템 메모리를 초과하면 운영 체제는 오래되었거나 사용되지 않는 메모리 부분을 스왑하기 시작합니다. 스왑된 각 부분은 디스크에 기록되어 성능에 심각한 영향을 미칩니다. 디스크에서 쓰거나 읽는 것은 메모리에서 쓰거나 읽는 것보다 5자릿수(100,000배!) 더 느립니다(메모리 0.1µs, 디스크 10ms).

Redis를 특정 메모리 양으로 제한하도록 구성할 수 있습니다. redis.conf 파일에서 maxmemory 지시문을 설정하면 Redis의 메모리 사용량을 직접 제어할 수 있습니다. maxmemory를 활성화하면 Redis에 메모리를 해제하는 방법을 결정하는 제거 정책을 구성해야 합니다. evicted_keys 섹션에서 maxmemory-policy 지시문 구성에 대해 자세히 알아보세요.

image.png

알림 메트릭: mem_fragmentation_ratio

mem_fragmentation_ratio 메트릭은 운영 체제가 사용하는 메모리(used_memory_rss)와 Redis가 할당한 메모리(used_memory)의 비율을 제공합니다.

mem_fragmentation_ratio = used_memory_rss / used_memory
운영 체제는 각 프로세스에 물리적 메모리를 할당합니다. 운영 체제의 가상 메모리 관리자는 메모리 할당자가 중재하는 실제 매핑을 처리합니다.

이것이 의미하는 바는 무엇일까요? Redis 인스턴스의 메모리 사용량이 1GB인 경우 메모리 할당자는 먼저 데이터를 저장할 연속적인 메모리 세그먼트를 찾으려고 시도합니다. 연속적인 세그먼트를 찾을 수 없으면 할당자는 프로세스 데이터를 여러 세그먼트로 나누어야 하므로 메모리 오버헤드가 증가합니다.

조각화 비율을 추적하는 것은 Redis 인스턴스의 성능을 이해하는 데 매우 중요합니다. 조각화 비율이 1보다 크면 조각화가 발생하고 있음을 의미합니다. 비율이 1.5를 초과하면 과도한 조각화로 Redis 인스턴스가 요청한 물리적 메모리의 150%를 소비하고 있음을 나타냅니다. 1보다 작은 조각화 비율은 Redis가 시스템에서 사용 가능한 메모리보다 더 많은 메모리를 필요로 하여 스와핑이 발생하고 있음을 의미합니다. 디스크로의 스와핑은 지연 시간을 크게 증가시킵니다(used_memory 참조). 이상적으로 운영 체제는 물리적 메모리에 연속적인 세그먼트를 할당하며 조각화 비율은 1 이상입니다.

서버의 조각화 비율이 1.5를 초과하는 경우 Redis 인스턴스를 다시 시작하면 운영 체제가 이전에 조각화로 인해 사용할 수 없었던 메모리를 복구할 수 있습니다. 이 경우 알림으로 경고를 보내는 것으로 충분할 수 있습니다.

그러나 Redis 서버의 조각화 비율이 1 미만인 경우 페이지로 경고를 발행하여 사용 가능한 메모리를 빠르게 늘리거나 메모리 사용량을 줄일 수 있도록 해야 할 수 있습니다.

Redis 4부터는 포함된 jemalloc 복사본을 사용하도록 Redis를 구성할 때 새로운 능동적 조각 모음 기능을 사용할 수 있습니다. 이 도구는 조각화가 특정 수준에 도달하면 시작되고 값을 연속적인 메모리 영역에 복사하고 이전 복사본을 해제하여 서버 실행 중 조각화를 줄이도록 구성할 수 있습니다.

알림 메트릭: evicted_keys(캐시 전용)

Redis를 캐시로 사용하는 경우 최대 메모리 제한에 도달하면 자동으로 키를 제거하도록 구성해야 할 수 있습니다. Redis를 데이터베이스나 큐로 사용하는 경우 제거 대신 다른 방식을 사용하는 것이 좋습니다. 이 경우 이 메트릭은 건너뛸 수 있습니다.

키 제거를 추적하는 것은 중요합니다. Redis는 각 작업을 순차적으로 처리하므로 많은 키를 제거하면 적중률이 낮아져 지연 시간이 길어질 수 있습니다. TTL을 사용하는 경우 키가 제거되는 것을 원하지 않을 수 있습니다. 이 경우 이 메트릭이 지속적으로 0보다 크면 인스턴스의 지연 시간이 증가할 수 있습니다. TTL을 사용하지 않는 대부분의 다른 구성은 결국 메모리가 부족해져 키 제거를 시작합니다. 응답 시간이 허용 가능한 범위 내에 있다면 안정적인 제거율은 수용 가능합니다.

다음 명령어를 사용하여 키 만료 정책을 구성할 수 있습니다:

redis-cli CONFIG SET maxmemory-policy <policy>

여기서 policy는 다음 중 하나입니다:

  • noeviction: 메모리 제한에 도달하고 사용자가 새 키를 추가하려고 하면 오류 반환

  • volatile-lru: 만료 세트가 있는 키 중에서 가장 최근에 사용되지 않은 키 삭제

  • volatile-ttl: 만료 세트가 있는 키 중에서 남은 TTL이 가장 짧은 키 삭제
  • volatile-random: 만료 세트가 있는 키 중에서 임의의 키 삭제
  • allkeys-lru: 모든 키 세트에서 가장 최근에 사용되지 않은 키 삭제
  • allkeys-random: 모든 키 세트에서 임의의 키 삭제
  • volatile-lfu: Redis 4에서 추가됨, 만료 세트가 있는 키 중에서 가장 자주 사용되지 않은 키 삭제
  • allkeys-lfu: Redis 4에서 추가됨, 모든 키 세트에서 가장 자주 사용되지 않은 키 삭제

참고: 성능상의 이유로 LRU, TTL 또는 Redis 4(LFU 이후) 정책을 사용할 때 Redis는 실제로 전체 키 공간을 샘플링하지 않습니다. Redis는 먼저 키 공간의 무작위 하위 집합을 샘플링한 다음 해당 샘플에 제거 정책을 적용합니다. 일반적으로 최신(>= 3) 버전의 Redis는 실제 LRU에 더 가까운 LRU 샘플링 전략을 사용합니다. LFU 정책은 예를 들어 항목이 액세스 수준을 낮추기 위해 경과해야 하는 시간을 설정하여 조정할 수 있습니다. 자세한 내용은 Redis 문서를 참조하세요.

관찰 메트릭: blocked_clients

Redis는 리스트에서 작동하는 여러 블로킹 명령어를 제공합니다. BLPOP, BRPOP, BRPOPLPUSH는 각각 LPOP, RPOP, RPOPLPUSH 명령어의 블로킹 변형입니다. 소스 리스트가 비어 있지 않으면 명령어는 예상대로 실행됩니다. 그러나 소스 리스트가 비어 있으면 블로킹 명령어는 소스가 채워지거나 타임아웃에 도달할 때까지 대기합니다.

데이터를 기다리는 차단된 클라이언트 수의 증가는 문제의 징후일 수 있습니다. 지연 시간이나 다른 문제로 인해 소스 리스트가 채워지지 않을 수 있습니다. 차단된 클라이언트 자체가 경고를 유발하지는 않지만, 이 메트릭이 지속적으로 0이 아닌 값을 보이면 조사해야 합니다.

기본 활동 메트릭

참고: 이 섹션에는 'primary'와 'replica'라는 용어를 사용하는 메트릭이 포함됩니다. 특정 메트릭 이름을 인용하는 경우를 제외하고, 이 문서에서는 'primary'와 'replica'로 대체합니다.

이름 설명 Metric Type
connected_clients Redis에 연결된 클라이언트 수 Resource: Utilization
connected_slaves 현재 프라이머리 인스턴스에 연결된 레플리카 수 Other
master_last_io_seconds_ago 레플리카와 프라이머리 인스턴스 간의 마지막 상호 작용 이후 경과 시간(초) Other
keyspace 데이터베이스의 총 키 수 Resource: Utilization

알림 메트릭: connected_clients

Redis에 대한 액세스는 일반적으로 애플리케이션을 통해 중개되므로(사용자가 일반적으로 데이터베이스에 직접 액세스하지 않음), 대부분의 경우 연결된 클라이언트 수에는 합리적인 상한 및 하한이 있습니다. 숫자가 정상 범위를 벗어나면 문제가 있을 수 있습니다. 너무 낮으면 업스트림 연결이 끊어졌을 수 있고, 너무 높으면 과도한 동시 클라이언트 연결로 인해 서버의 요청 처리 능력이 과부하될 수 있습니다.

어쨌든 클라이언트 연결의 최대 개수는 항상 제한된 리소스입니다. 운영 체제, Redis 구성 또는 네트워크 제한에 의해 제한됩니다. 클라이언트 연결을 모니터링하면 새 클라이언트 또는 관리 세션에 사용할 수 있는 충분한 리소스가 있는지 확인하는 데 도움이 됩니다.

알림 메트릭: connected_slaves

데이터베이스가 읽기 중심이라면 Redis에서 사용 가능한 프라이머리-레플리카 데이터베이스 복제 기능을 사용하고 있을 수 있습니다. 이 경우 연결된 레플리카 수를 모니터링하는 것이 중요합니다. 연결된 레플리카 수가 예기치 않게 변경되면 프라이머리가 다운되었거나 레플리카 인스턴스에 문제가 있음을 나타낼 수 있습니다.

image.png

참고: 위 다이어그램에서 Redis 프라이머리 데이터베이스는 두 개의 연결된 레플리카가 있음을 표시하고, 첫 번째 하위 레플리카는 각각 두 개의 연결된 레플리카가 있다고 보고합니다. 보조 레플리카는 Redis 프라이머리 레플리카에 직접 연결되어 있지 않으므로 프라이머리에 연결된 레플리카 수에 포함되지 않습니다.

알림 메트릭: master_last_io_seconds_ago

Redis의 복제 기능을 사용할 때 레플리카 인스턴스는 주기적으로 프라이머리 인스턴스에 체크인합니다. 오랫동안 통신이 없으면 프라이머리 Redis 서버, 레플리카 서버 또는 둘 다에 문제가 있음을 나타낼 수 있습니다. 또한 레플리카가 마지막 동기화 이후 변경되었을 수 있는 오래된 데이터를 제공할 위험이 있습니다. Redis가 동기화를 수행하는 방식 때문에 프라이머리-레플리카 통신 중단을 최소화하는 것이 중요합니다. 중단 후 레플리카가 프라이머리 데이터베이스에 다시 연결되면 SYNC 명령을 보내 중단 동안 손실된 명령어만 부분 동기화하려고 시도합니다. 이것이 불가능하면 레플리카는 전체 SYNC를 요청하여 프라이머리가 데이터베이스를 디스크에 백그라운드 저장하고 동시에 수신된 모든 새 데이터 집합 수정 명령어를 버퍼링하도록 합니다. 백그라운드 저장이 완료되면 데이터는 버퍼링된 명령어와 함께 클라이언트로 전송됩니다. 레플리카가 SYNC를 수행할 때마다 프라이머리 인스턴스의 지연 시간이 크게 증가합니다.

주목할 만한 메트릭: keyspace

데이터베이스의 키 수를 추적하는 것은 일반적으로 좋은 생각입니다. 인메모리 데이터 스토어로서 키 공간이 클수록 Redis는 최적의 성능을 위해 더 많은 물리적 메모리가 필요합니다. Redis는 최대 메모리 제한에 도달할 때까지 계속 키를 추가하며, 이 시점에서 Redis는 새 키가 추가되는 속도와 동일한 속도로 키를 제거하기 시작합니다.

Redis를 캐시로 사용하고 키 공간이 포화 상태(위 그림 참조)이고 적중률이 낮은 경우 클라이언트가 오래된 데이터나 제거된 데이터를 요청하고 있을 수 있습니다. 시간 경과에 따른 keyspace_misses 수를 추적하면 원인을 파악하는 데 도움이 됩니다.

또한 Redis를 데이터베이스나 큐로 사용하는 경우 휘발성 키를 사용하지 않는 것이 좋을 수 있습니다. 키 공간이 증가함에 따라 가능하다면 박스에 메모리를 추가하거나 호스트 간에 데이터 세트를 분할하는 것을 고려해야 할 수 있습니다. 더 많은 메모리를 추가하는 것은 간단하고 효과적인 솔루션입니다. 하나의 박스가 제공할 수 있는 것보다 더 많은 리소스가 필요할 때는 데이터를 파티셔닝하거나 샤딩하여 여러 컴퓨터의 리소스를 결합할 수 있습니다. 파티셔닝 계획을 통해 Redis는 제거나 스와핑 없이 더 많은 키를 저장할 수 있습니다. 그러나 파티셔닝 계획을 적용하는 것은 몇 개의 메모리 스틱을 교체하는 것보다 더 까다롭습니다.

영속성 메트릭

이름 설명 Metric Type
rdb_last_save_time 마지막 디스크 저장의 Unix 타임스탬프 Other
rdb_changes_since_last_save 마지막 덤프 이후 데이터베이스에 대한 변경 사항 수 Other

영속성 활성화는 특히 Redis의 복제 기능을 사용하는 경우 필요할 수 있습니다. 레플리카는 프라이머리 인스턴스에 대한 모든 변경 사항을 맹목적으로 복제하므로, 프라이머리 인스턴스(영속성 없음)를 다시 시작하면 연결된 모든 레플리카가 현재 비어 있는 데이터 세트를 복제합니다.
Redis를 캐시로 사용하거나 사용 사례에서 데이터 손실이 덜 중요한 경우 영속성이 필요하지 않을 수 있습니다.

중요 모니터링 메트릭: rdb_last_save_time 및 rdb_changes_since_last_save

일반적으로 데이터 세트의 변동성을 주시하는 것이 좋습니다. 서버 장애가 발생할 경우 디스크에 두 번 쓰는 사이의 간격이 너무 길면 데이터 손실이 발생할 수 있습니다. 마지막 저장 시간과 장애 시간 사이에 데이터 세트에 대한 모든 변경 사항은 손실됩니다.
rdb_changes_since_last_save를 모니터링하면 데이터의 변동성에 대한 더 깊은 통찰력을 얻을 수 있습니다. 해당 간격 동안 데이터 세트가 크게 변하지 않은 경우 두 번 쓰기 사이의 긴 간격은 문제가 되지 않습니다. 두 메트릭을 모두 추적하면 주어진 시점에 장애가 발생할 경우 얼마나 많은 데이터가 손실될지 잘 파악할 수 있습니다.

오류 메트릭

참고: 이 섹션에는 'primary'와 'replica'라는 용어를 사용하는 메트릭이 포함됩니다. 특정 메트릭 이름을 인용하는 경우를 제외하고, 이 문서에서는 'primary'와 'replica'로 대체합니다.
Redis 오류 메트릭은 비정상적인 상황을 알려줄 수 있습니다. 다음 메트릭은 일반적인 오류를 추적합니다:

이름 설명 Metric Type
rejected_connections maxclient 제한에 도달하여 거부된 연결 수 Resource: Saturation
keyspace_misses 실패한 키 조회 횟수 Resource: Errors / Other
master_link_down_since_seconds 프라이머리 서버와 레플리카 서버 간의 링크가 끊어진 시간(초) Resource: Errors

알림 메트릭: rejected_connections

Redis는 많은 활성 연결을 처리할 수 있으며, 기본적으로 10,000개의 클라이언트 연결을 사용할 수 있습니다. redis.conf의 maxclient 지시문을 변경하여 최대 연결 수를 다른 값으로 설정할 수 있습니다. Redis 인스턴스가 현재 최대 연결 수에 도달하면 새로운 연결 시도는 모두 끊어집니다.

image.png

시스템이 maxclient 지시문으로 요청한 연결 수를 지원하지 않을 수 있습니다. Redis는 커널과 확인하여 사용 가능한 파일 디스크립터 수를 결정합니다. 사용 가능한 파일 디스크립터 수가 maxclient + 32(Redis는 자체 사용을 위해 32개의 파일 디스크립터를 예약함)보다 작으면 maxclient 지시문이 무시되고 사용 가능한 파일 디스크립터 수가 사용됩니다.

알림 메트릭: keyspace_misses

Redis가 키를 조회할 때마다 두 가지 결과만 가능합니다: 키가 존재하거나 존재하지 않습니다. 존재하지 않는 키를 조회하면 keyspace_misses 카운터가 증가합니다. 이 메트릭이 지속적으로 0이 아닌 값을 보이면 클라이언트가 데이터베이스에서 존재하지 않는 키를 찾으려고 시도하고 있음을 의미합니다. Redis를 캐시로 사용하지 않는 경우 keyspace_misses는 0이거나 0에 가까워야 합니다. 빈 키에 대해 호출된 모든 블로킹 작업(BLPOP, BRPOP, BRPOPLPUSH)은 keyspace_misses를 증가시킵니다.

이 메트릭은 프라이머리 노드와 레플리카 간의 연결이 끊어진 경우에만 사용할 수 있습니다. 이상적으로 이 값은 절대 0보다 커서는 안 됩니다. 프라이머리 데이터베이스와 레플리카 데이터베이스는 레플리카가 오래된 데이터를 제공하지 않도록 지속적인 통신을 유지해야 합니다. 연결 간의 큰 시간 간격이 발생하면 해결해야 합니다. 다시 연결되면 프라이머리 Redis 인스턴스는 레플리카의 데이터를 업데이트하는 데 리소스를 투입해야 하므로 지연 시간이 증가할 수 있습니다.

결론

이 문서에서는 Redis 서버를 모니터링하는 데 가장 유용한 몇 가지 메트릭을 소개했습니다. Redis를 처음 시작하는 경우 아래 목록의 메트릭을 모니터링하면 데이터베이스 인프라의 상태와 성능을 잘 파악할 수 있습니다:

  • 초당 처리된 명령어 수

  • 지연 시간

  • 메모리 조각화 비율
  • 제거된 키
  • 거부된 클라이언트

궁극적으로는 자신의 인프라와 사용 사례에 특히 관련된 추가 메트릭을 인식하게 될 것입니다. 물론 모니터링할 내용은 보유한 도구와 사용 가능한 메트릭에 따라 달라집니다.

문서 평가

이 페이지가 도움이 되었나요?