영속성·백업 (Persistence/Backup)
영속성·백업 (Persistence/Backup)
원문: Redis persistence · Redis Open Source
영속성(persistence)은 데이터를 SSD 같은 영속 저장 장치에 기록하는 일을 말해요. Redis는 몇 가지 영속성 방식을 제공하는데, 크게 네 가지로 나눌 수 있어요.
- RDB (Redis Database): 지정한 간격마다 데이터셋의 특정 시점(point-in-time) 스냅샷을 찍는 방식이에요.
- AOF (Append Only File): 서버가 받은 모든 쓰기 작업을 로그로 남기는 방식이에요. 서버가 시작할 때 이 로그를 다시 재생하면 원래 데이터셋을 재구성할 수 있죠. 명령은 Redis 프로토콜과 같은 형식으로 기록돼요.
- 영속성 없음: 영속성을 완전히 끌 수도 있어요. 캐시 용도로 쓸 때 종종 선택하는 방식이에요.
- RDB + AOF: 같은 인스턴스에서 AOF와 RDB를 함께 쓸 수도 있어요.
이런 방식 사이의 트레이드오프를 직접 고민하고 싶지 않다면, Redis Software의 영속성 옵션을 살펴볼 수 있어요. UI로 미리 구성해 두거든요.
각 방식의 장단점을 어떻게 평가할지, 이어서 차근차근 살펴볼게요.
RDB의 장점
- RDB는 Redis 데이터를 하나의 아주 컴팩트한 파일로 특정 시점에 남겨요. 백업 용도로 최고죠. 예를 들어 매시간 스냅샷을 최근 24시간 동안, 매일 스냅샷을 30일 동안 보관하면, 재해가 나도 다양한 시점의 데이터셋을 쉽게 복원할 수 있어요.
- 단일 컴팩트 파일이라 먼 데이터 센터나 Amazon S3(암호화 가능)로 옮기기 좋아서, 재해 복구(disaster recovery)에 아주 유리해요.
- Redis 성능을 극대화해요. 영속화를 위해 부모 프로세스가 하는 일은 자식 프로세스를 fork 하는 게 전부고, 나머지는 자식이 처리하거든요. 부모 프로세스는 디스크 I/O를 하지 않아요.
- 큰 데이터셋일 때 AOF보다 재시작이 빨라요.
- 레플리카에서 RDB는 재시작·장애 조치 이후 부분 재동기화를 지원해요.
RDB의 단점
- Redis가 멈추는 경우(예: 정전) 데이터 손실 확률을 최소화해야 한다면 RDB는 좋지 않아요. RDB를 언제 만들지 세이브 포인트를 여러 개 설정할 수 있긴 해요(예: 5분 이상 + 데이터셋에 쓰기 100회 이상). 그래도 보통 5분 이상 간격으로 스냅샷을 만들기 때문에, 정상 종료 없이 Redis가 멈추면 마지막 몇 분짜리 데이터를 잃을 준비를 해야 해요.
- 디스크에 영속화하려면 자식 프로세스를 위해 자주
fork()를 호출해야 해요. 데이터셋이 크면fork()는 시간이 걸리고, 아주 큰 데이터셋에 CPU 성능이 좋지 않다면 수십 밀리초에서 1초까지 클라이언트 서비스가 멈출 수 있어요. AOF도fork()가 필요하지만 덜 자주 하면 되고, 내구성과의 트레이드오프 없이 로그를 얼마나 자주 리라이트할지 조절할 수 있어요.
AOF의 장점
- AOF를 쓰면 Redis가 훨씬 더 내구적이에요.
fsync정책을 다양하게 정할 수 있거든요: 아예 안 하기, 1초마다, 쿼리마다. 기본 정책인 1초마다로도 쓰기 성능은 여전히 좋아요.fsync는 백그라운드 스레드가 수행하고, 메인 스레드는 fsync가 진행 중이지 않을 때 쓰기를 열심히 수행하므로, 잃을 수 있는 건 1초 분량의 쓰기뿐이에요. - AOF 로그는 append-only(추가 전용)라 탐색(seek)이 없고, 정전이 나도 손상 문제가 없어요. 로그 끝에 반쯤 쓰인 명령이 남아 있어도(디스크가 꽉 차는 등)
redis-check-aof도구가 쉽게 고쳐줘요. - AOF가 너무 커지면 Redis가 백그라운드에서 자동으로 리라이트해요. 리라이트는 완전히 안전해요. Redis가 기존 파일에 계속 추가하는 동안 최소한의 연산으로 현재 데이터셋을 만들 수 있는 새 파일이 만들어지고, 준비되면 두 파일을 교체하고 새 파일에 추가하기 시작하거든요.
- AOF에는 모든 연산이 차례로 기록돼서 이해하고 파싱하기 쉬운 형식이에요. 파일도 쉽게 내보낼 수 있고요. 예를 들어
FLUSHALL로 실수로 데이터를 다 날렸어도, 그 사이에 리라이트가 일어나지만 않았다면 서버를 멈추고 마지막 명령을 지운 뒤 다시 시작해서 데이터를 살릴 수 있어요.
AOF의 단점
- 보통 같은 데이터셋의 RDB 파일보다 AOF 파일이 더 커요.
fsync정책에 따라 RDB보다 느릴 수 있어요. 1초마다로 하면 성능이 여전히 높고,fsync를 끄면 높은 부하에서도 RDB만큼 빨라요. 그래도 엄청난 쓰기 부하가 있을 때 최대 지연 시간에 대한 보장은 RDB가 더 잘해줘요.
Redis < 7.0 에서는 또 다른 단점이 있었어요.
- 리라이트 중에 데이터베이스로 쓰기가 들어오면 메모리를 많이 쓸 수 있어요(쓰기를 메모리에 버퍼했다가 마지막에 새 AOF에 쓰거든요).
- 리라이트 중 도착한 모든 쓰기 명령이 디스크에 두 번 쓰여요.
- 리라이트가 끝날 때 Redis가 이 쓰기 명령들을 새 AOF 파일에 쓰고 fsync하는 동안 얼어붙을 수 있었어요.
그럼 뭘 써야 할까요?
PostgreSQL이 주는 정도의 데이터 안전성을 원한다면 두 방식(AOF + RDB)을 함께 쓰는 게 일반적인 권장 사항이에요.
데이터를 신경 쓰긴 하지만 재해 때 몇 분의 손실은 감수할 수 있다면 RDB만 써도 충분해요.
AOF만 쓰는 사용자도 많지만, 그건 권하지 않아요. RDB 스냅샷을 가끔 찍어 두면 데이터베이스 백업, 더 빠른 재시작, 그리고 AOF 엔진의 버그 상황에서 아주 좋은 안전망이 되거든요.
이제 두 영속성 모델의 세부 사항을 조금 더 살펴볼게요.
스냅샷 (Snapshotting)
기본적으로 Redis는 데이터셋 스냅샷을 dump.rdb라는 바이너리 파일로 디스크에 저장해요. N초마다 데이터셋에 M개 이상의 변경이 있으면 저장하도록 설정할 수도 있고, SAVE나 BGSAVE 명령으로 수동으로 저장할 수도 있어요.
예를 들어 이 설정은 키 1000개가 변경되면 60초마다 데이터셋을 자동으로 디스크에 덤프하게 해요.
save 60 1000
이 전략을 스냅샷이라고 불러요.
동작 원리
Redis가 데이터셋을 디스크에 덤프해야 할 때는 이렇게 동작해요.
- Redis가 fork()를 호출해요. 이제 자식 프로세스와 부모 프로세스로 나뉘어요.
- 자식 프로세스가 데이터셋을 임시 RDB 파일에 쓰기 시작해요.
- 자식 프로세스가 새 RDB 파일을 다 쓰면, 기존 파일을 새 파일로 교체해요.
이 방식 덕분에 Redis는 copy-on-write(쓰기 시 복사) 시맨틱의 이점을 누릴 수 있어요.
Append-only file
스냅샷은 크게 내구적이지 않아요. Redis를 실행 중인 컴퓨터가 멈추거나, 전원이 나가거나, 실수로 kill -9를 하면 Redis에 쓴 최신 데이터가 유실돼요. 어떤 애플리케이션에선 큰 문제가 아닐 수 있지만, 완전한 내구성이 필요한 경우도 있어요. 그럴 때는 스냅샷만으로는 부족하죠.
append-only file(AOF)은 Redis를 위한 대안적인, 완전히 내구적인 전략이에요. 버전 1.1부터 사용할 수 있어요.
설정 파일에서 AOF를 켤 수 있어요.
appendonly yes
이제부터 Redis가 데이터셋을 변경하는 명령(예: SET)을 받을 때마다 그 명령을 AOF에 추가해요. Redis를 재시작하면 AOF를 다시 재생해서 상태를 재구성해요.
Redis 7.0.0부터는 다중 파트 AOF(multi part AOF) 메커니즘을 써요. 원래 단일 AOF 파일이 base 파일(최대 1개) 과 incremental 파일(여러 개 가능) 로 나뉘는데, base 파일은 AOF가 리라이트될 때 존재하는 데이터의 초기(RDB 또는 AOF 형식) 스냅샷이고, incremental 파일은 마지막 base 파일이 만들어진 이후의 증분 변경을 담아요. 이 파일들은 별도 디렉터리에 모이고, manifest 파일이 관리해요.
로그 리라이트
쓰기 연산이 수행될수록 AOF는 점점 커져요. 예를 들어 카운터를 100번 증가시키면 데이터셋에는 최종 값을 담은 키 하나만 남지만, AOF에는 100개의 엔트리가 쌓여요. 그중 99개는 현재 상태를 재구성하는 데 필요하지 않아요.
리라이트는 완전히 안전해요. Redis가 기존 파일에 계속 추가하는 동안, 현재 데이터셋을 만드는 데 필요한 최소한의 연산으로 완전히 새로운 파일이 만들어져요. 준비되면 두 파일을 교체하고 새 파일에 추가하기 시작해요.
Redis에는 재미있는 기능이 있어요. 클라이언트 서비스를 중단하지 않고 백그라운드에서 AOF를 재구성할 수 있거든요. BGREWRITEAOF를 실행하면 Redis가 현재 인메모리 데이터셋을 재구성하는 데 필요한 최단 명령 시퀀스를 작성해요. Redis 2.2에서 AOF를 쓴다면 BGREWRITEAOF를 수시로 실행해야 하는데, 2.4부터는 로그 리라이트를 자동으로 트리거해요(예시 설정 파일 참고).
Redis 7.0.0부터, AOF 리라이트가 예약되면 Redis 부모 프로세스가 새 incremental AOF 파일을 열어 계속 쓰고, 자식 프로세스는 리라이트 로직을 실행해서 새 base AOF를 생성해요. Redis는 임시 manifest 파일로 새로 생성된 base 파일과 incremental 파일을 추적하다가, 준비되면 원자적(atomic) 교체 연산으로 이 임시 manifest 파일을 적용해요. 반복되는 실패·재시도 때문에 incremental 파일이 너무 많이 생기는 문제를 막으려고, Redis는 AOF 리라이트 제한 메커니즘을 도입해서 실패한 리라이트가 점점 더 느린 간격으로 재시도되게 해요.
append only file은 얼마나 내구적인가?
Redis가 데이터를 디스크에 fsync하는 횟수를 설정할 수 있어요. 세 가지 옵션이 있어요.
appendfsync always: 새 명령이 AOF에 추가될 때마다fsync. 아주 아주 느리지만 아주 안전해요. 명령은 여러 클라이언트·파이프라인의 명령 배치가 실행된 뒤 AOF에 추가되므로, (응답을 보내기 전에) 단일 쓰기 + 단일 fsync라는 점을 알아두세요.appendfsync everysec: 1초마다fsync. 충분히 빨라요(2.4부터는 스냅샷만큼 빠를 가능성이 높아요). 재해가 나면 1초 분량의 데이터를 잃을 수 있어요.appendfsync no: 절대fsync하지 않아요. 데이터를 운영체제에 맡겨요. 가장 빠르고 덜 안전한 방식이에요. 보통 Linux는 이 설정에서 데이터를 30초마다 flush하지만, 커널의 정확한 튜닝에 달려 있어요.
권장(그리고 기본) 정책은 1초마다 fsync하는 거예요. 빠르면서도 비교적 안전해요. always 정책은 실제로 아주 느리지만 그룹 커밋(group commit)을 지원해서, 병렬 쓰기가 여러 개일 때 Redis가 단일 fsync 연산을 수행하려고 해요.
AOF가 잘려나갔다면(truncated) 어떻게 해야 하나?
서버가 AOF 파일을 쓰다가 크래시했거나, AOF 파일을 저장한 볼륨이 쓰는 순간 가득 찼을 수 있어요. 이 경우에도 AOF에는 특정 시점 버전의 데이터셋(기본 AOF fsync 정책에서 최대 1초 오래된)을 나타내는 일관된 데이터가 남아 있지만, AOF의 마지막 명령이 잘려나갔을 수 있어요. 최신 주요 버전의 Redis는 어쨌든 AOF를 로드할 수 있는데, 파일에서 마지막의 제대로 형성되지 않은 명령만 버려요. 이 경우 서버는 다음과 같은 로그를 출력해요.
* Reading RDB preamble from AOF file...
* Reading the remaining AOF tail...
# !!! Warning: short read while loading the AOF file !!!
# !!! Truncating the AOF at offset 439 !!!
# AOF loaded anyway because aof-load-truncated is enabled
원한다면 설정을 바꿔 이런 경우 Redis가 멈추도록 강제할 수도 있어요. 하지만 기본 설정은 마지막 명령이 제대로 형성되지 않았어도 계속 진행하는 방식이에요. 재시작 후 가용성(availability)을 보장하기 위해서죠.
이전 버전의 Redis는 복구하지 못할 수 있는데, 그때는 다음 단계를 따라야 해요.
- AOF 파일의 백업 사본을 만들어요.
- Redis와 함께 제공되는
redis-check-aof도구로 원본 파일을 고쳐요.
$ redis-check-aof --fix <filename>
- 선택적으로
diff -u로 두 파일의 차이를 확인해요. - 고친 파일로 서버를 재시작해요.
AOF가 손상됐다면(corrupted) 어떻게 해야 하나?
AOF 파일이 잘려나간 게 아니라 중간에 잘못된 바이트 시퀀스로 손상됐다면 상황이 더 복잡해요. Redis는 시작할 때 불평하며 중단해요.
* Reading the remaining AOF tail...
# Bad file format reading the append only file: make a backup of your AOF file, then use ./redis-check-aof --fix <filename>
가장 좋은 방법은 처음에는 --fix 옵션 없이 redis-check-aof 유틸리티를 실행해서 문제를 이해하고, 파일에서 주어진 오프셋으로 이동해 직접 수리할 수 있는지 보는 거예요. AOF는 Redis 프로토콜과 같은 형식이라 수동으로 고치기 꽤 간단해요. 아니면 유틸리티가 파일을 고쳐주도록 할 수 있지만, 그 경우 손상된 부분부터 파일 끝까지 AOF 전체가 버려질 수 있어요. 손상이 파일 초반부에서 발생했다면 엄청난 양의 데이터 손실로 이어질 수 있죠.
동작 원리
로그 리라이트는 스냅샷에서 쓰던 것과 같은 copy-on-write 기법을 써요. 이렇게 동작해요.
Redis >= 7.0
- Redis가 fork()를 호출해요. 이제 자식과 부모 프로세스로 나뉘어요.
- 자식 프로세스가 임시 파일에 새 base AOF를 쓰기 시작해요.
- 부모 프로세스는 새 incremental AOF 파일을 열어 갱신을 계속 써요. 리라이트가 실패하면 기존 base·increment 파일(있으면)과 이 새로 연 increment 파일이 완전한 갱신 데이터셋을 나타내므로 안전해요.
- 자식 프로세스가 base 파일 리라이트를 끝내면 부모 프로세스가 신호를 받아, 새로 연 increment 파일과 자식이 생성한 base 파일로 임시 manifest를 만들어 저장해요.
- 이제 Redis가 manifest 파일을 원자적으로 교환해서 AOF 리라이트 결과가 적용돼요. 이전 base 파일과 쓰지 않는 increment 파일도 정리해요.
Redis < 7.0
- Redis가 fork()를 호출해요. 이제 자식과 부모 프로세스로 나뉘어요.
- 자식 프로세스가 임시 파일에 새 AOF를 쓰기 시작해요.
- 부모 프로세스는 모든 새 변경을 인메모리 버퍼에 모아요(동시에 기존 append-only 파일에도 새 변경을 쓰므로, 리라이트가 실패해도 안전해요).
- 자식 프로세스가 파일 리라이트를 끝내면 부모 프로세스가 신호를 받아 인메모리 버퍼를 자식이 생성한 파일 끝에 추가해요.
- 이제 Redis가 새 파일을 기존 파일로 원자적으로 rename하고, 새 파일에 새 데이터를 추가하기 시작해요.
지금 dump.rdb 스냅샷을 쓰고 있는데 AOF로 전환하려면?
현재 RDB 스냅샷을 쓰는 서버에서 AOF를 활성화하고 싶다면, 먼저 실행 중인 서버에서 CONFIG 명령으로 AOF를 활성화해 데이터를 변환해야 해요.
중요: 이 절차를 따르지 않고(예: 설정만 바꾸고 서버를 재시작) 하면 데이터 손실이 발생할 수 있어요!
Redis >= 2.2
준비:
- 최신
dump.rdb파일의 백업을 만들어요. - 이 백업을 안전한 곳으로 옮겨요.
실행 중인 데이터베이스에서 AOF로 전환:
- AOF 활성화:
redis-cli config set appendonly yes - 선택적으로 RDB 비활성화:
redis-cli config set save "" - 쓰기가 append only file에 올바르게 추가되는지 확인해요.
- 중요:
redis.conf를 갱신하고(CONFIG REWRITE로 가능) 위 설정과 일치하는지 확인해요. 이 단계를 잊으면 서버 재시작 때 설정 변경이 사라지고 서버가 기존 설정으로 다시 시작되어 데이터가 손실돼요.
다음에 서버를 재시작할 때:
- 재시작 전에 AOF 리라이트가 데이터 영속화를 마칠 때까지 기다려요.
INFO persistence를 보면서aof_rewrite_in_progress와aof_rewrite_scheduled가0이 되고aof_last_bgrewrite_status가ok인지 확인하면 돼요. - 재시작 후 데이터베이스가 이전과 같은 수의 키를 포함하는지 확인해요.
Redis 2.0
- 최신
dump.rdb파일의 백업을 만들어요. - 이 백업을 안전한 곳으로 옮겨요.
- 데이터베이스에 대한 모든 쓰기를 중단해요!
redis-cli BGREWRITEAOF를 실행해요. 그러면 append only file이 생성돼요.- Redis가 AOF 덤프 생성을 마치면 서버를 멈춰요.
redis.conf를 편집해 append only file 영속성을 활성화해요.- 서버를 재시작해요.
- 데이터베이스가 전환 전과 같은 수의 키를 포함하는지 확인해요.
- 쓰기가 append only file에 올바르게 추가되는지 확인해요.
AOF와 RDB 영속성의 상호작용
Redis >= 2.4는 RDB 스냅샷 작업이 이미 진행 중일 때 AOF 리라이트가 트리거되는 것을 막고, AOF 리라이트가 진행 중일 때 BGSAVE가 실행되는 것을 막아요. 이렇게 하면 두 Redis 백그라운드 프로세스가 동시에 무거운 디스크 I/O를 하는 것을 방지할 수 있어요.
스냅샷이 진행 중인데 사용자가 BGREWRITEAOF로 로그 리라이트를 명시적으로 요청하면, 서버는 작업이 예약되었다는 OK 상태 코드로 응답하고, 스냅샷이 끝나면 리라이트를 시작해요.
AOF와 RDB 영속성을 모두 활성화한 경우 Redis가 재시작하면 AOF 파일로 원본 데이터셋을 재구성해요. AOF가 가장 완전하다고 보장되기 때문이에요.
Redis 데이터 백업하기
이 섹션을 시작하기 전에 이 문장을 꼭 읽어주세요: 데이터베이스를 반드시 백업하세요. 디스크는 깨지고, 클라우드의 인스턴스는 사라지고 합니다. 백업이 없으면 데이터가 /dev/null로 사라질 위험이 커요.
Redis는 데이터 백업에 정말 친화적이에요. 데이터베이스가 실행 중에도 RDB 파일을 복사할 수 있거든요. RDB는 한 번 생성되면 절대 수정되지 않고, 생성되는 동안에는 임시 이름을 쓰다가 새 스냅샷이 완성됐을 때만 rename(2)으로 최종 목적지로 원자적으로 이름을 바꿔요.
즉, 서버가 실행 중이어도 RDB 파일을 복사하는 것은 완전히 안전해요. 이렇게 하는 걸 권장해요.
- 서버에 cron 작업을 만들어 한 디렉터리에 RDB 파일의 시간별 스냅샷을, 다른 디렉터리에 일별 스냅샷을 만들어요.
- cron 스크립트가 실행될 때마다
find명령을 호출해 너무 오래된 스냅샷을 삭제해요. 예를 들어 시간별 스냅샷은 최근 48시간, 일별 스냅샷은 1~2개월치를 보관할 수 있어요. 스냅샷 이름에는 날짜와 시간 정보를 담도록 해요. - 하루에 한 번 이상은 RDB 스냅샷을 데이터 센터 밖, 또는 적어도 Redis 인스턴스를 실행하는 물리 머신 밖으로 옮겨요.
AOF 영속성 백업하기
AOF 영속성만 활성화한 Redis 인스턴스도 백업할 수 있어요. Redis 7.0.0부터 AOF 파일은 appenddirname 설정이 결정하는 단일 디렉터리에 있는 여러 파일로 나뉘어요. 정상 운영 중에는 이 디렉터리의 파일을 복사하거나 tar하면 그게 백업이 돼요. 하지만 리라이트 도중에 하면 잘못된 백업이 될 수 있어요. 그걸 피하려면 백업 중에는 AOF 리라이트를 꺼야 해요.
- 자동 리라이트를 꺼요.
CONFIG SET auto-aof-rewrite-percentage 0. 이 시간 동안BGREWRITEAOF로 수동으로 리라이트를 시작하지 않아야 해요. - 진행 중인 리라이트가 없는지
INFO persistence로 확인하고aof_rewrite_in_progress가 0인지 확인해요. 1이면 리라이트가 끝날 때까지 기다려야 해요. - 이제
appenddirname디렉터리의 파일을 안전하게 복사할 수 있어요. - 끝나면 리라이트를 다시 켜요.
CONFIG SET auto-aof-rewrite-percentage <이전 값>.
참고: AOF 리라이트가 꺼진 시간을 최소화하고 싶다면 (위 3단계에서) appenddirname의 파일에 하드 링크를 만들고, 하드 링크를 만든 뒤 (4단계에서) 리라이트를 다시 켜면 돼요. 이제 하드 링크를 복사하거나 tar한 뒤 끝나면 지우면 돼요. Redis가 이 디렉터리의 파일에 추가만 하거나, 필요한 경우 완전히 교체하는 것만 보장하므로, 내용은 어느 시점에서든 일관되기 때문이에요.
참고: 백업 중에 서버가 재시작되는 경우를 대비해, 재시작 후 자동 리라이트가 시작되지 않게 하려면 1단계를 바꿔 갱신된 설정을 CONFIG REWRITE로 영속화하면 돼요. 끝나면 (4단계에서) 자동 리라이트를 다시 켜고, 또 한 번 CONFIG REWRITE로 영속화하세요.
7.0.0 이전에는 AOF 파일을 복사하는 것만으로 백업할 수 있었어요(RDB 스냅샷 백업처럼요). 파일의 마지막 부분이 없어도 Redis가 로드할 수 있었죠(앞의 잘린 AOF 파일 섹션 참고).
BACKUP 명령군으로 하는 온라인 백업
Redis 8.10.0부터 BACKUP 명령군은 쓰기를 멈추거나 AOF 리라이트를 수동으로 관리하지 않고도 자족적(self-contained)이고 복원 가능한 백업을 만들어요. 백업은 다중 파트 AOF 형식을 재사용하므로, 세 파일로 구성된 MP-AOF 호환 아티팩트 세트예요.
- BASE — 특정 시점 스냅샷(
appendonly.aof.N.base.rdb). - INCR — 스냅샷 이후에 추가된 증분 쓰기(
appendonly.aof.N.incr.aof). - Manifest — 파일 세트를 설명하는 독립형 manifest(
appendonly.aof.manifest).
백업 생성이 백업 확정과 분리되어 있으므로, 컨트롤 플레인이 클러스터의 노드들에서 BACKUP START를 시차를 두고 실행해 모두 동시에 fork하지 않게 만들 수 있어요. 각 노드는 BASE를 독립적으로 만들고 INCR에 계속 추가하다가 나중에 BACKUP SEAL로 고정돼요. 복원은 BASE + INCR을 로드하므로, 복원된 데이터셋은 단지 이전 BASE 스냅샷이 아니라 seal 경계 시점의 상태를 반영해요.
노드에서의 전형적인 워크플로는 이래요.
BACKUP START— 백업 윈도우를 열고 새 BASE 스냅샷을 만들어요. AOF 영속성이 활성화되어 있든 없든 동작해요.BACKUP LIST— 지금까지 고정된 불변 파일의 절대 경로를 얻어요. Redis가 INCR 데이터를 계속 쌓는 동안 데이터 플레인은 BASE 파일 복사를 시작할 수 있어요.BACKUP SEAL— 백업을 고정하고, INCR을 하드 링크하고 manifest를 써요. Seal 후에는BACKUP LIST에 INCR과 manifest 파일도 포함돼요.BACKUP LIST가 보고한 seal된 파일들을 백업 저장소로 복사해요.BACKUP CLEANUP— 복사가 끝난 뒤 seal된 파일을 제거하고 고정된 아티팩트를 해제해요.
아무 때나 BACKUP STATUS로 현재 백업 상태를 확인하고, 아직 seal되지 않은 백업은 BACKUP ABORT로 취소할 수 있어요.
백업 파일은 backupdirname 설정(기본값 backupdir)이 이름 짓는 디렉터리에, Redis 작업 디렉터리 dir 아래에서 결정된 경로에 기록돼요. backupdirname은 시작 시에만 설정할 수 있어요. backup-sealed-ttl 설정은 Redis가 seal된 백업을 자동 정리하기 전에 몇 초 동안 보관할지를 정하며, 0(기본값)이면 자동 정리가 비활성화되어 BACKUP CLEANUP이 호출될 때까지 파일이 고정 상태로 남아요.
백업 복원하기
백업을 복원하려면 시작 시에만 설정되는 preload-file 설정을 사용해요. 서버 시작 중에 특정 파일이나 manifest를 로드하죠. <type>:<path> 형식으로 지정하며, <type>은 aof 또는 rdb예요. seal된 백업을 복원하려면 manifest를 가리키면 돼요.
preload-file aof:/tmp/restore-backup/appendonly.aof.manifest
단일 RDB 파일도 프리로드할 수 있어요.
preload-file rdb:/tmp/backup-to-recover.rdb
preload-file이 설정되면 Redis는 지정된 파일이나 manifest와 그 연관 파일만 로드해요. AOF나 RDB 영속성이 활성화되어 있어도 일반적인 appenddirname과 dump.rdb 로딩은 건너뛰어요. 프리로드 대상이 없거나 로드할 수 없으면 시작이 중단돼요. 프리로드가 끝나면 Redis는 정상적으로 구성된 영속성 모드를 이어가요.
재해 복구 (Disaster recovery)
Redis 맥락에서 재해 복구는 기본적으로 백업과 같은 이야기에, 그 백업을 여러 외부 데이터 센터로 옮길 수 있는 능력이 더해진 거예요. 이렇게 하면 Redis가 실행되고 스냅샷을 만드는 주 데이터 센터에 치명적인 사건이 발생해도 데이터가 보호돼요.
비용이 너무 높지 않으면서 가장 흥미로운 재해 복구 기법 몇 가지를 살펴볼게요.
- Amazon S3 같은 서비스는 재해 복구 시스템을 구현하기 좋아요. 일별 또는 시간별 RDB 스냅샷을 암호화된 형태로 S3로 옮기면 돼요.
gpg -c(대칭 암호화 모드)로 데이터를 암호화할 수 있어요. 비밀번호는 여러 안전한 곳에 보관하세요(예: 조직의 핵심 인물들에게 사본을 나눠주기). 데이터 안전성을 높이려면 여러 스토리지 서비스를 함께 쓰는 게 권장돼요. - SCP(SSH의 일부)로 스냅샷을 먼 서버로 옮겨요. 꽤 간단하고 안전한 방법이에요. 나와 아주 먼 곳에 작은 VPS를 두고, ssh를 설치하고, 암호 없는 ssh 클라이언트 키를 만든 뒤 작은 VPS의
authorized_keys파일에 추가하면 자동으로 백업을 전송할 준비가 돼요. 최상의 결과를 위해 서로 다른 두 제공업체의 VPS를 최소한 두 개 두세요.
이 시스템은 제대로 구현하지 않으면 쉽게 실패할 수 있다는 점을 이해하는 게 중요해요. 최소한, 전송이 끝난 뒤 파일 크기(복사한 파일의 크기와 일치해야 해요) 와 VPS를 쓴다면 SHA1 다이제스트까지 확인할 수 있어야 해요.
또한 새 백업 전송이 어떤 이유로든 작동하지 않을 때를 대비해 독립적인 경보 시스템도 필요해요.