카테고리
게시일
Jan 3, 2026

Redis는 In-Memory 및 비정형 DBMS이다.
- In-memory DB: 디스크가 아닌 메모리를 주 저장소로 사용해, 매우 낮은 지연시간으로 데이터를 읽고 쓰는 데이터베이스
- 비정형 DB: 스키마가 고정되지 않은 자유로운 형태의 데이터(문서, JSON, 로그 등)를 저장·조회하는 데이터베이스
- 원자적 연산 : 다른 DBMS와 마찬가지로 한 요청은 원자적 연산으로 끝나 데이터의 동시접근을 중재한다.
redis는 네트워크 공유 메모리에 더 가깝다
redis를 마치 다른 DBMS의 대용처럼 쓰려고 하면 사용하기 불편하다.
- DBMS에서 가장 중요한 것 중 하나는 데이터 영속성이다. 즉 시스템에 장애가 생겨 꺼지더라도 데이터가 손실되지 않고 유지된다. 디스크에 백업이 불가능한 것은 아니나, 한 트랜잭션마다 데이터 영속성을 보장해주지 않는다.
- redis는 in-memory이기 때문에 용량당 비용이 크다. 즉 대용량 빅데이터에는 사용이 어렵다.
이런 단점은 레디스의 데이터 영속성과 용량을 희생해서 매우 빠른 지연속도를 보장하려는 철학 때문이라고 볼 수 있다. 따라서 데이터 저장용으로 레디스를 사용하기보다는, 서버/프로세스간 공유되는 임시 메모리의 역할을 맡는다.
redis는 서로 다른 여러 프로세스 사이에 공유되는 메모리를 저장하고 제공할 때 사용된다.
State와 Stateless Application 개발
redis가 왜 그렇게 인기인지 알기 위해서는 Stateless라는 개념을 알아야 한다. State란, 클라이언트의 한 요청에 의존하는 메모리를 의미한다. 예를 들어 요청 id, 요청 질의, 중간에 처리한 임시작업물 등 클라이언트의 그 요청을 처리하는데 필요한 데이터들이 있다. 원래는 이걸 각 프로세스의 메모리공간에 할당했다. 이걸 Stateful Application이라고 한다.
Stateful Application은 프로세스가 사망했을 때 그 작업물을 전부 잃어버린다.
요청 id, 요청 질의, 중간에 처리한 임시작업물을 전부 날려버린다면, 클라이언트의 요청을 영영 잃어버리고 발 것이다.
그럼 이 잃어버린 작업물을 되살리려면 어떻게 하면 될까? 이 State들을 바깥으로 빼면 된다. 즉 외부에 공유되는 메모리를 저장한 서버를 두고, 각 프로세스는 state를 직접적으로 저장하지 않는다. 이것이 Stateless Application이다. 이 때 공유 메모리의 역할에 맞춤인 것이 일반 DBMS보다 훨씬 빠르게 동작하는 redis이다. 이렇게 구성하면 한 프로세스가 죽어도, 다른 프로세스가 기존 State를 받고 이어서 작업할 수 있다.
Stateless Application은 State를 외부 메모리에 둔 Application이다. 그 외부 메모리 역할에 적합한것이 빠른 redis이다.
Job Distribution(작업 분산)
redis가 인기있는 이유는 작업 분산에도 관련있다. 바로 공유되는 작업 대기큐를 만들어주기 때문이다.
작업분산은 Stateless와도 관련이 있지만, 두 개념이 엄밀히 말해 같은것은 아니다. 작업 분산에 stateless를 도입하면 훨씬 가용성에 도움을 줄 수 있지만, 굳이 기존 stateful 서비스를 stateless로 개발하지 않고도 redis 대기큐만 도입해도 쉽게 작업분산을 구현할 수 있다.
여기에 쿠버네티스까지 얹으면 더욱 가용성을 극대화할 수 있다.
로드밸런싱
예를 들어 동시에 수만명이 접속하는 티게팅 서비스를 만든다고 가정하자. Http 요청은 오버헤드가 굉장히 큰 작업이다. 따라서 HTTP 요청을 여러개의 웹서버에서 병렬로 처리하는 서비스를 설계해야한다. 즉, 로드밸런서가 각 요청을 여러개의 병렬 웹서버에 뿌려줘야 한다. 이 때, 각기 다른 병렬 웹서버가 공유하는 하나의 메모리에 클라이언트의 티켓 예약 요청을 순서대로 쌓아줘야 한다. 실제 요청의 처리가 이루어진 이후(예약 성공 or 예약 실패) 웹서버가 처리 결과를 클라이언트에게 응답한다.
정리하자면
- HTTP 요청에 대한 응답은 요청마다 연결 비용과 보안 핸드셰이크 오버헤드가 크다. 따라서 HTTP에 대한 응답은 여러개의 병렬 웹서버가 담당한다. (연결을 실질적으로 웹서버로 골고루 포워딩 해주는 것은 로드밸런서가 담당한다. 대표적으로 CDN이나, 쿠버네티스의 Service에서 로드밸런싱을 담당한다.)
- 각 병렬 웹서버는 요청을 redis에 enqueue한다. redis는 원자적 연산으로 비교적 공정성을 보장할 수 있다. 거기에 TCP 연결이 keep-alive이고, in-memory DB이기 때문에 초당 십만개의 요청이 burst되더라도 무난히 요청을 처리할 수 있다. (단, redis도 파이프라이닝, 즉 RTT 요청을 생략한 설계가 필요할 수 있다.)
캐싱
전통적인 redis의 사용 사례이다. redis를 네트워크 캐시로 둔다. 전세계에 서비스하는 애플리케이션의 경우, 각 Region(지역)의 둔 지역 서버 (Edge server라고 한다)에 redis를 이용한 네트워크 캐시서버를 두어 더 빠르게 db 쿼리결과를 제공할 수 있다.
redis 사용사례
Job Queue
- 클라이언트가 특정 작업 요청
- Producer(혹은 Dispatcher)가 Job을 redis Queue에 push
- 각 Worker가 blocking wait 하고 있다가 Job을 pop 해서 처리
- Stateless Application 구현에도 자주 쓰임
- Stateless Application에서, 다른 Worker가 실패한 Job을 Producer가 다시 Dispatching해야 한다.
- 상태 전이 → worker에서 실패 시 job에 Fail로 상태전이를 시킨다. Dispatcher는 Fail된 Job을 다시 Dispatching한다.
- Lease 및 revalidation → worker에서 상태전이도 채 못 시키고 무한루프나 커널패닉으로 식물인간화 되는 경우가 있다. 이 때 Job은 영영 미아가 된다. 이걸 방지하기 위해 Job에 Lease와 Revalidation 시스템을 둔다. Dispatcher는 Lease 시간 이후에도 Job이 끝나지 않았다면 다른 worker에 Dispatching한다. 만약 Worker가 Lease된 Job을 처리할 때 시간이 더 필요하면 revalidation을 한다.
- 쿠버네티스에서는 보통 각 Worker와 Producer들이 각각 하나의 Pod로 구현한다. 이 때 Job의 공정한 분배와 State 재활용은 Producer Pod들이 하고, 실제 작업은 Worker Pod들이 한다면, pod의 수를 유동적으로 늘리고 줄이고(Scale in/out), 각 pod들이 죽었을 때 재시동을 하는 것은 쿠버네티스가 담당한다.
Cache
- DB 조회 결과를 Redis에 캐싱
- 동일 요청에 대해 DB 부하를 직접적으로 감소
- TTL 설정으로 데이터 자동 만료 가능
Session Store
- 로그인 세션, 인증 토큰 저장
- 여러 서버가 하나의 네트워크 공유 메모리를 사용
- Stateless Application 구현에 자주 쓰인다.
- 요즘에는 아에 state를 서버쪽에 저장하지 않는 JWT같은 기술도 사용한다. (JWT는 모든 로그인 정보가 포함된 인증서를 서버가 서명한 뒤 클라이언트가 저장한다.)
Job Caching
- 계산 비용 큰 중간 결과를 Redis 캐시에 저장하는 경우
Idempotent(멱등성) 모장
- 같은 키를 가진 요청을 여러 번 보내도 결과가 동일
- 요청 처리 중간 상태를 서버에 남기지 않음
예:
- 결제 요청에 idempotency key 비교
- 이 때 idempotency key가 redis에 저장