Foundry
캐시/Redis
중급
핵심

분산 캐시와 Redis 자료구조 선택

캐시를 문자열로만 쓰지 않는다. 타입이 성능을 바꾼다

분산 캐시와 Redis 자료구조 선택

타입 선택

타입캐시 용도대표 명령
String직렬화한 객체, 카운터GET / SETEX / INCR
Hash객체의 일부 필드만 갱신HGET / HSET
List최근 N건 목록LPUSH / LRANGE / LTRIM
Set중복 없는 집합, 존재 검사SADD / SISMEMBER
Sorted Set점수 기반 랭킹, 시간순 정렬ZADD / ZRANGE

실무 포인트

  • 객체 전체를 String으로 넣으면 필드 하나 갱신에도 전체 재직렬화가 필요하다. 부분 갱신이 잦으면 Hash
  • 운영에서 KEYS는 금지. 전체 키를 훑어 서버를 멈춘다. SCAN으로 커서 순회한다
  • 왕복이 많으면 파이프라인이나 MGET으로 묶는다. 네트워크 RTT가 병목인 경우가 흔하다
  • 큰 값이나 원소가 수십만 개인 컬렉션은 단일 명령이 오래 걸린다. 키를 쪼갠다
  • Redis는 명령을 사실상 단일 스레드로 처리한다. 무거운 명령 하나가 전체 지연을 만든다
면접에서 이렇게 나옵니다

Q.랭킹 기능을 Redis로 구현한다면 어떤 자료구조를 쓰나요?

정렬된 집합(Sorted Set)을 씁니다. 점수로 정렬된 상태를 유지하면서 순위 조회가 로그 시간입니다.

연산명령복잡도
점수 갱신ZADDO(log n)
상위 N명ZREVRANGEO(log n + N)
특정 사용자 순위ZREVRANKO(log n)
점수 구간 조회ZRANGEBYSCOREO(log n + N)

다른 자료구조로는 이 조합이 안 됩니다. 리스트는 정렬을 유지하지 못하고, 해시는 순위를 모릅니다. DB 로 하면 매번 정렬이나 인덱스 스캔이 필요합니다.

주의할 점입니다.

항목내용
동점 처리점수가 같으면 사전순이라, 먼저 달성한 사람을 앞에 두려면 점수에 시간을 섞는다
기간별 랭킹일간과 주간을 각각 다른 키로 두고 만료를 건다
규모수천만 명이면 메모리를 계산해 보고 샤딩을 검토한다

흔한 실수: 랭킹 전체를 매번 가져오는 것. 상위 100명만 필요하면 그만큼만 요청해야 합니다.

Q.객체 캐싱에 String과 Hash 중 무엇을 선택하나요?

전체를 한 번에 읽고 쓰면 String, 필드별로 접근하면 Hash 입니다.

항목String (직렬화)Hash
부분 조회안 된다. 전체를 읽는다필드만 읽는다
부분 갱신전체를 다시 쓴다필드만 쓴다
만료키 단위키 단위. 필드별로는 불가
메모리작은 객체는 Hash 가 더 효율적작은 해시는 압축 저장된다
직렬화 비용매번 전체 직렬화필드 단위라 적다

기준은 접근 패턴입니다. 프로필 전체를 화면에 뿌린다면 String 이 단순하고, 조회수만 자주 올린다면 Hash 로 그 필드만 증가시키는 것이 훨씬 싸습니다.

흔한 실수: 필드별 만료가 필요한데 Hash 를 고르는 것. Hash 는 필드 단위 만료가 없어서, 필요하면 필드를 별도 키로 나눠야 합니다.

Q.운영 중 KEYS 명령을 쓰면 안 되는 이유는?

Redis 는 단일 스레드로 명령을 처리하는데, KEYS 는 전체 키를 훑는 O(n) 명령이라 그 시간 동안 다른 요청이 전부 멈춥니다.

키가 100만 개면 수백 밀리초에서 수 초
그 사이 모든 클라이언트가 대기한다

대안입니다.

목적대안
패턴으로 키 찾기SCAN. 커서로 조금씩 나눠 훑는다
특정 묶음 관리별도 집합에 키 목록을 관리한다
통계INFO 나 DBSIZE 로 개수만 본다

같은 이유로 위험한 명령이 더 있습니다. FLUSHALL, 큰 컬렉션에 대한 SMEMBERS 나 LRANGE 전체 조회, 큰 키의 DEL 도 오래 걸립니다.

흔한 실수: 개발 환경에서 문제없어 운영에서도 쓰는 것. 키가 적으면 빠르므로 규모가 커진 뒤에야 드러납니다. 운영에서는 위험 명령을 아예 비활성화하는 설정을 걸어두는 편이 안전합니다.

Q.Redis가 갑자기 전체적으로 느려졌다면 무엇을 확인하나요?

단일 스레드라 한 요청이 오래 걸리면 전부 밀립니다. 그 원인부터 찾습니다.

확인방법
느린 명령SLOWLOG 로 오래 걸린 명령을 본다
O(n) 명령KEYS, 큰 컬렉션 전체 조회, 큰 키 삭제
메모리 상태상한 도달, 축출 급증, 단편화
스냅샷 저장저장 중 fork 와 쓰기 시 복사로 지연이 생긴다
네트워크대역폭 포화, 큰 값 전송
만료 폭주대량 키가 동시에 만료되며 정리 부하가 든다

스냅샷이 자주 간과됩니다. 저장 시점에 프로세스를 복제하는데, 그 뒤 쓰기가 많으면 복사가 대량으로 일어나 메모리와 지연이 함께 나빠집니다.

흔한 실수: 서버 CPU 사용률만 보는 것. 단일 스레드라 코어 하나가 100%면 그것이 상한입니다. 전체 CPU 가 12%로 보여도 이미 포화일 수 있습니다.

먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.

더 깊이 공부하기

읽었으면 문제로 확인해보세요

캐시/Redis 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.