Redis Big Keys: `--bigkeys`와 `--memkeys`를 같이 봐야 하는 이유
Dev
마지막 업데이트

Redis Big Keys: `--bigkeys`와 `--memkeys`를 같이 봐야 하는 이유


Redis big key 문제는 메모리 그래프 하나로만 보이면 자꾸 헷갈립니다. 실제 운영에서는 element 수가 너무 많은 key, 메모리를 지나치게 많이 쓰는 key, 그리고 그 둘이 겹치는 key가 서로 다른 방식으로 사고를 만듭니다. 프로덕션에서 Redis slow log를 보다가 HGETALL이 200ms 넘게 걸리는 걸 발견한 적이 있는데, 해당 hash key의 field가 12만 개가 넘어 있었습니다. 메모리 자체는 크지 않았지만, 단일 command 실행 시간이 Redis 전체 응답을 잠그고 있었습니다. 그래서 “가장 큰 key를 지우자”보다 먼저 무엇이 truly expensive한지 나눠서 봐야 합니다.

짧게 말하면 --bigkeys는 cardinality와 구조 복잡도 쪽, --memkeysMEMORY USAGE는 실제 메모리 비용 쪽을 보여줍니다. 이 셋을 같이 봐야 data shape 문제를 제대로 설명할 수 있습니다.


이 글이 필요한 상황

아래 중 하나라면 이 글부터 보는 편이 좋습니다.

  • Redis memory usage가 계속 높아지는데 어떤 key가 문제인지 모른다
  • 특정 command만 느리고 persistence나 replication 비용도 같이 커진다
  • 몇 개 key가 유난히 비싸 보이는데 cardinality 문제인지 memory 문제인지 헷갈린다
  • cleanup은 해도 비슷한 운영 이슈가 반복된다

bigkeysmemkeys는 같은 말이 아닙니다

Redis CLI 문서 기준으로 redis-cli --bigkeys는 element 수가 많은 key를 찾는 쪽에 가깝고, redis-cli --memkeys는 메모리를 많이 쓰는 key를 찾는 쪽에 가깝습니다.

이 차이가 실전에서 꽤 중요합니다.

관찰 방식주로 알려주는 것놓치기 쉬운 것
--bigkeyskey의 길이, cardinality, 구조적 복잡도메모리 오버헤드가 큰 key
--memkeys실제 메모리 비용이 큰 keyelement 수는 많지 않아도 비싼 구조
MEMORY USAGE key특정 key의 실제 메모리 사용량전체 분포나 다른 key와 비교

즉 list, set, hash, zset이 원소 수 때문에 비싼 경우도 있고, cardinality는 적당해 보여도 실제 메모리 사용량이 큰 경우도 있습니다.

첫 10분 체크

초반에는 아래 네 줄이면 충분합니다.

redis-cli --bigkeys
redis-cli --memkeys
redis-cli --keystats
redis-cli MEMORY USAGE my:key SAMPLES 0

추가로 production 부하가 걱정되면 CLI 문서에 나온 것처럼 -i 0.1로 SCAN 사이에 잠깐 쉬게 할 수 있습니다.

redis-cli --bigkeys -i 0.1
redis-cli --memkeys -i 0.1

경험상 이 4줄을 한 번 돌리는 것만으로도 문제의 80%는 어느 방향인지 가닥이 잡힙니다. 이 단계에서 먼저 답해야 할 질문은 세 가지입니다.

  • cardinality가 지나치게 큰 key가 있는가
  • 실제 메모리 사용량이 비정상적으로 큰 key가 있는가
  • 문제 key가 특정 prefix나 feature에 몰려 있는가

왜 big key가 memory 문제로만 끝나지 않을까요

Redis latency 문서가 강조하듯, 느린 command 하나가 single-threaded Redis 전체를 잠깐 막을 수 있습니다. big key는 그 느린 command를 더 자주 만들 수 있습니다.

대표적인 영향은 아래와 같습니다.

  • 큰 collection을 건드리는 command가 오래 걸린다
  • replication과 persistence 비용이 커진다
  • eviction pressure가 더 거칠게 드러난다
  • hot key 하나가 전체 latency 체감을 왜곡한다

즉 big key는 저장 용량 문제이기도 하지만, 동시에 command shape 문제이기도 합니다.

이런 패턴이면 big key를 의심하세요

아래 조합이 자주 같이 보입니다.

  • HGETALL, LRANGE, SMEMBERS, ZRANGE 같은 넓은 조회가 느리다
  • SLOWLOG에 특정 key family를 건드리는 command가 반복된다
  • AOF rewrite나 RDB save 구간에 더 괴롭다
  • memory는 높고, 지워도 같은 key family가 다시 커진다

이 패턴이면 개별 incident보다 data shape가 반복적으로 문제를 만드는 쪽일 가능성이 큽니다.

MEMORY USAGE는 샘플링 옵션까지 같이 보세요

Redis 공식 문서 기준으로 MEMORY USAGE는 nested type에 대해 SAMPLES 옵션을 받을 수 있고, 기본 샘플 수는 5입니다. 더 정확하게 보고 싶다면 SAMPLES 0으로 전체를 기준 삼아 볼 수 있습니다.

redis-cli MEMORY USAGE cart:123 SAMPLES 0
redis-cli MEMORY USAGE timeline:user:42 SAMPLES 0

특히 “원소 수는 그리 많지 않아 보이는데 왜 이렇게 비싸지?” 같은 질문을 할 때 유용합니다.

흔한 잘못된 시작

아래 대응은 자주 보이지만 보통 첫 단계로는 비효율적입니다.

  • KEYS *로 전체를 뒤지는 것
  • --bigkeys만 보고 메모리 문제까지 다 설명됐다고 생각하는 것
  • 가장 큰 key를 바로 삭제하는 것
  • maxmemory만 늘리면 끝날 문제라고 보는 것

특히 KEYS는 Redis latency 문서에서도 production에서 흔한 latency 원인으로 경고하는 패턴이라 피하는 편이 낫습니다.

실전 점검 순서

1. --bigkeys--memkeys를 둘 다 돌립니다

cardinality와 메모리 비용을 분리해서 봐야 합니다.

2. --keystatsMEMORY USAGE로 실제 무게를 확인합니다

문제 key를 추측이 아니라 수치로 좁혀야 합니다.

3. 그 key를 건드리는 command family를 확인합니다

SLOWLOG나 app trace를 같이 보면 원인이 더 빨리 보입니다.

4. retention, sharding boundary, object shape를 다시 봅니다

진짜 해결은 cleanup보다 구조 변경인 경우가 많습니다.

5. persistence와 latency 부작용까지 다시 확인합니다

메모리 그래프만 좋아졌다고 사건이 끝난 것은 아닐 수 있습니다.

구조 변경이 필요한 대표 패턴

아래 중 하나면 redesign이 더 근본적인 경우가 많습니다.

  • 하나의 key가 tenant 전체 데이터를 다 들고 있다
  • time window가 너무 길어서 계속 누적된다
  • 한 번 조회할 때 매번 너무 많은 data를 만진다
  • Redis가 원래 갖고 있지 않아도 되는 materialized blob을 오래 들고 있다

이때 자주 쓰는 방향은 아래입니다.

  • tenant, 날짜, object boundary 기준으로 쪼개기
  • retention을 강하게 제한하기
  • summary와 raw data를 분리하기
  • Redis 대신 다른 저장소나 다른 캐시 shape를 쓰기

체크리스트

  • --bigkeys--memkeys 결과를 둘 다 봤다
  • MEMORY USAGE ... SAMPLES 0으로 실제 비용을 샘플링했다
  • 문제 key family를 건드리는 command 패턴을 알고 있다
  • retention이나 key boundary를 바꿀 수 있는지 검토했다
  • persistence와 latency까지 함께 다시 확인했다

FAQ

Q. big key는 메모리 문제만 일으키나요?

아니요. memory, latency, persistence, eviction behavior를 함께 흔드는 경우가 많습니다.

Q. 가장 빠른 첫 단계는 무엇인가요?

--bigkeys--memkeys를 같이 돌려서 cardinality 문제와 memory 문제를 분리해 보세요.

Q. 가장 큰 key를 그냥 지우면 되나요?

애플리케이션 영향과 재생성 경로를 이해한 경우에만 그렇습니다. 구조가 그대로면 다시 생깁니다.

Q. 언제 redesign이 불가피한가요?

같은 key family가 반복해서 memory와 latency incident를 만드는 패턴일 때입니다.

Sources:

먼저 읽어볼 가이드

검색 유입이 많은 핵심 글부터 이어서 보세요.

광고