LLM WikiAccess-protected knowledge portal
← 스터디 홈
2편 · 약 14분

지속성(RDB/AOF)과 메모리 관리

인메모리 저장소의 약점

Redis는 데이터를 메모리에 둔다. 프로세스가 재시작되거나 서버가 다운되면 데이터가 사라진다. 순수 캐시라면 이 특성이 문제가 되지 않지만, 세션, 카운터, 메시지 큐처럼 재시작 후에도 데이터가 필요한 경우라면 지속성이 필수다.

Redis는 두 가지 지속성 메커니즘을 제공한다.

  • RDB(Redis Database Snapshot): 특정 시점의 전체 스냅샷을 이진 파일로 저장한다.
  • AOF(Append-Only File): 모든 쓰기 명령을 로그로 기록한다.

두 가지를 함께 쓰는 하이브리드(hybrid) 방식도 Redis 4.0부터 지원한다.

RDB 스냅샷

RDB는 특정 시점의 메모리 전체를 이진 파일(dump.rdb)로 저장한다. 파일이 컴팩트하고 로드 속도가 빠르다.

BGSAVE와 fork

BGSAVE 명령을 실행하면 Redis 메인 프로세스가 fork()를 호출해 자식 프로세스를 생성한다. 자식이 RDB 파일을 디스크에 쓰는 동안 부모는 계속 클라이언트 요청을 처리한다.

fork 직후 부모와 자식은 동일한 물리 메모리 페이지를 공유한다. OS는 페이지를 읽기 전용(read-only) 으로 표시한다. 부모가 새로운 쓰기를 처리할 때 OS가 해당 페이지를 복사(Copy-on-Write, CoW)해서 부모만의 독립적인 사본을 만든다. 자식은 fork 시점의 일관된 스냅샷을 유지한다.

Redis 메인 프로세스 → fork() 자식 프로세스
부모 (계속 서빙)
클라이언트 요청 처리 새 쓰기 → CoW 페이지 복사
자식 (스냅샷 쓰기)
메모리 → dump.rdb fork 시점 스냅샷 일관성 유지
RDB BGSAVE: fork 후 자식이 스냅샷을 쓰는 동안 부모는 클라이언트 요청을 계속 처리한다

RDB 설정

# redis.conf
save 3600 1      # 3600초 동안 변경 1건 이상이면 자동 저장
save 300 100     # 300초 동안 변경 100건 이상이면 자동 저장
save 60 10000    # 60초 동안 변경 10000건 이상이면 자동 저장

dbfilename dump.rdb
dir /var/lib/redis

stop-writes-on-bgsave-error yes   # 저장 실패 시 쓰기 거부

수동 저장:

BGSAVE    # 비동기 (백그라운드, 권장)
SAVE      # 동기 (블로킹, 운영 중 사용 금지)
LASTSAVE  # 마지막 성공 저장 타임스탬프 확인

RDB 장단점

장점:

  • 로드 속도가 빠르다. 재시작 복구 시간이 짧다.
  • 파일이 컴팩트해 백업·이전·원격 전송이 쉽다.
  • fork/CoW 덕분에 부모 성능에 영향이 적다.

단점:

  • 마지막 스냅샷 이후 데이터는 유실된다(분 단위 손실 가능).
  • 데이터셋이 크면 fork 비용이 크고, fork 순간 메모리 사용량이 일시적으로 증가할 수 있다.

AOF (Append-Only File)

AOF는 모든 쓰기 명령을 텍스트 로그(appendonly.aof)에 순서대로 기록한다. 재시작 시 이 파일을 재생(replay)해 데이터를 복원한다.

fsync 정책

AOF의 내구성은 appendfsync 설정으로 결정된다.

정책동작데이터 손실 위험쓰기 성능
always명령마다 fsync최대 1개 명령낮음
everysec1초마다 fsync (기본값)최대 1초 분량중간
noOS가 flush 결정수십초 가능높음

운영 환경에서는 everysec을 권장한다. always는 쓰기 집중 워크로드에서 IOPS 병목이 생기고, no는 OS flush 타이밍에 의존해 예측 불가능한 손실이 발생할 수 있다.

# redis.conf
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no   # rewrite 중에도 fsync 허용

AOF 재작성 (Rewrite)

시간이 지나면 AOF 파일에 불필요한 중간 상태 명령이 쌓인다. INCR counter를 1000번 실행한 결과는 SET counter 1000 한 줄로 대체할 수 있다.

AOF 재작성도 fork를 사용해 백그라운드에서 동작한다. 자식이 현재 메모리 상태를 최소 명령 집합으로 새 파일에 쓰는 동안, 부모는 새 쓰기를 기존 AOF와 재작성 버퍼에 함께 기록한다. 재작성 완료 시 새 파일로 원자적으로 교체한다.

# 자동 재작성 설정 (권장)
auto-aof-rewrite-percentage 100   # 마지막 재작성 대비 100% 증가 시 트리거
auto-aof-rewrite-min-size 64mb    # 최소 64 MB 이상일 때만 재작성

# 수동 트리거
BGREWRITEAOF

AOF 장단점

장점:

  • 내구성이 높다. everysec이면 최대 1초 분량만 손실.
  • 텍스트 포맷이라 파일을 직접 읽거나 편집할 수 있다.
  • 쓰기 오류 시 redis-check-aof 도구로 일부 복구 가능.

단점:

  • 같은 데이터셋에 대해 RDB보다 파일이 크다.
  • 재시작 복구 속도가 RDB보다 느리다(명령을 재생해야 함).
  • always 정책은 I/O 집중 워크로드에서 병목.

하이브리드 지속성

Redis 4.0부터 하이브리드(hybrid) 방식을 지원한다. AOF 파일의 앞부분에 RDB 스냅샷을 기록하고, 그 이후의 명령만 AOF 형식으로 덧붙인다. 재시작 시 RDB 부분을 먼저 빠르게 로드하고, 이후 AOF 부분만 재생하므로 복구 속도와 내구성을 함께 얻는다.

# redis.conf
aof-use-rdb-preamble yes   # Redis 7.0+에서 기본값 yes

세 방식의 특성 비교:

방식복구 속도데이터 손실 위험파일 크기권장 용도
RDB빠름분 단위작음백업, 복제 초기화
AOF느림초 단위높은 내구성 요구
Hybrid빠름초 단위중간운영 환경 일반

메모리 관리와 maxmemory

Redis는 maxmemory로 사용 가능한 최대 메모리를 제한할 수 있다.

# redis.conf
maxmemory 2gb
maxmemory-policy allkeys-lru

maxmemory에 도달하면 maxmemory-policy에 따라 키를 축출(eviction)하거나 에러를 반환한다.

축출 정책 (Eviction Policy)

정책대상알고리즘권장 용도
noeviction없음 (에러 반환)중요 데이터 저장, 유실 불허
allkeys-lru전체 키LRU범용 캐시 (기본 추천)
volatile-lruTTL 있는 키LRU세션·임시 데이터 캐시
allkeys-lfu전체 키LFU접근 빈도 기반 캐시
volatile-lfuTTL 있는 키LFU빈도 기반 세션 캐시
allkeys-random전체 키무작위균등 분포 데이터
volatile-randomTTL 있는 키무작위만료 예정 데이터
volatile-ttlTTL 있는 키TTL 가장 짧은 것 먼저명시적 만료 관리

LRU vs LFU: LRU는 최근에 접근한 키를 유지한다. 최근에 한 번 접근했지만 거의 쓰이지 않는 키도 살아남는 단점이 있다. LFU는 접근 빈도를 추적해 자주 쓰이는 키를 유지하므로 캐시 히트율이 더 높을 때가 많다. 접근 패턴이 시간에 따라 변화한다면 LFU가 유리하다.

주의: Redis의 LRU/LFU는 엄밀한 전체 정렬이 아닌 샘플 기반 근사(approximate) 알고리즘이다. maxmemory-samples(기본값 5)를 높이면 정확도가 올라가지만 CPU를 더 사용한다.

용도에 따른 지속성 + 메모리 설정 선택

순수 캐시
(유실 허용)
세션·임시 데이터
(분 단위 손실 허용)
메시지·이벤트
(손실 최소화)
지속성 끔
allkeys-lru
RDB only
volatile-lru
RDB + AOF hybrid
appendfsync everysec
noeviction
용도별 권장 설정

운영 확인 명령

# 현재 메모리 사용 현황
INFO memory

# 지속성 상태
INFO persistence

# 마지막 RDB 저장 성공 여부
LASTSAVE

# AOF 재작성 수동 트리거
BGREWRITEAOF

INFO memory에서 주목할 지표:

  • used_memory_human: 현재 사용 중인 메모리(RSS 아님)
  • mem_fragmentation_ratio: 단편화 비율. 1.0 미만이면 스왑 사용 중, 1.5 이상이면 단편화 심각
  • maxmemory_human: 설정된 상한
  • evicted_keys: 지금까지 축출된 키 수

한 줄 정리

RDB는 빠른 복구, AOF는 높은 내구성을 제공하며, 운영 환경에서는 하이브리드(RDB preamble + AOF everysec)가 두 장점을 함께 잡는 가장 일반적인 선택이다.

References

  • https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/
  • https://engineeringatscale.substack.com/p/redis-persistence-aof-rdb-crash-recovery
  • https://www.sobyte.net/post/2022-08/redis-rdb-and-aof/
  • https://www.dragonflydb.io/guides/redis-persistence-3-technical-approaches
  • https://medium.com/@srujana.dakoju/redis-cache-eviction-strategies-b806c67e37c0
  • https://redis.io/blog/cache-eviction-strategies/
  • https://redis-doc-test.readthedocs.io/en/latest/topics/lru-cache/
  • https://docs.aws.amazon.com/whitepapers/latest/database-caching-strategies-using-redis/evictions.html