Redis 핵심 정리 시리즈 4편. RDB 스냅샷·AOF 로그·하이브리드 모드까지 — 인메모리 DB가 재시작 후에도 데이터를 잃지 않게 하는 영속성 전략을 사진 보관·일지 기록·합본 비유로 풀어가며 fsync 정책·성능 트레이드오프·복구 시나리오까지 친절하게 정리한 글.
이 글은 Redis 핵심 정리 시리즈의 네 번째 편입니다. 1편에서 Redis가 인메모리 DB라는 정체를 잡았고, 2편에서는 자료 구조를, 3편에서는 운영 명령어를 익혔어요. 그런데 한 가지 큰 질문이 남아 있어요 — "Redis는 RAM에 다 저장한다는데, 서버가 꺼지면 데이터가 다 날아가는 거 아닌가요?" 그 답이 이번 편의 주제예요.
Redis는 RDB(스냅샷)와 AOF(로그)라는 두 가지 영속성 메커니즘을 지원합니다. 그리고 둘을 합친 하이브리드 모드가 가장 권장되는 운영 설정이에요. 이번 편에서는 각자의 동작 원리·트레이드오프·복구 시나리오까지 한 번에 정리합니다.
왜 영속성 단원이 처음엔 어렵게 느껴질까요
이유는 세 가지예요.
첫째, 이름이 비슷한 약어가 너무 많아요. RDB·AOF·BGSAVE·BGREWRITEAOF·fsync·EVERYSEC — 한 페이지에 몰려 나오면 머리가 어지럽습니다.
둘째, 트레이드오프가 다차원이에요. 성능 vs 내구성 vs 복구 속도 vs 파일 크기 — 네 축을 동시에 놓고 비교해야 해서 한 번에 안 잡혀요.
셋째, 운영 권장 설정이 글마다 달라 보입니다. 누구는 RDB만 쓰라 하고, 누구는 AOF만 쓰라 하고, 누구는 둘 다 쓰라 해요. 정답이 헷갈리죠.
해결법은 한 가지예요. 두 가지를 일상 비유로 나눠 잡고 가는 겁니다. RDB는 주기적으로 사진 한 장 찍어 보관, AOF는 모든 변경을 일지에 기록, 하이브리드는 사진 + 일지 합본. 이 비유가 잡히면 트레이드오프와 권장 설정이 자연스럽게 따라옵니다.
영속성이 왜 필요한가 — 큰 그림
Redis는 기본적으로 모든 데이터를 RAM에만 저장해요. 서버가 재시작되면 데이터가 다 사라집니다. 영속성 메커니즘이 없으면 캐시 외 용도로는 쓰기 어려워요.
영속성을 켜면 — 재시작 후에도 데이터를 자동 복구할 수 있어요. 두 가지 방식 중 하나(또는 둘 다)를 골라 디스크에 데이터를 저장해 두는 거예요.
| 방식 | 비유 | 한 줄 설명 |
|---|---|---|
| RDB | 주기적 사진 보관 | 특정 시점의 전체 데이터를 바이너리로 저장 |
| AOF | 변경 일지 기록 | 모든 쓰기 명령을 텍스트 로그에 기록 |
| 하이브리드 | 사진 + 일지 합본 | RDB 스냅샷 위에 그 후 변경만 AOF로 |
자세한 영속성 옵션은 Redis 영속성 공식 문서에 정리되어 있어요. 이 글은 그걸 한국어 비유 톤으로 풀어 가는 학습 노트입니다.
RDB — 주기적으로 사진 한 장 찍기
RDB(Redis Database) 스냅샷은 특정 시점(point-in-time)의 Redis 데이터 전체를 바이너리 파일(dump.rdb)로 저장하는 방식이에요. 회사 비유로 — 사물함 전체를 정해진 시간마다 카메라로 한 컷 찰칵 찍어 사진을 보관하는 거예요. 사진 한 장에 사물함 전체가 담겨 있어 복구할 때 빠르게 펼치면 끝나요.
RDB가 동작하는 방식 — fork() 트릭
RDB의 우아한 점이 하나 있어요 — fork() 시스템 콜로 자식 프로세스를 만들어 백그라운드에서 저장합니다. 그래서 부모 프로세스(메인 Redis)는 클라이언트 요청을 계속 처리할 수 있어요.
RDB 저장 과정:
1. Redis 메인 프로세스가 fork() 호출
2. 자식 프로세스 생성 (메모리 페이지 복사 — Copy-On-Write)
3. 자식 프로세스가 dump.rdb 파일에 데이터 저장
4. 부모 프로세스는 계속 클라이언트 요청 처리
5. 자식 프로세스 완료 후 종료
여기서 시험 함정이 하나 있어요. fork()는 Copy-On-Write(COW) 라는 리눅스 메커니즘을 활용해요. 자식 프로세스를 만들 때 메모리를 통째로 복사하지 않고, 변경이 일어난 페이지만 복사합니다. 그래서 RDB 저장 중에도 메모리 사용량이 두 배가 되지 않아요(쓰기 트래픽이 폭증하지 않는 한).
RDB 설정 (redis.conf)
# 자동 스냅샷 — save <초> <변경_횟수>
# "N초 동안 M번 이상 변경이 있으면 스냅샷 저장"
save 3600 1 # 1시간 내 1번 이상 변경 시
save 300 100 # 5분 내 100번 이상 변경 시
save 60 10000 # 1분 내 10000번 이상 변경 시
# 저장 파일 설정
dbfilename dump.rdb
dir /var/lib/redis # 저장 디렉토리
# 압축 (권장)
rdbcompression yes
# CRC64 체크섬 (무결성 확인)
rdbchecksum yes
# RDB 저장 실패 시 쓰기 거부
stop-writes-on-bgsave-error yes
save 옵션이 여러 줄 있는 건 OR 조건이에요. "1시간에 1번 변경" OR "5분에 100번 변경" OR "1분에 10000번 변경" 중 하나라도 만족하면 저장해요. 트래픽이 많을수록 더 자주 사진을 찍는 적응형 패턴이에요.
수동 RDB 저장
# 백그라운드 저장 (비동기 — 권장)
BGSAVE
# 응답: Background saving started
# 동기 저장 (블로킹 — 운영 환경 사용 주의)
SAVE
# 완료될 때까지 모든 클라이언트 요청 차단
# 마지막 저장 시간 확인
LASTSAVE # Unix 타임스탬프
여기서 시험 함정이 하나 있어요. SAVE는 운영에서 절대 금지예요. 백그라운드 fork() 없이 메인 스레드가 직접 저장하니까 그동안 모든 요청이 블로킹돼요. 운영에서는 항상 BGSAVE 입니다.
RDB의 장점·단점
RDB 장점:
- 복구 빠름 (바이너리 한 번에 로드)
- 파일 크기 작음 (압축됨)
- 쓰기 성능에 영향 적음 (주기적으로만 저장)
- 백업·이관에 편리 (한 파일 복사하면 끝)
RDB 단점:
- 두 스냅샷 사이 데이터 손실 위험
(예: save 3600 1 → 최대 1시간 손실 가능)
- 큰 데이터셋에서 fork() 비용 (수 초 멈출 수 있음)
RDB 복구 흐름
# RDB 파일로 복구하는 방법:
# 1. Redis 서버 중지
# 2. dump.rdb 파일을 데이터 디렉토리에 복사
# 3. Redis 서버 재시작 → 자동으로 dump.rdb 로드
# 파일 위치 확인
redis-cli CONFIG GET dir
redis-cli CONFIG GET dbfilename
한 줄 정리 — RDB = 주기적 사진. 빠른 복구 + 작은 파일, 단 사진 사이 손실 위험.
AOF — 변경 일지에 모든 쓰기를 기록
AOF(Append Only File) 는 Redis에 실행된 모든 쓰기 명령어를 로그 파일(appendonly.aof)에 순차적으로 기록하는 방식이에요. 서버 재시작 시 이 로그를 처음부터 재실행하여 데이터를 복구합니다.
회사 비유로 — 사물함에 일어난 모든 변경을 빠짐없이 일지에 적어 두는 방식이에요. 누가 봉투를 넣었고, 누가 어떤 봉투를 꺼냈고, 누가 어떤 라벨을 바꿨고 — 다 기록합니다. 재시작하면 일지를 처음부터 다시 읽어 사물함 상태를 복원해요.
AOF 동작:
클라이언트 명령 → Redis 실행 → appendonly.aof에 기록
↓
재시작 시 AOF 파일의 모든 명령 재실행 → 데이터 복구
AOF 설정
# AOF 활성화
appendonly yes
appendfilename "appendonly.aof"
dir /var/lib/redis
# Fsync 정책 (디스크 동기화 빈도)
appendfsync everysec # 기본값 — 매초 fsync (성능·내구성 균형)
# appendfsync always # 모든 쓰기마다 fsync (최고 내구성)
# appendfsync no # OS 결정 (최고 성능)
# AOF 재작성 중 fsync 비활성화 (성능 개선)
no-appendfsync-on-rewrite no
# AOF 자동 재작성 트리거
auto-aof-rewrite-percentage 100 # 기준 크기 대비 100% 이상 커지면
auto-aof-rewrite-min-size 64mb # 단, 최소 64MB 이상일 때만
Fsync 정책 — 가장 중요한 트레이드오프
appendfsync가 영속성 단원에서 가장 중요한 옵션이에요. 디스크에 실제로 데이터를 쓰는 빈도를 결정합니다.
| fsync 정책 | 데이터 손실 위험 | 성능 영향 | 설명 |
|---|---|---|---|
| always | 없음 (0 손실) | 매우 큼 | 모든 쓰기마다 fsync |
| everysec | 최대 1초 | 작음 | 1초마다 fsync (기본값·권장) |
| no | 클 수 있음 | 없음 | OS가 결정 (수 초~수십 초) |
여기서 정말 중요한 시험 함정 — everysec은 최대 1초 손실 가능입니다. "AOF 쓰면 손실 0개"가 아니에요. 1초 동안의 명령어는 OS 버퍼에만 있다가 fsync 직전 서버가 죽으면 사라집니다. 0 손실을 원하면 always — 단 성능이 크게 떨어져요.
AOF 재작성(Rewrite)
AOF 파일은 시간이 지나면 계속 커져요. 예를 들어 INCR counter를 1000번 실행하면 파일에 1000줄이 기록되지만, 실제로는 SET counter 1000 한 줄만 있어도 같은 결과가 나와요. AOF 재작성은 이런 중복을 제거해 파일 크기를 줄입니다.
# 수동 AOF 재작성 (백그라운드)
BGREWRITEAOF
# 재작성 진행 상태 확인
INFO persistence
자동 재작성은 auto-aof-rewrite-percentage와 auto-aof-rewrite-min-size 두 옵션이 동시에 만족될 때 트리거돼요.
AOF 복구
# AOF 파일 무결성 확인
redis-check-aof appendonly.aof
# 손상된 AOF 파일 수정 (불완전한 부분 잘라냄)
redis-check-aof --fix appendonly.aof
# 복구 과정:
# 1. Redis 서버 중지
# 2. appendonly.aof 파일을 데이터 디렉토리에 복사
# 3. Redis 서버 재시작 → 자동으로 AOF 재실행
여기서 시험 함정이 하나 있어요. AOF 파일이 손상됐을 때 --fix는 손상된 부분 이후를 통째로 잘라내요. 그 부분의 데이터는 잃어버립니다. 가능하면 정기 백업을 따로 두는 게 안전해요.
AOF 장점·단점
AOF 장점:
- 내구성 높음 (everysec: 최대 1초 손실)
- 사람이 읽을 수 있는 텍스트 로그 (디버깅 용이)
- 자동 재작성으로 파일 크기 관리 가능
AOF 단점:
- 파일 크기 큼 (RDB 대비)
- 복구 느림 (모든 명령 재실행)
- 쓰기 성능 영향 있음 (everysec도 약간 느려짐)
한 줄 정리 — AOF = 변경 일지. 높은 내구성, 단 파일 크기·복구 시간 큼.
하이브리드 모드 — 사진 + 일지 합본
Redis 4.0+부터 RDB와 AOF를 함께 사용하는 하이브리드 모드를 지원해요. 가장 우아한 운영 설정이에요.
핵심 아이디어 — AOF 재작성 시점에 RDB 스냅샷을 파일 시작 부분에 넣고, 그 이후 변경사항만 AOF 형식으로 추가합니다. 이렇게 하면 빠른 복구(RDB)와 높은 내구성(AOF)을 동시에 달성할 수 있어요.
하이브리드 설정
# redis.conf
appendonly yes # AOF 활성화
aof-use-rdb-preamble yes # 하이브리드 모드 활성화
# AOF 재작성 트리거
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
하이브리드 파일 구조
appendonly.aof (하이브리드 모드):
┌─────────────────────────────────┐
│ RDB 바이너리 스냅샷 │ ← 재작성 시점의 전체 데이터
│ (빠른 로드) │
├─────────────────────────────────┤
│ AOF 텍스트 로그 │ ← 스냅샷 이후 변경사항
│ SET key1 value1 │
│ INCR counter │
│ ... │
└─────────────────────────────────┘
복구 흐름 — 1. AOF 파일 시작의 RDB 스냅샷을 빠르게 로드 2. 그 이후의 AOF 로그를 순차 재실행 3. 둘이 합쳐져 마지막 상태까지 복원
이게 우아한 이유는 — 재시작 복구 시간은 RDB만큼 빠르고, 데이터 손실은 AOF만큼 작아요. 그래서 일반 운영의 권장 기본 설정입니다.
영속성 비교 — 한 표로 정리
| 비교 항목 | RDB | AOF | 하이브리드 |
|---|---|---|---|
| 내구성 | 낮음 (스냅샷 간격만큼 손실) | 높음 (everysec: 최대 1초) | 높음 |
| 복구 속도 | 빠름 (바이너리 로드) | 느림 (모든 명령 재실행) | 빠름 |
| 파일 크기 | 작음 | 큼 | 중간 |
| 쓰기 성능 | 좋음 (주기적 저장) | 영향 있음 (everysec) | 중간 |
| 가장 적합 | 캐시·재생성 가능 데이터 | 금융·중요 데이터 | 일반 목적 (권장) |
| Redis 기본값 | 활성 (주기적) | 비활성 | — |
여기서 시험 단골 — 권장 설정 = 하이브리드 (AOF + aof-use-rdb-preamble yes). 단순 캐시 용도면 RDB만으로도 충분.
영속성 모니터링 — INFO persistence
redis-cli INFO persistence
주요 출력 항목 —
rdb_last_save_time # 마지막 RDB 저장 Unix 타임스탬프
rdb_changes_since_last_save # 마지막 저장 이후 변경 수
rdb_last_bgsave_status # 마지막 백그라운드 저장 상태 (ok/err)
aof_enabled # AOF 활성화 여부 (0/1)
aof_current_size # 현재 AOF 파일 크기 (바이트)
aof_rewrite_in_progress # AOF 재작성 진행 중 여부 (0/1)
aof_last_rewrite_time_sec # 마지막 재작성 소요 시간
aof_last_bgrewrite_status # 마지막 백그라운드 재작성 상태
운영 모니터링에서는 rdb_last_bgsave_status·aof_last_bgrewrite_status 두 값이 ok인지가 가장 중요해요. err이면 디스크 공간 부족·fork() 실패 같은 사고가 일어났다는 신호입니다.
운영 환경 권장 설정
# /etc/redis/redis.conf (운영 권장)
# RDB 설정
save 3600 1
save 300 100
save 60 10000
rdbcompression yes
rdbchecksum yes
# AOF 설정
appendonly yes
appendfsync everysec
no-appendfsync-on-rewrite yes # 재작성 중 성능 최적화
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 하이브리드 모드 (Redis 4.0+)
aof-use-rdb-preamble yes
# 슬레이브에서 RDB 비활성화 (마스터만 RDB)
# 슬레이브는 AOF만 사용 권장
이 설정이 일반 운영의 기본 베이스예요. 특수한 요구사항(금융 데이터·완전 무손실 등)이 없으면 이 설정에서 시작하는 게 안전합니다.
데이터 복구 시나리오
시나리오 1 — 정상 재시작
Redis 시작 시 자동:
1. AOF가 활성화되어 있으면 AOF 파일 로드
2. AOF가 비활성화되어 있으면 RDB 파일 로드
3. 두 파일 모두 없으면 빈 데이터베이스로 시작
여기서 시험 함정이 하나 있어요. 두 파일이 모두 있을 때 Redis는 AOF를 우선 로드합니다. AOF가 더 최신 데이터를 보장하기 때문이에요. 만약 RDB 파일을 우선 쓰고 싶다면 appendonly no로 명시해야 합니다.
시나리오 2 — AOF 파일 손상
redis-check-aof --fix /var/lib/redis/appendonly.aof
# → 손상된 부분까지만 복구, 이후 데이터는 손실
시나리오 3 — RDB로 특정 시점 복구
# 1. Redis 중지
systemctl stop redis
# 2. 백업된 dump.rdb 파일 복사
cp /backup/dump.rdb.2024-01-15 /var/lib/redis/dump.rdb
# 3. Redis 시작
systemctl start redis
백업 스크립트 예시
#!/bin/bash
BACKUP_DIR="/backup/redis"
DATE=$(date +%Y%m%d_%H%M%S)
REDIS_DATA_DIR="/var/lib/redis"
mkdir -p $BACKUP_DIR
# RDB 저장 트리거
redis-cli BGSAVE
# 저장 완료 대기 (LASTSAVE 변화 감지)
PREV_LASTSAVE=$(redis-cli LASTSAVE)
while [ $(redis-cli LASTSAVE) -eq $PREV_LASTSAVE ]; do
sleep 1
done
# 파일 복사
cp $REDIS_DATA_DIR/dump.rdb $BACKUP_DIR/dump.rdb.$DATE
# 30일 이상 된 백업 삭제
find $BACKUP_DIR -name "dump.rdb.*" -mtime +30 -delete
echo "Redis backup completed: $BACKUP_DIR/dump.rdb.$DATE"
영속성 vs 복제 — 다른 도구
자주 헷갈리는 핵심 한 가지 — 영속성과 복제(Replication)는 서로 다른 도구예요. 둘 다 데이터 보호 목적이지만 동작과 보장이 달라요.
복제(Replication):
- 데이터를 여러 서버에 분산
- 서버 한 대 장애 시 다른 서버에서 서비스 유지
- 모든 서버가 동시에 종료되면 데이터 손실 (디스크에 저장 안 했으면)
영속성(Persistence):
- 데이터를 디스크에 저장
- 재시작 후에도 데이터 유지
- 디스크 장애 시 데이터 손실 (다른 서버에 복사 안 했으면)
완전한 보호 = 복제 + 영속성 모두 사용
여기서 시험 함정이 하나 있어요. "복제만 켜 놓으면 안전한가요?" 정답은 아니에요. 모든 노드가 동시에 재시작되면(데이터 센터 정전 같은 상황) 영속성이 없으면 데이터가 다 사라져요. 복제는 노드 장애 대응, 영속성은 재시작 대응 — 자리가 달라요.
자세한 클러스터·복제 흐름은 7편에서 풀어 갑니다.
성능과 내구성 트레이드오프
영속성 옵션을 고를 때 핵심 축이 두 가지예요.
성능 영향
대략적인 벤치마크(환경에 따라 다름) —
영속성 없음: ~100,000 ops/sec
RDB (60s/10k): ~98,000 ops/sec (-2%)
AOF everysec: ~80,000 ops/sec (-20%)
AOF always: ~10,000 ops/sec (-90%)
AOF always는 디스크 I/O 병목으로 성능 저하가 매우 커요. 금융처럼 절대 손실 불가가 아닌 한 거의 쓰지 않습니다.
데이터 손실 위험
손실 위험 (낮음 → 높음):
AOF always < AOF everysec < RDB(1분) < RDB(1시간) < 영속성 없음
권장 매핑:
- 캐시 용도: 영속성 없음 또는 RDB
- 일반 목적: AOF everysec + RDB 하이브리드 (가장 권장)
- 크리티컬 데이터: AOF always
운영에서 자주 틀리는 함정 4가지
1. 디스크 공간 부족
AOF 파일은 자동 재작성 없이 두면 무한히 커져요.
# 모니터링
df -h /var/lib/redis
redis-cli INFO persistence | grep aof_current_size
# 자동 재작성 설정 필수
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
2. fork() 실패
대용량 데이터(>10GB)에서 BGSAVE·BGREWRITEAOF 시 fork() 실패가 일어날 수 있어요. Linux 커널 설정으로 예방합니다.
# /proc/sys/vm/overcommit_memory = 1 권장
echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf
sysctl -p
# redis.conf
stop-writes-on-bgsave-error yes # 저장 실패 시 쓰기 거부 (안전 장치)
3. AOF·RDB 동시 활성화 시 우선순위
# 두 파일 모두 있을 때 Redis는 AOF를 우선 로드
appendonly yes # AOF 우선
appendonly no # RDB만
4. SAVE 명령 운영 사용
SAVE # 동기 저장 — 모든 요청 블로킹 (운영 절대 금지)
BGSAVE # 백그라운드 — 권장
동적 설정 변경
운영 중 재시작 없이 영속성 설정을 바꿀 수 있어요.
# 현재 설정 확인
redis-cli CONFIG GET save
redis-cli CONFIG GET appendonly
redis-cli CONFIG GET appendfsync
redis-cli CONFIG GET aof-use-rdb-preamble
# 동적 변경
redis-cli CONFIG SET appendonly yes
redis-cli CONFIG SET appendfsync everysec
redis-cli CONFIG REWRITE # 변경사항을 redis.conf에 저장
시험 직전 한 번 더 — 자주 헷갈리는 함정 모음
여기까지가 Redis 4편의 핵심입니다. 시험·면접 직전 압축 노트로 마무리할게요.
- RDB = 주기적 사진. 빠른 복구 + 작은 파일, 단 사진 사이 손실 위험
- AOF = 변경 일지. 높은 내구성, 단 파일 크기·복구 시간 큼
- 하이브리드(권장) = RDB 스냅샷 + AOF 로그 합본. 빠른 복구 + 높은 내구성
- RDB는
fork()+ Copy-On-Write 로 백그라운드 저장 (메인 스레드 비블로킹) save 3600 1= "1시간 내 1번 변경 시 저장" — OR 조건 누적SAVE운영 절대 금지 — 메인 스레드 블로킹. 항상BGSAVE- AOF fsync 정책 —
always(0손실, 매우 느림) /everysec(최대 1초 손실, 권장) /no(OS 결정) everysec도 최대 1초 손실 가능 — "AOF=무손실"은 오답- AOF 재작성(
BGREWRITEAOF) — 중복 명령 제거로 파일 크기 축소 - 자동 재작성 —
auto-aof-rewrite-percentage+auto-aof-rewrite-min-size둘 다 만족 시 - 하이브리드 활성화 —
aof-use-rdb-preamble yes(Redis 4.0+) - 두 파일 모두 있을 때 — AOF 우선 로드 (더 최신)
- AOF 손상 복구 —
redis-check-aof --fix(이후 데이터 손실) - 복제 ≠ 영속성 — 복제는 노드 장애, 영속성은 재시작 대응. 자리 다름
- 완전 보호 = 복제 + 영속성 모두
- 권장 운영 설정 —
appendonly yes+appendfsync everysec+aof-use-rdb-preamble yes - 슬레이브 노드 — RDB 비활성(
save ""), AOF만 - 모니터링 —
INFO persistence로*_status값ok확인 - 디스크 공간 — AOF 자동 재작성 없으면 무한 증가
- fork() 실패 예방 —
vm.overcommit_memory = 1 stop-writes-on-bgsave-error yes— 저장 실패 시 쓰기 거부 (안전 장치)- 동적 설정 —
CONFIG SET후CONFIG REWRITE로 영구화 - 데이터 손실 위험 순서 —
AOF always < AOF everysec < RDB(1분) < RDB(1시간) < 없음
시리즈 다른 편
같은 시리즈의 다른 글들도 같은 친절 톤으로 묶어 정리되어 있어요.
- 1편 — Redis 입문
- 2편 — 데이터 구조 7종 심화
- 3편 — 명령어 (TTL · SCAN · 트랜잭션 · 파이프라이닝)
- 4편 — 영속성 (RDB · AOF · 하이브리드) (현재 글)
- 5편 — 캐싱 패턴
- 6편 — Pub/Sub & Streams
- 7편 — 클러스터 · 고가용성
- 8편 — Spring Data Redis
- 9편 — 성능 최적화 (완)