데이터베이스

레디스 데이터는 언제 유실될까?

삼록이 2025. 7. 21. 13:25

레디스란?

Key-Value 형태로 데이터를 저장하는 인메모리 데이터베이스다.

보통의 데이터베이스가 디스크에 저장되는데 반해 레디스의 데이터는 메모리에 저장되어 매우 빠르다는 장점이 존재하나, 데이터가 유실될 수도 있어 휘발성을 가지고 있다고도 한다.

 

우리가 들어온 레디스에 대한 설명이다.

그런데 사실 프로젝트를 몇 번 진행하며 레디스의 데이터가 유실된 것을 본적이 없다.

메모리에 저장되어 휘발성이 있다고 하는데 컴퓨터를 껐다 켜도 이전의 데이터가 여전히 레디스에 남아있다.

그 이유는 뭘까?

 


데이터 유실을 본 적이 없던 이유

사실, 제일 처음 만들어졌을 때는 레디스는 데이터가 영구히 저장되는 영속성을 지원하지 않았으나, 어느 순간부터는 다른 DB처럼 영속성이 지원되어졌다. 그 영속석을 지원하는 2가지 방법이 바로 스냅샷과 AOF다.

 

  • 스냅샷 : 일정 간격으로 전체 데이터를 스냅샷 형태로 디스크에 저장한다. 그래서 서버를 다시 켜 마지막 저장 시점으로 복원된다.
  • AOF : 클라이언트가 레디스에게 보냈던 모든 명령어를 저장해두었던 파일이다. 즉, 레디스에 데이터가 쌓이고 변화했던 모든 명령어가 AOF라는 파일에 따로 저장된 것이고 레디스는 서버가 재시작되면 다시 이 파일을 처음부터 끝까지 읽고 명령을 한 줄 씩 실행해 기존 상태로 완벽하게 복구되는 것이다.

이로 인해, 나는 레디스의 데이터가 유실된 것을 본 적이 없는 것이다.

그럼에도 불구하고 휘발성이 있다라고 아직까지 정의하는 데는 분명 이유가 있을 것인데.. 그럼 도대체 언제 휘발된다는 말일까?


메모리가 꽉 찬다면?

바로 메모리가 꽉 찼을 때 삭제 될 수 있다.

레디스의 메모리가 꽉 찼을 때, 레디스의 설정상태에 따라 데이터가 삭제된다. 즉 유실된다는 말이다.

기본적으로 레디스의 설정상태는 메모리가 꽉 찼을 때 데이터가 삭제되지 않도록 설정해놓았다. 

데이터는 유실되지 않겠지만, 메모리가 꽉 찼으니 레디스에 추가 데이터를 삽입할 수도 없는 상태가 되버린다.

그래서 일반적으로 레디스의 설정을 메모리가 꽉 차면 일부 데이터를 삭제하는 설정으로 세팅한다고 한다.

 

그렇다면 내 레디스의 메모리는 얼마이고 얼마나 사용하고 있는지 어떻게 알 수 있을까?

info memory 명령어를 통해 확인 할 수 있다.

그러면 여러 항목이 나올텐데, 그 중 아래 사항에 대해 설명해보자면,

  • used_memory :레디스가 현재 사용중인 총 메모리(bytes 단위)
  • user_memory_human:레디스가 현재 사용중인 총 메모리를 읽기 쉽게 표현하므로 이걸 보면 된다.(대략 994 킬로바이트)
  • used_memory_rss: 운영체제에서 레디스 프로세스에 할당하고 있는 현재 메모리양
  • used_memory_rss_human: 운영체제에서 레디스 프로세스에 할당한 현재 메모리양를 읽게 쉽게 표현(18MB다)
  • maxmemory : 설정된 최대 메모리 제한(0이면 제한 없음)
  • maxmemory_policy : 메모리가 찼을 때 삭제 정책

*maxmemory가 0라는 것은 레디스 기본 설정으로 레디스는 OS가 허락하는 한 무제한으로 메모리를 사용하려고 하는 설정이다.

따라서 실제 운영환경에서는 maxmemory를 명시적으로 설정해서 레디스가 전체 서버 메모리를 다 잡아먹지 않도록 해야한다고 한다.

(실제 전체 메모리의 2~30%선으로 명시해두는게 좋다고하는데 확실치는 않다)

 


maxmemory-policy 정책

레디스는 메모리 기반이라 메모리 한도를 넘으면 새 데이터를 넣을 수가 없다. 

그렇다면 그 순간 무언가를 삭제해야하는데 그때 무엇을 지울지를 정하는 정책이 바로 이  maxmemory-policy다.

정책이름 제거 대상 알고리즘 설명
noeviction 아무것도 안 지움 없음 기본값. 새 쓰기 요청 거절함
allkeys-lru 모든 키 LRU 가장 자주 안 쓰인 키부터 제거
volatile-lru TTL 있는 키만 LRU TTL 설정된 키 중 덜 사용된 것 제거
allkeys-random 모든 키 Random 무작위로 삭제 (속도 빠름, 정교하지 않음)
volatile-random TTL 있는 키만 Random TTL 있는 키 중 무작위 삭제
volatile-ttl TTL 있는 키만 짧은 TTL 만료 임박한 키부터 제거

 

noeviction은 기본 설정으로 메모리가 꽉 차면 데이터가 삭제되지 않는 대신 새로운 데이터가 들어올 수도 없다.

휘발되면 안되는 리프레시 토큰이나,세션,인증 정보 처럼 삭제되면 안되는 데이터가 있을 때 추천된다.

 

allkeys-lru는 가장 일반적인 캐시용 정책이다.

레디스를 순수 캐시용으로 쓰는 경우로 실무에서 가장 많이 쓰이는 정책이라고 한다. 


설정 바꾸는 방법

도커로 run할 때 아래와 같이 옵션을 주어 run을 하는게 편해서 이 명령어를 가지고 왔다.

docker run -d --name redis -p 6379:6379 redis --maxmemory 512mb --maxmemory-policy allkeys-lru

 

그런데 나 같은 경우에는 리프레시 토큰과 캐싱용도로 같이 레디스를 운용 중이라.

noeviction으로 하기에도 애매하고 allkeys-lru 설정을 하기에도 애매하다.

그럴 경우에는 docker로 포트를 달리하여 레디스를 2개를 띄우고, 스프링에서 토큰용 레디스, 캐싱용 레디스 따로 띄우는 것도 방법이다.