Redis — 하나의 특성에서 파생되는 모든 활용

Redis를 공부하면 자료구조, 캐싱 전략, pub/sub, 분산락, 클러스터가 따로따로 쏟아진다. 외울 게 많아 보인다. 그런데 이 모든 활용은 사실 Redis의 단 하나의 특성에서 파생된다.

Redis는 단일 스레드로 동작하는 인메모리 저장소다. 메모리에 있으니 빠르고, 단일 스레드니까 모든 명령이 순차적으로 — 즉 원자적으로 — 실행된다. 이 두 가지가 Redis로 할 수 있는 모든 것의 출발점이다.


단일 스레드 인메모리가 왜 출발점인가

  • 인메모리라서 빠르다 → 캐시, 세션, 실시간 순위 같은 저지연 용도.
  • 단일 스레드라서 원자적이다 → 락, 카운터, 큐 같은 동시성 조율 도구.
  • 메모리는 휘발성이고 유한하다 → 영속성(AOF/RDB), eviction, 메모리 튜닝, HA가 필요해진다.

아래 다섯 갈래는 전부 이 특성의 결과다.

① 자료구조 — 모든 활용의 기반

String만 있는 게 아니다. Hash, List, Set, Sorted Set, Stream이 각자 다른 내부 구조(listpack/hashtable, quicklist, skiplist)로 최적화돼 있다. 어떤 자료구조를 고르냐가 키 개수, 메모리, 원자적 연산 가능 여부를 결정한다. 나머지 활용은 전부 이 자료구조 위에 선다.

Redis 자료구조 심화

② 캐싱 — 가장 흔한 용도

인메모리의 속도를 가장 직접적으로 쓰는 게 캐시다. Cache-Aside, Write-Through, Write-Behind의 선택, TTL 설계, Cache Stampede 방어, @Cacheable과 트랜잭션의 충돌까지 — 캐시는 “빠르다”의 대가로 “정합성”이라는 숙제를 가져온다.

Redis 캐싱 전략

③ 메시징 — pub/sub vs Stream

Redis로 메시지도 보낸다. 휘발성이고 못 받으면 끝인 pub/sub과, append-only log로 저장·재처리·consumer group을 지원하는 Stream. 이 선택은 “메시지를 잃어도 되나”라는 질문 하나로 갈린다.

Redis pub/sub vs Stream

④ 분산 조율 — 분산락

단일 스레드의 원자성을 분산 환경의 동시성 제어에 쓰는 게 분산락이다. SET NX PX, UUID 토큰, Lua 원자적 해제, 그리고 단일 노드의 한계에서 나온 Redlock과 그 논쟁(GC pause), Redisson Watchdog까지. 인메모리 속도 + 원자성이 만나는 지점.

분산락 — Redis로 구현하고 Redlock까지

⑤ HA와 운영 — 메모리의 한계를 다루기

메모리는 유한하고 서버는 죽는다. 그래서 Master-Replica 복제, Sentinel 자동 failover, Cluster의 16384 슬롯 분산, eviction policy와 maxmemory 튜닝, 원자적 연산을 위한 Lua가 필요하다. “빠르다”를 프로덕션에서 유지하기 위한 장치들.

Redis 클러스터·메모리·Lua

그래서 언제 Redis인가 — 대안과 비교

빠르고 다재다능하다고 아무 데나 쓰는 게 아니다. “왜 다른 것 대신 Redis인가”를 답할 수 있어야 한다.

  • vs 로컬(인프로세스) 캐시 — Caffeine/Guava: 로컬 캐시는 네트워크 홉이 없어 가장 빠르고 단순하다. 하지만 인스턴스마다 따로라 서버가 여러 대면 캐시가 제각각이고 무효화가 안 맞는다. 읽기 전용 참조 데이터나 단일 인스턴스면 로컬이 낫고, 여러 서버가 같은 상태를 공유해야 하면 Redis다. (L1=로컬, L2=Redis로 겹쳐 쓰기도 한다.)
  • vs Memcached: 둘 다 인메모리 캐시지만, Memcached는 멀티스레드라 단순 key-value 처리량·메모리 효율이 좋다. Redis는 자료구조(Sorted Set·Stream 등)·영속성·복제/클러스터·Pub/Sub·Lua 원자성을 준다. 순수 단순 캐시만이면 Memcached도 충분하고, **캐시 이상(랭킹·락·큐·세션)**을 하면 Redis다.
  • vs 메시지 브로커 — Kafka: Redis Streams/pub-sub은 가볍지만 Kafka 급의 영속·재처리·파티션 확장성은 아니다. 가벼운 실시간 팬아웃이면 Redis, 대규모 영속 로그·파이프라인이면 Kafka.

안 맞는 경우: 메모리보다 큰 데이터셋의 1차 저장소, 복잡한 쿼리·조인, 강한 내구성·트랜잭션이 필요한 원본 데이터 → RDB/전용 DB가 맞다. Redis는 ‘빠른 보조 계층’이지 원본 저장소가 아니다.

면접에서 이 그림이 유용한 이유

“Redis를 어디에 써봤나”를 받으면 다섯 갈래를 특성에서 풀어 답할 수 있다. “인메모리라 캐시·세션, 단일 스레드 원자성이라 분산락·카운터, 휘발성이라 영속성과 HA를 신경 써야 한다”는 식으로. 그 위에 본인이 겪은 이슈(캐시 stampede, 락 만료 타이밍, failover 중 쓰기 실패, 메모리 eviction으로 키 증발)를 붙이면 깊이가 드러난다. 개별 기능을 외운 사람과 특성에서 도출하는 사람의 차이다.