• Redis는 데이터를 메모리에 들고 있다. 프로세스가 죽으면 그대로 사라지므로, 디스크에 남겨 재시작 후 복원하는 장치가 필요하다. 이것이 **지속성(persistence)**이다.
  • 방식은 두 가지다.
    • RDB(Redis Database): 특정 시점의 데이터 전체를 파일 하나로 덤프하는 스냅샷.
    • AOF(Append Only File): 데이터를 바꾼 쓰기 명령을 순서대로 기록한 로그. 재시작 시 로그를 재생해 상태를 복원한다.
  • 둘은 배타적이지 않다. 동시에 켤 수 있고, 데이터를 중요하게 다룬다면 그게 권장 구성이다.

RDB: 스냅샷

  • 어느 순간의 데이터셋 전체를 dump.rdb라는 바이너리 파일 하나로 저장한다.
  • 언제 저장할지는 save <초> <변경 키 수> 형식의 save point로 정한다. 조건을 만족하면 자동으로 스냅샷을 뜬다.
dir /data
dbfilename dump.rdb
save 900 1        # 900초 동안 1개 이상 변경되면 저장
save 300 10
save 60 10000     # 60초 동안 10000개 이상 변경되면 저장
  • save ""로 지정하면 자동 스냅샷이 완전히 꺼진다.
  • 수동으로 뜨려면 BGSAVE를 쓴다. SAVE도 있지만 메인 스레드를 블로킹하므로 운영 중에는 쓰지 않는다.

동작 방식

  • Redis가 fork()로 자식 프로세스를 만든다.
  • 자식이 임시 파일에 데이터셋을 쓰고, 다 쓰면 기존 dump.rdb를 원자적으로 교체(rename)한다.
  • 부모 프로세스는 디스크 I/O를 전혀 하지 않고 계속 클라이언트 요청을 처리한다. copy-on-write 덕분에 메모리 복사도 변경된 페이지만 발생한다.
  • 완성된 RDB 파일은 그 이후 수정되지 않으므로, 서버가 돌아가는 중에 그냥 복사해도 안전하다. 백업이 쉬운 이유다.

장단점

  • 장점
    • 단일 파일이라 컴팩트하다. 시간별·일별로 보관하거나 S3·원격지로 옮기기 좋아 백업과 재해 복구에 적합하다.
    • 부모 프로세스가 디스크 작업을 하지 않아 성능 영향이 작다.
    • 데이터셋이 클 때 AOF보다 재시작 로딩이 빠르다.
  • 단점
    • 마지막 스냅샷 이후의 쓰기는 전부 사라진다. 5분 간격으로 뜬다면 최대 5분치 유실을 각오해야 한다.
    • 데이터셋이 크면 fork() 자체가 수십 밀리초~1초까지 걸려 순간적으로 응답이 멈출 수 있다.

AOF: 명령 로그

  • 데이터를 변경하는 명령(SET, DEL, LPUSH 등)을 받을 때마다 파일 끝에 덧붙인다. 형식은 Redis 프로토콜(RESP) 그대로라 사람이 읽을 수 있다.
  • 재시작하면 이 로그를 처음부터 재생해서 메모리 상태를 복원한다.
appendonly yes
appendfsync everysec

appendfsync - 내구성의 핵심 손잡이

  • 파일에 쓴다고 곧바로 디스크에 안착하는 게 아니다. OS 버퍼에 머무르므로 fsync를 언제 호출하는지가 실제 유실 범위를 결정한다.
동작최대 유실성능
always명령 배치마다 fsync사실상 없음매우 느림
everysec1초마다 fsync (기본·권장)1초스냅샷과 비슷
noOS에 맡김리눅스 기준 약 30초가장 빠름
  • everysec은 fsync를 백그라운드 스레드에서 수행하고, 메인 스레드는 fsync가 진행 중이 아닐 때 쓰기를 몰아서 처리한다. 그래서 기본값으로 쓸 만하다.
  • always도 그룹 커밋을 지원해, 동시에 들어온 여러 쓰기를 한 번의 fsync로 묶는다.

로그 재작성(rewrite)

  • 카운터를 100번 증가시키면 최종 값은 하나지만 AOF에는 100줄이 쌓인다. 이대로 두면 파일이 무한정 커진다.
  • 그래서 Redis는 현재 데이터셋을 만드는 최소 명령 집합으로 로그를 다시 쓴다. 이것이 rewrite다.
  • 자동 트리거는 auto-aof-rewrite-percentage(직전 rewrite 대비 증가율)와 auto-aof-rewrite-min-size로 조절하고, 수동으로는 BGREWRITEAOF를 호출한다.
  • rewrite 중에도 기존 파일에 계속 append하다가 새 파일이 완성되면 교체하므로, 도중에 실패해도 안전하다.

Redis 7.0의 multi-part AOF

  • 7.0부터 AOF가 파일 하나가 아니다. appenddirname 디렉터리(기본 appendonlydir) 안에 세 종류가 들어간다.
    • base 파일: rewrite 시점의 스냅샷. 기본 설정에서는 RDB 포맷으로 저장된다(aof-use-rdb-preamble yes).
    • incr 파일: base 이후의 증분 명령 로그. 여러 개일 수 있다.
    • manifest 파일: 어떤 base와 incr가 유효한지 추적하는 목록.
  • 로딩할 때는 base를 읽고 incr를 이어서 재생한다. base가 RDB 포맷이라 순수 명령 로그보다 로딩이 빠르다.
  • 백업할 때 파일 하나만 챙기면 안 되고 디렉터리 전체를 떠야 한다는 뜻이기도 하다.

장단점

  • 장점
    • appendfsync 정책으로 내구성 수준을 고를 수 있다. 기본값에서도 유실이 1초로 제한된다.
    • append-only라 디스크 seek이 없고, 전원이 나가도 파일 중간이 깨질 일이 거의 없다. 끝이 잘려도 redis-check-aof로 고칠 수 있다.
    • 텍스트라 사람이 읽고 편집할 수 있다. FLUSHALL을 실수로 날렸어도 rewrite가 아직 안 일어났다면, 서버를 멈추고 마지막 줄을 지운 뒤 재시작해 복구할 수 있다.
  • 단점
    • 같은 데이터셋 기준 RDB보다 파일이 크다.
    • always로 두면 눈에 띄게 느려진다.

둘을 같이 쓰면

  • AOF와 RDB를 모두 켜는 것이 기본 권장 구성이다. PostgreSQL 수준의 데이터 안전성을 원한다면 그렇게 한다.
  • 재시작 시에는 AOF를 우선 로드한다. 더 완전한 상태를 담고 있다고 보장되기 때문이다.
  • AOF 단독은 권장되지 않는다. RDB 스냅샷은 백업·빠른 재시작·AOF 엔진 버그에 대한 보험 역할을 한다.
  • Redis는 RDB 스냅샷과 AOF rewrite가 동시에 돌지 않도록 조정한다. 무거운 디스크 I/O가 겹치는 것을 막기 위해서다.
RDBAOF
저장 단위시점 스냅샷쓰기 명령 로그
유실 범위마지막 스냅샷 이후 전부appendfsync에 따라 0~30초
파일 크기작다크다
재시작 속도빠르다상대적으로 느리다
백업 적합성높다 (단일 파일 복사)낮다 (디렉터리 + rewrite 고려)
성능 영향fork 순간 지연fsync 정책에 비례

운영 중 확인과 전환

  • 현재 상태 확인은 INFO persistence로 한다. 주요 필드는 다음과 같다.
    • rdb_last_save_time, rdb_last_bgsave_status: 마지막 스냅샷 시각과 성공 여부.
    • aof_enabled, aof_last_write_status, aof_last_bgrewrite_status: AOF 활성화 여부와 마지막 쓰기·rewrite 결과.
    • loading: 1이면 아직 디스크에서 읽어들이는 중이다.
  • 운영 중인 서버에 AOF를 켤 때는 절차를 지켜야 한다. 설정 파일만 고치고 재시작하면 데이터가 날아간다.
redis-cli config set appendonly yes
redis-cli config rewrite   # 설정 파일에 반영. 빠뜨리면 재시작 시 원복되어 유실된다
  • 재시작 전에 INFO persistence에서 aof_rewrite_in_progressaof_rewrite_scheduled가 0이고 aof_last_bgrewrite_statusok인지 확인한다.
  • stop-writes-on-bgsave-error yes(기본값)면 스냅샷이 실패한 뒤 Redis가 쓰기를 전부 거부한다. 디스크가 가득 찼을 때 갑자기 쓰기가 막히는 원인이 대개 이것이다.

지속성만으로 안 되는 경우

  • 클러스터·복제 환경에서는 지속성이 켜져 있어도 데이터가 사라질 수 있다. failover가 일어난 뒤 복귀한 옛 마스터는 replica로 강등되면서 디스크에서 복원한 데이터를 버리기 때문이다.
  • 자세한 내용은 Redis 클러스터 노드 재시작 시 데이터 유실 막기 참고.

참고 자료